Skip to content

Commit d353415

Browse files
authored
Merge pull request #1831 from nunit/issue-1829
Add support for NUnit V2 ResultWriter extension
2 parents ff4f590 + 6b35153 commit d353415

5 files changed

Lines changed: 67 additions & 58 deletions

File tree

KnownExtensions.cake

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ public static class KnownExtensions
1111
public static ExtensionSpecifier VSProjectLoader = new ExtensionSpecifier(
1212
"NUnit.Extension.VSProjectLoader", "nunit-extension-vs-project-loader", "3.9.0");
1313
public static ExtensionSpecifier NUnitV2ResultWriter = new ExtensionSpecifier(
14-
"NUnit.Extension.NUnitV2ResultWriter", "nunit-extension-nunit-v2-result-writer", "4.0.0-beta.1");
14+
"NUnit.Extension.NUnitV2ResultWriter", "nunit-extension-nunit-v2-result-writer", "4.0.0-dev.14");
15+
public static ExtensionSpecifier TeamCityEventListener = new ExtensionSpecifier(
16+
"NUnit.Extension.TeamCityEventListener", "nunit-extension-teamcity-event-listener", "1.0.9");
1517
public static ExtensionSpecifier Net462PluggableAgent = new ExtensionSpecifier(
1618
"NUnit.Extension.Net462PluggableAgent", "nunit-extension-net462-pluggable-agent", "4.1.0-alpha.5");
1719
public static ExtensionSpecifier Net80PluggableAgent = new ExtensionSpecifier(

build.cake

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Load the recipe
2-
#load nuget:?package=NUnit.Cake.Recipe&version=2.0.0-dev100
2+
#load nuget:?package=NUnit.Cake.Recipe&version=2.0.0-beta.1
33
// Comment out above line and uncomment below for local tests of recipe changes
4-
//#load ../NUnit.Cake.Recipe/recipe/*.cs
54
//#load ../NUnit.Cake.Recipe/recipe/*.cake
65

76
// Load additional cake files

package-tests.cake

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,6 @@ void AddToBothLists(PackageTest test)
1111
NetCoreRunnerTests.Add(test);
1212
}
1313

