Skip to content

Commit b72fb2a

Browse files
authored
Migrate tests from MSTest to xUnit and clean up test infrastructure (#193)
Test Framework Migration (MSTest → xUnit) Replaced MSTest with xUnit (v2.9.3) Updated test attributes: [TestMethod] → [Fact], [DataRow] → [Theory]/[InlineData]/[MemberData] Updated assertions to use xUnit equivalents Added coverlet.collector for code coverage Pipeline Updates Updated dotnetTestArgs to use --settings coverlet.runsettings --collect:"XPlat Code Coverage" Added coverlet.runsettings file to configure coverage output format (cobertura,opencover) for ADO pipeline compatibility Added PublishCodeCoverageResults@2 task via postTest parameter to publish code coverage results to Azure DevOps Code Cleanup Fixed indentation issues in test files Removed obsolete MSTest-specific configurations
1 parent 6688e2d commit b72fb2a

32 files changed

Lines changed: 774 additions & 922 deletions

Directory.Build.props

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,5 @@
77
</PackageReference>
88
</ItemGroup>
99

10-
<!-- MSTest config -->
11-
<PropertyGroup>
12-
<EnableMSTestRunner>true</EnableMSTestRunner>
13-
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
14-
<MSTestAnalysisMode>Recommended</MSTestAnalysisMode>
15-
</PropertyGroup>
10+
1611
</Project>

Pipelines/recursive-extractor-pr.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,16 @@ extends:
4242
poolName: MSSecurity-1ES-Build-Agents-Pool
4343
poolImage: MSSecurity-1ES-Windows-2022
4444
poolOs: windows
45-
dotnetTestArgs: '-- --coverage --report-trx'
45+
dotnetTestArgs: '--settings coverlet.runsettings --collect:"XPlat Code Coverage"'
4646
includeNuGetOrg: false
4747
nugetFeedsToUse: 'config'
4848
nugetConfigPath: 'nuget.config'
4949
onInit:
5050
- task: NuGetAuthenticate@1
51+
postTest:
52+
- task: PublishCodeCoverageResults@2
53+
inputs:
54+
summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml'
5155

5256
- template: dotnet-test-job.yml@templates
5357
parameters:
@@ -57,12 +61,16 @@ extends:
5761
poolName: MSSecurity-1ES-Build-Agents-Pool
5862
poolImage: MSSecurity-1ES-Windows-2022
5963
poolOs: windows
60-
dotnetTestArgs: '-- --coverage --report-trx'
64+
dotnetTestArgs: '--settings coverlet.runsettings --collect:"XPlat Code Coverage"'
6165
includeNuGetOrg: false
6266
nugetFeedsToUse: 'config'
6367
nugetConfigPath: 'nuget.config'
6468
onInit:
6569
- task: NuGetAuthenticate@1
70+
postTest:
71+
- task: PublishCodeCoverageResults@2
72+
inputs:
73+
summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml'
6674

6775
- stage: Build
6876
dependsOn:

Pipelines/recursive-extractor-release.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,16 @@ extends:
4343
poolName: MSSecurity-1ES-Build-Agents-Pool
4444
poolImage: MSSecurity-1ES-Windows-2022
4545
poolOs: windows
46-
dotnetTestArgs: '-- --coverage --report-trx'
46+
dotnetTestArgs: '--settings coverlet.runsettings --collect:"XPlat Code Coverage"'
4747
includeNuGetOrg: false
4848
nugetFeedsToUse: 'config'
4949
nugetConfigPath: 'nuget.config'
5050
onInit:
5151
- task: NuGetAuthenticate@1
52+
postTest:
53+
- task: PublishCodeCoverageResults@2
54+
inputs:
55+
summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml'
5256
- template: dotnet-test-job.yml@templates
5357
parameters:
5458
jobName: 'cli_dotnet_test_windows'
@@ -57,12 +61,16 @@ extends:
5761
poolName: MSSecurity-1ES-Build-Agents-Pool
5862
poolImage: MSSecurity-1ES-Windows-2022
5963
poolOs: windows
60-
dotnetTestArgs: '-- --coverage --report-trx'
64+
dotnetTestArgs: '--settings coverlet.runsettings --collect:"XPlat Code Coverage"'
6165
includeNuGetOrg: false
6266
nugetFeedsToUse: 'config'
6367
nugetConfigPath: 'nuget.config'
6468
onInit:
6569
- task: NuGetAuthenticate@1
70+
postTest:
71+
- task: PublishCodeCoverageResults@2
72+
inputs:
73+
summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml'
6674

6775
- stage: Build
6876
dependsOn:

RecursiveExtractor.Cli.Tests/CliTests/CliTests.cs

Lines changed: 62 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,40 @@
33
using Microsoft.CST.RecursiveExtractor;
44
using Microsoft.CST.RecursiveExtractor.Cli;
55
using Microsoft.CST.RecursiveExtractor.Tests;
6-
using Microsoft.VisualStudio.TestTools.UnitTesting;
76
using RecursiveExtractor.Tests.ExtractorTests;
87
using System;
98
using System.IO;
109
using System.Linq;
1110
using System.Threading;
11+
using Xunit;
1212

1313
namespace RecursiveExtractor.Tests.CliTests
1414
{
15-
[TestClass]
16-
public class CliTests : BaseExtractorTestClass
15+
public class CliTests : IClassFixture<BaseExtractorTestClass>
1716
{
18-
[DataTestMethod]
19-
[DataRow("TestData.zip", 5)]
20-
[DataRow("TestData.7z")]
21-
[DataRow("TestData.tar", 6)]
22-
[DataRow("TestData.rar")]
23-
[DataRow("TestData.rar4")]
24-
[DataRow("TestData.tar.bz2", 6)]
25-
[DataRow("TestData.tar.gz", 6)]
26-
[DataRow("TestData.tar.xz")]
27-
[DataRow("sysvbanner_1.0-17fakesync1_amd64.deb", 8)]
28-
[DataRow("TestData.a")]
29-
[DataRow("TestData.bsd.ar")]
30-
[DataRow("TestData.iso")]
31-
[DataRow("TestData.vhdx")]
32-
[DataRow("TestData.wim")]
33-
[DataRow("EmptyFile.txt", 1)]
34-
[DataRow("TestDataArchivesNested.Zip", 54)]
17+
[Theory]
18+
[InlineData("TestData.zip", 5)]
19+
[InlineData("TestData.7z")]
20+
[InlineData("TestData.tar", 6)]
21+
[InlineData("TestData.rar")]
22+
[InlineData("TestData.rar4")]
23+
[InlineData("TestData.tar.bz2", 6)]
24+
[InlineData("TestData.tar.gz", 6)]
25+
[InlineData("TestData.tar.xz")]
26+
[InlineData("sysvbanner_1.0-17fakesync1_amd64.deb", 8)]
27+
[InlineData("TestData.a")]
28+
[InlineData("TestData.bsd.ar")]
29+
[InlineData("TestData.iso")]
30+
[InlineData("TestData.vhdx")]
31+
[InlineData("TestData.wim")]
32+
[InlineData("EmptyFile.txt", 1)]
33+
[InlineData("TestDataArchivesNested.Zip", 54)]
3534
public void ExtractArchiveParallel(string fileName, int expectedNumFiles = 3)
3635
{
37-
ExtractArchive(fileName, expectedNumFiles, false);
36+
CliTests.ExtractArchive(fileName, expectedNumFiles, false);
3837
}
3938

40-
internal void ExtractArchive(string fileName, int expectedNumFiles, bool singleThread)
39+
internal static void ExtractArchive(string fileName, int expectedNumFiles, bool singleThread)
4140
{
4241
var directory = TestPathHelpers.GetFreshTestDirectory();
4342
var path = Path.Combine(Directory.GetCurrentDirectory(), "TestData", "TestDataArchives", fileName);
@@ -46,35 +45,35 @@ internal void ExtractArchive(string fileName, int expectedNumFiles, bool singleT
4645
Thread.Sleep(100);
4746
if (Directory.Exists(directory))
4847
{
49-
files = Directory.EnumerateFiles(directory, "*.*", SearchOption.AllDirectories).ToArray();
48+
files = [.. Directory.EnumerateFiles(directory, "*.*", SearchOption.AllDirectories)];
5049
}
51-
Assert.AreEqual(expectedNumFiles, files.Length);
50+
Assert.Equal(expectedNumFiles, files.Length);
5251
}
5352

54-
[DataTestMethod]
55-
[DataRow("TestData.zip", 5)]
56-
[DataRow("TestData.7z")]
57-
[DataRow("TestData.tar", 6)]
58-
[DataRow("TestData.rar")]
59-
[DataRow("TestData.rar4")]
60-
[DataRow("TestData.tar.bz2", 6)]
61-
[DataRow("TestData.tar.gz", 6)]
62-
[DataRow("TestData.tar.xz")]
63-
[DataRow("sysvbanner_1.0-17fakesync1_amd64.deb", 8)]
64-
[DataRow("TestData.a")]
65-
[DataRow("TestData.bsd.ar")]
66-
[DataRow("TestData.iso")]
67-
[DataRow("TestData.vhdx")]
68-
[DataRow("TestData.wim")]
69-
[DataRow("EmptyFile.txt", 1)]
70-
[DataRow("TestDataArchivesNested.Zip", 54)]
53+
[Theory]
54+
[InlineData("TestData.zip", 5)]
55+
[InlineData("TestData.7z")]
56+
[InlineData("TestData.tar", 6)]
57+
[InlineData("TestData.rar")]
58+
[InlineData("TestData.rar4")]
59+
[InlineData("TestData.tar.bz2", 6)]
60+
[InlineData("TestData.tar.gz", 6)]
61+
[InlineData("TestData.tar.xz")]
62+
[InlineData("sysvbanner_1.0-17fakesync1_amd64.deb", 8)]
63+
[InlineData("TestData.a")]
64+
[InlineData("TestData.bsd.ar")]
65+
[InlineData("TestData.iso")]
66+
[InlineData("TestData.vhdx")]
67+
[InlineData("TestData.wim")]
68+
[InlineData("EmptyFile.txt", 1)]
69+
[InlineData("TestDataArchivesNested.Zip", 54)]
7170
public void ExtractArchiveSingleThread(string fileName, int expectedNumFiles = 3)
7271
{
73-
ExtractArchive(fileName, expectedNumFiles, true);
72+
CliTests.ExtractArchive(fileName, expectedNumFiles, true);
7473
}
7574

76-
[DataTestMethod]
77-
[DataRow("TestDataForFilters.7z")]
75+
[Theory]
76+
[InlineData("TestDataForFilters.7z")]
7877
public void ExtractArchiveWithAllowFilters(string fileName, int expectedNumFiles = 1)
7978
{
8079
var directory = TestPathHelpers.GetFreshTestDirectory();
@@ -86,21 +85,21 @@ public void ExtractArchiveWithAllowFilters(string fileName, int expectedNumFiles
8685
Input = newpath,
8786
Output = directory,
8887
Verbose = true,
89-
AllowFilters = new string[]
90-
{
88+
AllowFilters =
89+
[
9190
"*.cs"
92-
}
91+
]
9392
});
9493
var files = Array.Empty<string>();
9594
if (Directory.Exists(directory))
9695
{
97-
files = Directory.EnumerateFiles(directory, "*.*", SearchOption.AllDirectories).ToArray();
96+
files = [.. Directory.EnumerateFiles(directory, "*.*", SearchOption.AllDirectories)];
9897
}
99-
Assert.AreEqual(expectedNumFiles, files.Length);
98+
Assert.Equal(expectedNumFiles, files.Length);
10099
}
101100

102-
[DataTestMethod]
103-
[DataRow("TestDataForFilters.7z")]
101+
[Theory]
102+
[InlineData("TestDataForFilters.7z")]
104103
public void ExtractArchiveWithDenyFilters(string fileName, int expectedNumFiles = 2)
105104
{
106105
var directory = TestPathHelpers.GetFreshTestDirectory();
@@ -112,33 +111,31 @@ public void ExtractArchiveWithDenyFilters(string fileName, int expectedNumFiles
112111
Input = newpath,
113112
Output = directory,
114113
Verbose = true,
115-
DenyFilters = new string[]
116-
{
114+
DenyFilters =
115+
[
117116
"*.cs"
118-
}
117+
]
119118
});
120119
var files = Array.Empty<string>();
121120
if (Directory.Exists(directory))
122121
{
123-
files = Directory.EnumerateFiles(directory, "*.*", SearchOption.AllDirectories).ToArray();
122+
files = [.. Directory.EnumerateFiles(directory, "*.*", SearchOption.AllDirectories)];
124123
}
125-
Assert.AreEqual(expectedNumFiles, files.Length);
124+
Assert.Equal(expectedNumFiles, files.Length);
126125
}
127126

128-
[DataTestMethod]
129-
[DataRow("TestDataEncrypted.7z")]
130-
[DataRow("TestDataEncryptedAes.zip")]
131-
[DataRow("TestDataEncrypted.rar4")]
127+
[Theory]
128+
[InlineData("TestDataEncrypted.7z")]
129+
[InlineData("TestDataEncryptedAes.zip")]
130+
[InlineData("TestDataEncrypted.rar4")]
132131
public void ExtractEncryptedArchive(string fileName, int expectedNumFiles = 3)
133132
{
134133
var directory = TestPathHelpers.GetFreshTestDirectory();
135134
var path = Path.Combine(Directory.GetCurrentDirectory(), "TestData", "TestDataArchives", fileName);
136135
var passwords = EncryptedArchiveTests.TestArchivePasswords.Values.SelectMany(x => x);
137136
RecursiveExtractorClient.ExtractCommand(new ExtractCommandOptions() { Input = path, Output = directory, Verbose = true, Passwords = passwords });
138-
string[] files = Directory.EnumerateFiles(directory, "*.*", SearchOption.AllDirectories).ToArray();
139-
Assert.AreEqual(expectedNumFiles, files.Length);
140-
}
141-
142-
protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
137+
string[] files = [.. Directory.EnumerateFiles(directory, "*.*", SearchOption.AllDirectories)];
138+
Assert.Equal(expectedNumFiles, files.Length);
139+
}
143140
}
144141
}

