Skip to content

Commit 42ec510

Browse files
keegan-carusoKeegan Caruso
andauthored
Onboard to code coverage in ADO (#2798)
* Onboard to code coverage * Test stability improvements * Update test script for code coverage --------- Co-authored-by: Keegan Caruso <keegancaruso@microsoft.com>
1 parent ff63778 commit 42ec510

8 files changed

Lines changed: 74 additions & 26 deletions

File tree

azurepipelines-coverage.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
coverage:
2+
status: # Code coverage status will be posted to pull requests based on targets defined below.
3+
comments: on # Off by default. When on, details about coverage for each file changed will be posted as a pull request comment.
4+
diff: # diff coverage is code coverage only for the lines changed in a pull request.
5+
target: 75% # set this to a desired %.

build/CodeCoverage.runsettings

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,17 @@
77
<RunSettings>
88
<DataCollectionRunSettings>
99
<DataCollectors>
10-
<DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0" assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
10+
<DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0">
1111
<Configuration>
12+
<Format>Cobertura</Format>
1213
<CodeCoverage>
1314

14-
<!--
15-
About include/exclude lists:
16-
Empty "Include" clauses imply all; empty "Exclude" clauses imply none.
17-
Each element in the list is a regular expression (ECMAScript syntax). See http://msdn.microsoft.com/library/2k3te2cs.aspx.
18-
An item must first match at least one entry in the include list to be included.
19-
Included items must then not match any entries in the exclude list to remain included.
15+
<!--
16+
About include/exclude lists:
17+
Empty "Include" clauses imply all; empty "Exclude" clauses imply none.
18+
Each element in the list is a regular expression (ECMAScript syntax). See http://msdn.microsoft.com/library/2k3te2cs.aspx.
19+
An item must first match at least one entry in the include list to be included.
20+
Included items must then not match any entries in the exclude list to remain included.
2021
-->
2122

2223
<!-- Match assembly file paths: -->
@@ -40,7 +41,17 @@ Included items must then not match any entries in the exclude list to remain inc
4041
<ModulePath>.*\system.identitymodel.tokens.jwt.dll</ModulePath>
4142
</Include>
4243
</ModulePaths>
43-
44+
<Attributes>
45+
<Exclude>
46+
<Attribute>^System\.Diagnostics\.CodeAnalysis\.ExcludeFromCodeCoverageAttribute$</Attribute>
47+
<Attribute>^System\.CodeDom\.Compiler\.GeneratedCodeAttribute$</Attribute>
48+
</Exclude>
49+
</Attributes>
50+
<Sources>
51+
<Exclude>
52+
<Source>.*\.g\.cs$</Source>
53+
</Exclude>
54+
</Sources>
4455
</CodeCoverage>
4556
</Configuration>
4657
</DataCollector>

build/dependenciesTest.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<BannedApiAnalyzersVersion>3.3.4</BannedApiAnalyzersVersion>
44
<DotNetCoreAppRuntimeVersion>2.1.30</DotNetCoreAppRuntimeVersion>
55
<MicrosoftAzureKeyVaultCryptographyVersion>2.0.5</MicrosoftAzureKeyVaultCryptographyVersion>
6-
<MicrosoftNETTestSdkVersion>16.10.0</MicrosoftNETTestSdkVersion>
6+
<MicrosoftNETTestSdkVersion>17.11.0</MicrosoftNETTestSdkVersion>
77
<NetStandardVersion>2.0.3</NetStandardVersion>
88
<NewtonsoftVersion>13.0.3</NewtonsoftVersion>
99
<SystemSecurityClaimsVersion>4.3.0</SystemSecurityClaimsVersion>

build/template-Build-run-tests-sign.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,19 @@ steps:
6868
inputs:
6969
targetType: filePath
7070
filePath: ./$(WilsonSourceDirectory)runTests.ps1
71-
arguments: '-buildType $(BuildConfiguration)'
71+
arguments: '-buildType $(BuildConfiguration) -runningInCI $True'
72+
73+
- task: PublishTestResults@2
74+
condition: succeededOrFailed()
75+
inputs:
76+
testResultsFormat: 'XUnit'
77+
testResultsFiles: '**/*.trx'
78+
searchFolder: '$(Agent.TempDirectory)'
79+
80+
- task: PublishCodeCoverageResults@2
81+
condition: succeededOrFailed()
82+
inputs:
83+
summaryFileLocation: '$(Agent.TempDirectory)/**/*.cobertura.xml'
7284

7385
- task: CopyFiles@2
7486
displayName: 'Copy Files to: [staging]\ProductBinaries'
@@ -174,7 +186,7 @@ steps:
174186
- task: securedevelopmentteam.vss-secure-development-tools.build-task-uploadtotsa.TSAUpload@2
175187
displayName: 'TSA upload to Codebase: WILSON Stamp: Azure'
176188
inputs:
177-
GdnPublishTsaOnboard: false
189+
GdnPublishTsaOnboard: false
178190
GdnPublishTsaConfigFile: '$(Build.SourcesDirectory)/build/tsaConfig.json'
179191
continueOnError: true
180192
condition: and(succeeded(), eq(variables['PipelineType'], 'legacy'))

runTests.ps1

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
param([string]$buildType="Debug", [string]$dotnetDir="c:\Program Files\dotnet", [string]$root=$PSScriptRoot, [string]$failBuildOnTest="YES")
1+
param(
2+
[string]$buildType="Debug",
3+
[string]$dotnetDir="c:\Program Files\dotnet",
4+
[string]$root=$PSScriptRoot,
5+
[string]$failBuildOnTest="YES",
6+
[bool]$runningInCI=$false)
27

38
################################################# Functions ############################################################
49

@@ -31,7 +36,9 @@ Write-Host "dotnetDir: " $dotnetDir
3136
Write-Host "root: " $root;
3237
Write-Host "failBuildOnTest: " $failBuildOnTest;
3338
Write-Host "slnFile: " $slnFile;
39+
Write-Host "runningInCI: " $runningInCI;
3440

41+
$runSettingsPath = $PSScriptRoot + "\build\CodeCoverage.runsettings"
3542
[xml]$buildConfiguration = Get-Content $PSScriptRoot\buildConfiguration.xml
3643
$dotnetexe = "$dotnetDir\dotnet.exe";
3744
$startTime = Get-Date
@@ -41,6 +48,13 @@ Write-Host "dotnetexe: " $dotnetexe;
4148

4249
$ErrorActionPreference = "Stop"
4350

51+
$tempToUse = $env:TEMP;
52+
53+
if ($runningInCI) {
54+
# Temp dir used in ADO
55+
$tempToUse = "C:\__w\_temp";
56+
}
57+
4458
$testProjects = $buildConfiguration.SelectNodes("root/projects/test/project")
4559
foreach ($testProject in $testProjects)
4660
{
@@ -50,10 +64,10 @@ foreach ($testProject in $testProjects)
5064

5165
$name = $testProject.name;
5266
Write-Host ">>> Set-Location $root\test\$name"
53-
pushd
67+
Push-Location
5468
Set-Location $root\test\$name
55-
Write-Host ">>> Start-Process -Wait -PassThru -NoNewWindow $dotnetexe 'test $name.csproj' --filter category!=nonwindowstests --no-build --no-restore -nodereuse:false -v n -c $buildType"
56-
$p = Start-Process -Wait -PassThru -NoNewWindow $dotnetexe "test $name.csproj --filter category!=nonwindowstests --no-build --no-restore -nodereuse:false -v n -c $buildType"
69+
Write-Host ">>> Start-Process -Wait -PassThru -NoNewWindow $dotnetexe 'test $name.csproj' --filter category!=nonwindowstests --no-build --no-restore -nodereuse:false -v n -c $buildType --collect ""Code Coverage"" --settings ""$runSettingsPath"" --logger trx --results-directory ""$tempToUse"""
70+
$p = Start-Process -Wait -PassThru -NoNewWindow $dotnetexe "test $name.csproj --filter category!=nonwindowstests --no-build --no-restore -nodereuse:false -v n -c $buildType --collect ""Code Coverage"" --settings ""$runSettingsPath"" --logger trx --results-directory ""$tempToUse"""
5771

5872
if($p.ExitCode -ne 0)
5973
{
@@ -68,7 +82,7 @@ foreach ($testProject in $testProjects)
6882
}
6983
$testExitCode = $p.ExitCode + $testExitCode
7084

71-
popd
85+
Pop-Location
7286

7387
WriteSectionFooter("End Test");
7488
}

test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTests.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,11 +384,12 @@ public async Task RequestRefresh(ConfigurationManagerTheoryData<OpenIdConnectCon
384384
configuration = await theoryData.ConfigurationManager.GetConfigurationAsync(CancellationToken.None);
385385
}
386386

387-
theoryData.ConfigurationManager.RefreshInterval = theoryData.RefreshInterval;
388-
theoryData.ConfigurationManager.MetadataAddress = theoryData.UpdatedMetadataAddress;
389387
if (theoryData.SleepTimeInMs > 0)
390388
Thread.Sleep(theoryData.SleepTimeInMs);
391389

390+
theoryData.ConfigurationManager.RefreshInterval = theoryData.RefreshInterval;
391+
theoryData.ConfigurationManager.MetadataAddress = theoryData.UpdatedMetadataAddress;
392+
392393
theoryData.ConfigurationManager.RequestRefresh();
393394

394395
if (theoryData.SleepTimeInMs > 0)
@@ -433,6 +434,7 @@ public static TheoryData<ConfigurationManagerTheoryData<OpenIdConnectConfigurati
433434
ExpectedUpdatedConfiguration = OpenIdConfigData.AADCommonV1Config,
434435
RefreshInterval = TimeSpan.MaxValue,
435436
RequestRefresh = true,
437+
SleepTimeInMs = 1000,
436438
UpdatedMetadataAddress = "AADCommonV2Json"
437439
});
438440