14-
public static class Extensions
15-
{
16-
// Extensions used in tests, with version specified.
17-
public static ExtensionSpecifier NUnitV2Driver = new ExtensionSpecifier(
18-
"NUnit.Extension.NUnitV2Driver", "nunit-extension-nunit-v2-driver", "3.9.0");
19-
public static ExtensionSpecifier NUnitProjectLoader = new ExtensionSpecifier(
20-
"NUnit.Extension.NUnitProjectLoader", "nunit-extension-nunit-project-loader", "3.8.0");
21-
public static ExtensionSpecifier VSProjectLoader = new ExtensionSpecifier(
22-
"NUnit.Extension.VSProjectLoader", "nunit-extension-vs-project-loader", "3.9.0");
23-
public static ExtensionSpecifier NUnitV2ResultWriter = new ExtensionSpecifier(
24-
"NUnit.Extension.NUnitV2ResultWriter", "nunit-extension-nunit-v2-result-writer", "3.8.0");
25-
public static ExtensionSpecifier TeamCityEventListener = new ExtensionSpecifier(
26-
"NUnit.Extension.TeamCityEventListener", "nunit-extension-teamcity-event-listener", "1.0.9");
27-
}
28-
2914
//////////////////////////////////////////////////////////////////////
3015
// RUN MOCK-ASSEMBLY UNDER EACH RUNTIME
3116
//////////////////////////////////////////////////////////////////////
@@ -423,10 +408,18 @@ StandardRunnerTests.Add(new PackageTest(1, "ExtensionsInstalledFromAddedDirector
423408
NetCoreRunnerTests.Add(new PackageTest(1, "ExtensionsInstalledFromAddedDirectory")
424409
{
425410
Description = "List Extensions shows extension from added directory",
426-
Arguments = "--extensionDirectory fakes/netstandard2.0 --list-extensions --trace:Debug",
411+
Arguments = "--extensionDirectory fakes/netstandard2.0 --list-extensions",
427412
ExpectedOutput = new[] { Contains("Extension:", exactly: 5) }
428413
});
429414

415+
AddToBothLists(new PackageTest(1, "SpecificExtensionInstalled")
416+
{
417+
Description = "List Extensions shows V2ResultWriter if we include it as needed",
418+
Arguments = "--list-extensions",
419+
ExpectedOutput = new[] { Contains("nunit-v2-result-writer.dll", exactly: 1) },
420+
ExtensionsNeeded = new[] { KnownExtensions.NUnitV2ResultWriter }
421+
});
422+
430423
//////////////////////////////////////////////////////////////////////
431424
// TEST OF ASSEMBLY RESOLUTION STATISTICS
432425
//////////////////////////////////////////////////////////////////////
@@ -518,22 +511,24 @@ NetCoreRunnerTests.Add(new PackageTest(1, "ListResolutionStatistics_Run")
518511
// ExtensionsNeeded = new[] { Extensions.NUnitProjectLoader }
519512
//});
520513

521-
//// V2 Result Writer Test
522-
//StandardRunnerTests.Add(new PackageTest(1, "V2ResultWriterTest_Net462")
523-
//{
524-
// Description = "Run mock-assembly under .NET 4.6.2 and produce V2 output",
525-
// Arguments = "testdata/net462/mock-assembly.dll --result=TestResult.xml --result=NUnit2TestResult.xml;format=nunit2",
526-
// ExpectedResult = new MockAssemblyExpectedResult("net-4.6.2"),
527-
// ExtensionsNeeded = new[] { Extensions.NUnitV2ResultWriter }
528-
//});
514+
// V2 Result Writer Tests
515+
StandardRunnerTests.Add(new PackageTest(1, "V2ResultWriterTest_Net462")
516+
{
517+
Description = "Run mock-assembly under .NET 4.6.2 and produce V2 output",
518+
Arguments = "testdata/net462/mock-assembly.dll --result=TestResult.xml --result=NUnit2TestResult.xml;format=nunit2",
519+
ExpectedResult = new MockAssemblyExpectedResult("net-4.6.2"),
520+
// TODO: Check that V2 result file was created
521+
ExtensionsNeeded = new[] { KnownExtensions.NUnitV2ResultWriter }
522+
});
529523

530-
//StandardRunnerTests.Add(new PackageTest(1, "V2ResultWriterTest_Net60")
531-
//{
532-
// Description = "Run mock-assembly under .NET 6.0 and produce V2 output",
533-
// Arguments = "testdata/net6.0/mock-assembly.dll --result=TestResult.xml --result=NUnit2TestResult.xml;format=nunit2",
534-
// ExpectedResult = new MockAssemblyExpectedResult("netcore-6.0"),
535-
// ExtensionsNeeded = new[] { Extensions.NUnitV2ResultWriter }
536-
//});
524+
AddToBothLists(new PackageTest(1, "V2ResultWriterTest_Net60")
525+
{
526+
Description = "Run mock-assembly under .NET 6.0 and produce V2 output",
527+
Arguments = "testdata/net6.0/mock-assembly.dll --result=TestResult.xml --result=NUnit2TestResult.xml;format=nunit2",
528+
ExpectedResult = new MockAssemblyExpectedResult("netcore-6.0"),
529+
// TODO: Check that V2 result file was created
530+
ExtensionsNeeded = new[] { KnownExtensions.NUnitV2ResultWriter }
531+
});
537532

538533
//// VS Project Loader Tests
539534
//StandardRunnerTests.Add(new PackageTest(1, "VSProjectLoaderTest_Project")
@@ -578,7 +573,7 @@ StandardRunnerTests.Add(new PackageTest(1, "TeamCityListenerTest")
578573
Description = "Run mock-assembly with --teamcity enabled",
579574
Arguments = "testdata/net462/mock-assembly.dll --enable NUnit.Engine.Listeners.TeamCityEventListener",
580575
ExpectedResult = new MockAssemblyExpectedResult("net-4.6.2"),
581-
ExtensionsNeeded = new[] { Extensions.TeamCityEventListener }
576+
ExtensionsNeeded = new[] { KnownExtensions.TeamCityEventListener }
582577
});
583578

584579
//// V2 Framework Driver Tests

src/NUnitConsole/nunit4-console/ConsoleRunner.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,6 @@ public ConsoleRunner(ITestEngine engine, ConsoleOptions options, ExtendedTextWri
6868
Guard.ArgumentNotNull(_outWriter = writer);
6969

7070
// NOTE: Accessing Services triggers the engine to initialize all services
71-
_resultService = _engine.Services.GetService<IResultService>();
72-
Guard.OperationValid(_resultService is not null, "Internal Error: ResultService was not found");
73-
74-
_filterService = _engine.Services.GetService<ITestFilterService>();
75-
Guard.OperationValid(_filterService is not null, "Internal Error: TestFilterService was not found");
76-
7771
_extensionService = _engine.Services.GetService<IExtensionService>();
7872
Guard.OperationValid(_extensionService is not null, "Internal Error: ExtensionService was not found");
7973

@@ -87,6 +81,12 @@ public ConsoleRunner(ITestEngine engine, ConsoleOptions options, ExtendedTextWri
8781

8882
_extensionService.InstallExtensions();
8983

84+
_resultService = _engine.Services.GetService<IResultService>();
85+
Guard.OperationValid(_resultService is not null, "Internal Error: ResultService was not found");
86+
87+
_filterService = _engine.Services.GetService<ITestFilterService>();
88+
Guard.OperationValid(_filterService is not null, "Internal Error: TestFilterService was not found");
89+
9090
_workDirectory = options.WorkDirectory ?? Directory.GetCurrentDirectory();
9191

9292
if (!Directory.Exists(_workDirectory))

src/NUnitEngine/nunit.engine/Services/ResultService.cs

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ public class ResultService : Service, IResultService
1313
private static readonly Logger log = InternalTrace.GetLogger(typeof(ResultService));
1414

1515
private readonly string[] BUILT_IN_FORMATS = new string[] { "nunit3", "cases", "user" };
16-
private List<ExtensionNode> _extensionNodes = new List<ExtensionNode>();
1716

17+
private ExtensionService? _extensionService;
1818
private string[]? _formats;
1919

2020
[MemberNotNull(nameof(_formats))]
@@ -24,12 +24,13 @@ public string[] Formats
2424
{
2525
if (_formats is null)
2626
{
27+
Guard.OperationValid(_extensionService is not null, "Formats property may not be accessed before ResultService is started");
28+
2729
var formatList = new List<string>(BUILT_IN_FORMATS);
2830

29-
if (_extensionNodes is not null)
30-
foreach (var node in _extensionNodes)
31-
foreach (var format in node.GetValues("Format"))
32-
formatList.Add(format);
31+
foreach (var node in WriterNodes)
32+
foreach (var format in node.GetValues("Format"))
33+
formatList.Add(format);
3334

3435
_formats = formatList.ToArray();
3536
}
@@ -61,14 +62,13 @@ public IResultWriter GetResultWriter(string format, params object?[]? args)
6162
return new XmlTransformResultWriter(args!);
6263

6364
default:
64-
if (_extensionNodes is not null)
65-
foreach (var node in _extensionNodes)
66-
foreach (var supported in node.GetValues("Format"))
67-
if (supported == format && node.ExtensionObject is not null)
68-
{
69-
log.Debug($" Returning {node.TypeName}");
70-
return (IResultWriter)node.ExtensionObject;
71-
}
65+
foreach (var node in WriterNodes)
66+
foreach (var supported in node.GetValues("Format"))
67+
if (supported == format && node.ExtensionObject is not null)
68+
{
69+
log.Debug($" Returning {node.TypeName}");
70+
return (IResultWriter)node.ExtensionObject;
71+
}
7272

7373
throw new NUnitEngineException("ResultWriter not found for format: " + format);
7474
}
@@ -80,10 +80,7 @@ public override void StartService()
8080

8181
try
8282
{
83-
var extensionService = ServiceContext.GetService<ExtensionService>();
84-
85-
if (extensionService is not null && extensionService.Status == ServiceStatus.Started)
86-
_extensionNodes.AddRange(extensionService.GetExtensionNodes<IResultWriter>());
83+
_extensionService = ServiceContext.GetService<ExtensionService>();
8784

8885
// If there is no extension service, we start anyway using built-in writers
8986
Status = ServiceStatus.Started;
@@ -94,5 +91,21 @@ public override void StartService()
9491
throw;
9592
}
9693
}
94+
95+
private List<ExtensionNode>? _writerNodes;
96+
private List<ExtensionNode> WriterNodes
97+
{
98+
get
99+
{
100+
if (_writerNodes is null)
101+
{
102+
Guard.OperationValid(_extensionService is not null, "WriterNodes property may not be accessed before ResultService is started");
103+
104+
_writerNodes = [.. _extensionService.GetExtensionNodes<IResultWriter>()];
105+
}
106+
107+
return _writerNodes;
108+
}
109+
}
97110
}
98111
}

0 commit comments

Comments
 (0)