RecursiveExtractor.Cli.Tests/RecursiveExtractor.Cli.Tests.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
<Nullable>enable</Nullable>
77

88
<IsPackable>false</IsPackable>
9-
<OutputType>Exe</OutputType>
109
</PropertyGroup>
1110

1211
<ItemGroup>
13-
<PackageReference Include="Microsoft.Testing.Extensions.CodeCoverage" Version="17.14.2" />
14-
<PackageReference Include="Microsoft.Testing.Extensions.TrxReport" Version="1.8.4" />
15-
<PackageReference Include="MSTest" Version="3.10.4" />
12+
<PackageReference Include="xunit" Version="2.9.3" />
13+
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2" />
14+
<PackageReference Include="coverlet.collector" Version="6.0.4" />
15+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
1616
</ItemGroup>
1717

1818
<ItemGroup>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
global using Microsoft.VisualStudio.TestTools.UnitTesting;
1+
global using Xunit;
22

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
using Xunit;
2+
3+
[assembly: CollectionBehavior(DisableTestParallelization = false)]
Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
using Microsoft.CST.RecursiveExtractor.Tests;
2-
using Microsoft.VisualStudio.TestTools.UnitTesting;
32
using NLog;
43
using NLog.Config;
54
using NLog.Targets;
5+
using System;
66