test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,9 @@
77
using System.Globalization;
88
using System.IO;
99
using System.Reflection;
10-
using System.Security.Cryptography;
1110
using System.Text;
12-
using System.Text.Json;
1311
using Microsoft.IdentityModel.TestUtils;
1412
using Microsoft.IdentityModel.Tokens;
15-
using Newtonsoft.Json;
1613
using Xunit;
1714

1815
namespace Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests

test/Microsoft.IdentityModel.Protocols.Tests/ExtensibilityTests.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,23 @@ public async Task ConfigurationManagerUsingCustomClass()
8383
configuration = await configManager.GetConfigurationAsync();
8484
TestUtilities.SetField(configManager, "_lastRequestRefresh", DateTimeOffset.UtcNow - TimeSpan.FromHours(1));
8585
configManager.MetadataAddress = "IssuerMetadata2.json";
86-
configManager.RequestRefresh();
8786

8887
// Wait for the refresh to complete.
89-
await Task.Delay(250).ContinueWith(_ =>
88+
await Task.Delay(500);
89+
90+
for (int i = 0; i < 5; i++)
9091
{
91-
configuration2 = configManager.GetConfigurationAsync().GetAwaiter().GetResult();
92-
});
92+
configManager.RequestRefresh();
93+
configuration2 = await configManager.GetConfigurationAsync();
94+
95+
if (IdentityComparer.AreEqual(configuration.Issuer, configuration2.Issuer))
96+
await Task.Delay(1000);
97+
else
98+
break;
99+
}
93100

94101
if (IdentityComparer.AreEqual(configuration.Issuer, configuration2.Issuer))
95-
context.Diffs.Add("IdentityComparer.AreEqual(configuration.Issuer, configuration2.Issuer)");
102+
context.Diffs.Add($"Expected: {configuration.Issuer}, to be different from: {configuration2.Issuer}");
96103

97104
TestUtilities.AssertFailIfErrors(context);
98105
}

0 commit comments

Comments
 (0)