Skip to content

Commit 1f96bc0

Browse files
committed
WIP
1 parent 2adfabc commit 1f96bc0

File tree

11 files changed

+276
-115
lines changed

11 files changed

+276
-115
lines changed

NUnitConsole.sln

+7-7
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "nunit.extensibility", "src\
154154
EndProject
155155
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "nunit.extensibility.tests", "src\NUnitCommon\nunit.extensibility.tests\nunit.extensibility.tests.csproj", "{B22FEE5B-83D4-4021-B066-1B958332D391}"
156156
EndProject
157-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FakeExtensions", "src\NUnitCommon\FakeExtensions\FakeExtensions.csproj", "{E2A4C099-E35D-4E27-B89D-957140ED970F}"
158-
EndProject
159157
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "nunit.common", "src\NUnitCommon\nunit.common\nunit.common.csproj", "{9D9CAD66-8EDF-4ED0-A222-503BE9B21EC7}"
160158
EndProject
161159
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "nunit.common.tests", "src\NUnitCommon\nunit.common.tests\nunit.common.tests.csproj", "{6605DA54-EBF4-4ED1-B5BC-B607AD0CE308}"
@@ -164,6 +162,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "nunit.agent.core", "src\NUn
164162
EndProject
165163
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "nunit.agent.core.tests", "src\NUnitCommon\nunit.agent.core.tests\nunit.agent.core.tests.csproj", "{89258A3E-5B62-487A-9AE7-D7672CBF61F1}"
166164
EndProject
165+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FakeExtensions", "src\TestData\FakeExtensions\FakeExtensions.csproj", "{608AA86D-4090-33CA-0031-BD324E5A766E}"
166+
EndProject
167167
Global
168168
GlobalSection(SolutionConfigurationPlatforms) = preSolution
169169
Debug|Any CPU = Debug|Any CPU
@@ -270,10 +270,6 @@ Global
270270
{B22FEE5B-83D4-4021-B066-1B958332D391}.Debug|Any CPU.Build.0 = Debug|Any CPU
271271
{B22FEE5B-83D4-4021-B066-1B958332D391}.Release|Any CPU.ActiveCfg = Release|Any CPU
272272
{B22FEE5B-83D4-4021-B066-1B958332D391}.Release|Any CPU.Build.0 = Release|Any CPU
273-
{E2A4C099-E35D-4E27-B89D-957140ED970F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
274-
{E2A4C099-E35D-4E27-B89D-957140ED970F}.Debug|Any CPU.Build.0 = Debug|Any CPU
275-
{E2A4C099-E35D-4E27-B89D-957140ED970F}.Release|Any CPU.ActiveCfg = Release|Any CPU
276-
{E2A4C099-E35D-4E27-B89D-957140ED970F}.Release|Any CPU.Build.0 = Release|Any CPU
277273
{9D9CAD66-8EDF-4ED0-A222-503BE9B21EC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
278274
{9D9CAD66-8EDF-4ED0-A222-503BE9B21EC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
279275
{9D9CAD66-8EDF-4ED0-A222-503BE9B21EC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -290,6 +286,10 @@ Global
290286
{89258A3E-5B62-487A-9AE7-D7672CBF61F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
291287
{89258A3E-5B62-487A-9AE7-D7672CBF61F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
292288
{89258A3E-5B62-487A-9AE7-D7672CBF61F1}.Release|Any CPU.Build.0 = Release|Any CPU
289+
{608AA86D-4090-33CA-0031-BD324E5A766E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
290+
{608AA86D-4090-33CA-0031-BD324E5A766E}.Debug|Any CPU.Build.0 = Debug|Any CPU
291+
{608AA86D-4090-33CA-0031-BD324E5A766E}.Release|Any CPU.ActiveCfg = Release|Any CPU
292+
{608AA86D-4090-33CA-0031-BD324E5A766E}.Release|Any CPU.Build.0 = Release|Any CPU
293293
EndGlobalSection
294294
GlobalSection(SolutionProperties) = preSolution
295295
HideSolutionNode = FALSE
@@ -331,11 +331,11 @@ Global
331331
{71DE0F2C-C72B-4CBF-99BE-F2DC0FBEDA24} = {3B30D2E5-1587-4D68-B848-1BDDB3C24BFC}
332332
{49E8B583-37C2-4166-8007-3DB780D01004} = {3B30D2E5-1587-4D68-B848-1BDDB3C24BFC}
333333
{B22FEE5B-83D4-4021-B066-1B958332D391} = {3B30D2E5-1587-4D68-B848-1BDDB3C24BFC}
334-
{E2A4C099-E35D-4E27-B89D-957140ED970F} = {3B30D2E5-1587-4D68-B848-1BDDB3C24BFC}
335334
{9D9CAD66-8EDF-4ED0-A222-503BE9B21EC7} = {3B30D2E5-1587-4D68-B848-1BDDB3C24BFC}
336335
{6605DA54-EBF4-4ED1-B5BC-B607AD0CE308} = {3B30D2E5-1587-4D68-B848-1BDDB3C24BFC}
337336
{4FCFAF1C-1579-4A1C-BAF9-9627E39D7CDA} = {3B30D2E5-1587-4D68-B848-1BDDB3C24BFC}
338337
{89258A3E-5B62-487A-9AE7-D7672CBF61F1} = {3B30D2E5-1587-4D68-B848-1BDDB3C24BFC}
338+
{608AA86D-4090-33CA-0031-BD324E5A766E} = {37D508B2-91E0-4B32-869B-DFF9E68EA213}
339339
EndGlobalSection
340340
GlobalSection(ExtensibilityGlobals) = postSolution
341341
SolutionGuid = {D8E4FC26-5422-4C51-8BBC-D1AC0A578711}

global.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"sdk": {
3-
"version": "8.0.101",
3+
"version": "9.0.100",
44
"rollForward": "feature"
55
}
66
}

package-tests.cake

+26-8
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,24 @@ AddToBothLists(new PackageTest(1, "Net80WPFTest")
289289
ExpectedResult = new ExpectedResult("Passed") { Assemblies = new[] { new ExpectedAssemblyResult("WpfTest.dll", "netcore-8.0") } }
290290
});
291291

292+
//////////////////////////////////////////////////////////////////////
293+
// TESTS OF EXTENSION LISTING
294+
//////////////////////////////////////////////////////////////////////
295+
296+
AddToBothLists(new PackageTest(1, "NoExtensionsInstalled")
297+
{
298+
Description = "List Extensions shows none installed",
299+
Arguments = "--list-extensions",
300+
OutputCheck = new OutputDoesNotContain("Extension:"),
301+
});
302+
303+
AddToBothLists(new PackageTest(1, "ExtensionsInstalledFromAddedDirectory")
304+
{
305+
Description = "List Extensions shows extension from added directory",
306+
Arguments = "--extensionDirectory ../../src/TestData/FakeExtensions --list-extensions --trace:Debug",
307+
OutputCheck = new OutputContains("Extension:", exactly: 5)
308+
});
309+
292310
//////////////////////////////////////////////////////////////////////
293311
// RUN TESTS USING EACH OF OUR EXTENSIONS
294312
//////////////////////////////////////////////////////////////////////
@@ -313,14 +331,14 @@ AddToBothLists(new PackageTest(1, "Net80WPFTest")
313331
// ExtensionsNeeded = new[] { KnownExtensions.NUnitProjectLoader }
314332
//});
315333

316-
//// V2 Result Writer Test
317-
//StandardRunnerTests.Add(new PackageTest(1, "V2ResultWriterTest_Net462")
318-
//{
319-
// Description = "Run mock-assembly under .NET 4.6.2 and produce V2 output",
320-
// Arguments = "testdata/net462/mock-assembly.dll --result=TestResult.xml --result=NUnit2TestResult.xml;format=nunit2 --trace:Debug",
321-
// ExpectedResult = new MockAssemblyExpectedResult("net-4.6.2"),
322-
// ExtensionsNeeded = new[] { KnownExtensions.NUnitV2ResultWriter }
323-
//});
334+
// V2 Result Writer Test
335+
StandardRunnerTests.Add(new PackageTest(1, "V2ResultWriterTest_Net462")
336+
{
337+
Description = "Run mock-assembly under .NET 4.6.2 and produce V2 output",
338+
Arguments = "testdata/net462/mock-assembly.dll --result=TestResult.xml --result=NUnit2TestResult.xml;format=nunit2 --trace:Debug",
339+
ExpectedResult = new MockAssemblyExpectedResult("net-4.6.2"),
340+
ExtensionsNeeded = new[] { KnownExtensions.NUnitV2ResultWriter }
341+
});
324342

325343
//StandardRunnerTests.Add(new PackageTest(1, "V2ResultWriterTest_Net60")
326344
//{

src/NUnitCommon/nunit.extensibility.tests/ExtensionManagerTests.cs

+19-19
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,24 @@ public class ExtensionManagerTests
3434
typeof(IFrameworkDriver)
3535
};
3636

37-
private static readonly int[] KnownExtensionPointCounts = { 1, 1, 1, 2, 1, 1 };
37+
private static readonly int[] KnownExtensionPointCounts = { 1, 1, 1, 2, 1, 0 };
3838

39-
private const string DUMMY_FRAMEWORK_DRIVER_EXTENSION = "NUnit.Engine.Fakes.DummyFrameworkDriverExtension";
40-
private const string DUMMY_PROJECT_LOADER_EXTENSION = "NUnit.Engine.Fakes.DummyProjectLoaderExtension";
41-
private const string DUMMY_RESULT_WRITER_EXTENSION = "NUnit.Engine.Fakes.DummyResultWriterExtension";
42-
private const string DUMMY_EVENT_LISTENER_EXTENSION = "NUnit.Engine.Fakes.DummyEventListenerExtension";
43-
private const string DUMMY_SERVICE_EXTENSION = "NUnit.Engine.Fakes.DummyServiceExtension";
44-
private const string DUMMY_DISABLED_EXTENSION = "NUnit.Engine.Fakes.DummyDisabledExtension";
45-
private const string DUMMY_NUNIT_V2_DRIVER_EXTENSION = "NUnit.Engine.Fakes.V2DriverExtension";
39+
private const string FAKE_FRAMEWORK_DRIVER_EXTENSION = "NUnit.Engine.Fakes.FakeFrameworkDriverExtension";
40+
private const string FAKE_PROJECT_LOADER_EXTENSION = "NUnit.Engine.Fakes.FakeProjectLoaderExtension";
41+
private const string FAKE_RESULT_WRITER_EXTENSION = "NUnit.Engine.Fakes.FakeResultWriterExtension";
42+
private const string FAKE_EVENT_LISTENER_EXTENSION = "NUnit.Engine.Fakes.FakeEventListenerExtension";
43+
private const string FAKE_SERVICE_EXTENSION = "NUnit.Engine.Fakes.FakeServiceExtension";
44+
private const string FAKE_DISABLED_EXTENSION = "NUnit.Engine.Fakes.FakeDisabledExtension";
45+
private const string FAKE_NUNIT_V2_DRIVER_EXTENSION = "NUnit.Engine.Fakes.V2DriverExtension";
4646

4747
private readonly string[] KnownExtensions = {
48-
DUMMY_FRAMEWORK_DRIVER_EXTENSION,
49-
DUMMY_PROJECT_LOADER_EXTENSION,
50-
DUMMY_RESULT_WRITER_EXTENSION,
51-
DUMMY_EVENT_LISTENER_EXTENSION,
52-
DUMMY_SERVICE_EXTENSION,
53-
DUMMY_DISABLED_EXTENSION,
54-
DUMMY_NUNIT_V2_DRIVER_EXTENSION
48+
FAKE_FRAMEWORK_DRIVER_EXTENSION,
49+
FAKE_PROJECT_LOADER_EXTENSION,
50+
FAKE_RESULT_WRITER_EXTENSION,
51+
FAKE_EVENT_LISTENER_EXTENSION,
52+
FAKE_SERVICE_EXTENSION,
53+
FAKE_DISABLED_EXTENSION
54+
//FAKE_NUNIT_V2_DRIVER_EXTENSION
5555
};
5656
#pragma warning restore 414
5757

@@ -90,7 +90,7 @@ public void AllKnownExtensionsAreEnabledAsRequired()
9090
{
9191
foreach (var node in _extensionManager.Extensions)
9292
{
93-
var shouldBeEnabled = node.TypeName != DUMMY_DISABLED_EXTENSION;
93+
var shouldBeEnabled = node.TypeName != FAKE_DISABLED_EXTENSION;
9494
Assert.That(node.Enabled, Is.EqualTo(shouldBeEnabled));
9595
}
9696
}
@@ -132,17 +132,17 @@ public void ExtensionsAreAddedToExtensionPoint(
132132
public void ExtensionMayBeDisabledByDefault()
133133
{
134134
Assert.That(_extensionManager.Extensions,
135-
Has.One.Property(nameof(ExtensionNode.TypeName)).EqualTo(DUMMY_DISABLED_EXTENSION)
135+
Has.One.Property(nameof(ExtensionNode.TypeName)).EqualTo(FAKE_DISABLED_EXTENSION)
136136
.And.Property(nameof(ExtensionNode.Enabled)).False);
137137
}
138138

139139
[Test]
140140
public void DisabledExtensionMayBeEnabled()
141141
{
142-
_extensionManager.EnableExtension(DUMMY_DISABLED_EXTENSION, true);
142+
_extensionManager.EnableExtension(FAKE_DISABLED_EXTENSION, true);
143143

144144
Assert.That(_extensionManager.Extensions,
145-
Has.One.Property(nameof(ExtensionNode.TypeName)).EqualTo(DUMMY_DISABLED_EXTENSION)
145+
Has.One.Property(nameof(ExtensionNode.TypeName)).EqualTo(FAKE_DISABLED_EXTENSION)
146146
.And.Property(nameof(ExtensionNode.Enabled)).True);
147147
}
148148

src/NUnitConsole/nunit4-console/ConsoleRunner.cs

+35-9
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public class ConsoleRunner
3535
private const string INDENT6 = " ";
3636
private const string INDENT8 = " ";
3737

38+
private const string NUNIT_EXTENSION_DIRECTORIES = "NUNIT_EXTENSION_DIRECTORIES";
39+
3840
public static readonly int OK = 0;
3941
public static readonly int INVALID_ARG = -1;
4042
public static readonly int INVALID_ASSEMBLY = -2;
@@ -55,20 +57,35 @@ public class ConsoleRunner
5557

5658
public ConsoleRunner(ITestEngine engine, ConsoleOptions options, ExtendedTextWriter writer)
5759
{
58-
_engine = engine;
59-
_options = options;
60-
_outWriter = writer;
61-
62-
_workDirectory = options.WorkDirectory ?? Directory.GetCurrentDirectory();
63-
64-
if (!Directory.Exists(_workDirectory))
65-
Directory.CreateDirectory(_workDirectory);
60+
Guard.ArgumentNotNull(_engine = engine, nameof(engine));
61+
Guard.ArgumentNotNull(_options = options, nameof(options));
62+
Guard.ArgumentNotNull(_outWriter = writer, nameof(writer));
6663

64+
// NOTE: Accessing Services triggers the engine to initialize all services
6765
_resultService = _engine.Services.GetService<IResultService>();
66+
Guard.OperationValid(_resultService != null, "Internal Error: ResultService was not found");
67+
6868
_filterService = _engine.Services.GetService<ITestFilterService>();
69+
Guard.OperationValid(_filterService != null, "Internal Error: TestFilterService was not found");
70+
71+
_extensionService = _engine.Services.GetService<IExtensionService>();
72+
Guard.OperationValid(_extensionService != null, "Internal Error: ExtensionService was not found");
73+
6974
_extensionService = _engine.Services.GetService<IExtensionService>();
75+
Guard.OperationValid(_extensionService != null, "Internal Error: ExtensionService was not found");
7076

71-
// TODO: Exit with error if any of the services are not found
77+
var extensionPath = Environment.GetEnvironmentVariable(NUNIT_EXTENSION_DIRECTORIES);
78+
if (!string.IsNullOrEmpty(extensionPath))
79+
foreach (string extensionDirectory in extensionPath.Split(new[] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries))
80+
_extensionService.FindExtensionAssemblies(extensionDirectory);
81+
82+
foreach (string extensionDirectory in _options.ExtensionDirectories)
83+
_extensionService.FindExtensionAssemblies(extensionDirectory);
84+
85+
_workDirectory = options.WorkDirectory ?? Directory.GetCurrentDirectory();
86+
87+
if (!Directory.Exists(_workDirectory))
88+
Directory.CreateDirectory(_workDirectory);
7289

7390
// Attempt to enable extensions as requested by the user
7491
foreach (string typeName in options.EnableExtensions)
@@ -341,6 +358,14 @@ private static string GetOSVersion()
341358

342359
private void DisplayExtensionList()
343360
{
361+
if (_options.ExtensionDirectories.Count > 0)
362+
{
363+
_outWriter.WriteLine(ColorStyle.SectionHeader, "User Extension Directories");
364+
foreach (var dir in _options.ExtensionDirectories)
365+
_outWriter.WriteLine($" {Path.GetFullPath(dir)}");
366+
_outWriter.WriteLine();
367+
}
368+
344369
_outWriter.WriteLine(ColorStyle.SectionHeader, "Installed Extensions");
345370

346371
foreach (var ep in _extensionService?.ExtensionPoints ?? new IExtensionPoint[0])
@@ -403,6 +428,7 @@ private ExtendedTextWriter CreateOutputWriter()
403428

404429
private IResultWriter GetResultWriter(OutputSpecification spec)
405430
{
431+
Console.WriteLine($"GetResultWriter: {spec.ToString()}");
406432
return _resultService.GetResultWriter(spec.Format, spec.Transform);
407433
}
408434

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt
2+
3+
using System;
4+
using System.CodeDom;
5+
using System.Collections.Generic;
6+
using System.IO;
7+
using System.Reflection;
8+
using System.Xml;
9+
using NUnit.Engine.Extensibility;
10+
11+
namespace NUnit.Engine.Services
12+
{
13+
public abstract class NUnit3InterfaceWrapper<TARGET> where TARGET : class
14+
{
15+
protected Dictionary<string, MethodInfo> Methods { get; } = new Dictionary<string, MethodInfo>();
16+
17+
protected object _wrappedInstance;
18+
protected Type _wrappedType;
19+
20+
protected NUnit3InterfaceWrapper(object wrappedInstance)
21+
{
22+
_wrappedInstance = wrappedInstance;
23+
_wrappedType = wrappedInstance.GetType();
24+
}
25+
26+
protected MethodInfo WrapMethod(string methodName, params Type[] argTypes)
27+
{
28+
var method = _wrappedType.GetMethod(methodName, argTypes);
29+
if (method == null)
30+
throw new MissingMethodException(methodName);
31+
32+
return method;
33+
}
34+
}
35+
36+
///// <summary>
37+
///// Wrapper class for listeners based on the NUnit API
38+
///// </summary>
39+
//public class NUnitTestEventListenerWrapper : ITestEventListener
40+
//{
41+
// private NUnit.Engine.ITestEventListener _listener;
42+
43+
// public NUnitTestEventListenerWrapper(NUnit.Engine.ITestEventListener listener)
44+
// {
45+
// _listener = listener;
46+
// }
47+
48+
// public void OnTestEvent(string report)
49+
// {
50+
// _listener.OnTestEvent(report);
51+
// }
52+
//}
53+
54+
/// <summary>
55+
/// Wrapper class for result writers based on the NUnit API
56+
/// </summary>
57+
public class NUnitResultWriterWrapper : NUnit3InterfaceWrapper<IResultWriter>, IResultWriter
58+
{
59+
private MethodInfo _checkWritability;
60+
private MethodInfo _writeResultFile;
61+
62+
public NUnitResultWriterWrapper(object writer) : base(writer)
63+
{
64+
_checkWritability = WrapMethod("CheckWritability", typeof(string));
65+
_writeResultFile = WrapMethod("WriteResultFile", typeof(XmlNode), typeof(TextWriter) );
66+
}
67+
68+
public void CheckWritability(string outputPath)
69+
{
70+
_checkWritability.Invoke(_wrappedInstance, new object[] { outputPath });
71+
}
72+
73+
public void WriteResultFile(XmlNode resultNode, string outputPath)
74+
{
75+
using (var file = new StreamWriter(outputPath))
76+
{
77+
WriteResultFile(resultNode, file);
78+
}
79+
}
80+
81+
public void WriteResultFile(XmlNode resultNode, TextWriter writer)
82+
{
83+
_writeResultFile.Invoke(_wrappedInstance, new object[] { resultNode, writer });
84+
}
85+
}
86+
87+
///// <summary>
88+
///// Wrapper class for project loaders which use the NUnit Engine API
89+
///// </summary>
90+
//public class NUnitProjectLoaderWrapper : IProjectLoader
91+
//{
92+
// private NUnit.Engine.Extensibility.IProjectLoader _projectLoader;
93+
94+
// public NUnitProjectLoaderWrapper(NUnit.Engine.Extensibility.IProjectLoader projectLoader)
95+
// {
96+
// _projectLoader = projectLoader;
97+
// }
98+
99+
// public bool CanLoadFrom(string path)
100+
// {
101+
// return _projectLoader.CanLoadFrom(path);
102+
// }
103+
104+
// public IProject LoadFrom(string path)
105+
// {
106+
// return new Projects.NUnitProject(_projectLoader.LoadFrom(path));
107+
// }
108+
//}
109+
}

0 commit comments

Comments
 (0)