77
namespace RecursiveExtractor.Tests.ExtractorTests;
88

9-
public class BaseExtractorTestClass
9+
/// <summary>
10+
/// XUnit test fixture class for extractor tests. Sets up logging and test directories. Tests should use this class as a fixture via IClassFixture&lt;BaseExtractorTestClass&gt; to get the benefits of the setup and teardown.
11+
/// </summary>
12+
public class BaseExtractorTestClass : IDisposable
1013
{
11-
[ClassCleanup]
12-
public static void ClassCleanup()
13-
{
14-
TestPathHelpers.DeleteTestDirectory();
15-
}
14+
protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
1615

17-
[ClassInitialize]
18-
public static void ClassInitialize(TestContext context)
16+
static BaseExtractorTestClass()
1917
{
2018
var config = new LoggingConfiguration();
2119
var consoleTarget = new ConsoleTarget
@@ -27,5 +25,11 @@ public static void ClassInitialize(TestContext context)
2725

2826
LogManager.Configuration = config;
2927
}
30-
protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
28+
29+
/// <inheritdoc />
30+
public void Dispose()
31+
{
32+
TestPathHelpers.DeleteTestDirectory();
33+
GC.SuppressFinalize(this);
34+
}
3135
}

0 commit comments

Comments
 (0)