How can I run NUnit tests programmatically and in an extra process using NUnit.Engine?

118 views Asked by At

I have implemented an application in C# (net 7.0) which loads and executes unit tests programmatically using NUnit(3.13.3) and NUnit.Engine (3.16.3). Tests are also implemented in C# net 7.0.

My problem is that the tests are not being executed independent from my application. This means:

  • If the application and the tests have common dependencies, the tests are being executed with the dependencies of the application and not with their own. And this is a problem, if for example the versions differ.
  • Another problem comes if the application tries to reload the tests. The tests dll is reload but not its dependencies (independently of having them in common with the application).

I know the nunit-console runs tests in a separate process, and this will solve my problem, but I do not know how can I achieve this programmatically. The runner returned by the engine (ITestRunner runner = TestEngineActivator.CreateInstance().GetRunner(_testPackage);) always runs the tests in the same process as my application, not matter which settings my TestPackage have.

My question is, how do I get a runner which runs the tests in an extra process? Which settings do I need for the TestPackage? Do I have to install dome extra NuGets?

As I said, I implemented my application using net 7.0 and I have installed the two NuGets NUnit 3.13.3 and NUnit.Engine 3.16.3.

I get the ITestEngine in this way:

    public TestModel() {
        _engine = TestEngineActivator.CreateInstance();
        _settingsService = new SettingsService(true);
        _settingsService.LoadSettings();
        _engine.InternalTraceLevel = InternalTraceLevel.Off;
    }

Then I load the tests:

    public async Task<XmlNode?> LoadTestsAsync(string dllTestFile) {
        LoadedTestFile = dllTestFile;
        _testPackage = new TestPackage(LoadedTestFile);
        _runner = _engine.GetRunner(_testPackage);
        var nodes = await Task.Run(() => _runner.Explore(TestFilter.Empty));

        XmlWriter writer = XmlWriter.Create("tests.xml", new XmlWriterSettings() { Indent = true});
        nodes.WriteContentTo(writer);
        writer.Flush();
        writer.Dispose();

        return nodes;
    }

Run the tests:

   public void Run(TestNode testNode) {
        var filterService = _engine?.Services.GetService<ITestFilterService>();
        var builder = filterService?.GetTestFilterBuilder();
        CheckVirtualAndAddChildren(builder, testNode);
        _runner?.RunAsync(_events, builder?.GetFilter());
    }

And reload the tests:

   public async Task<XmlNode?> ReloadAsync() {        
        try {
            _runner?.Unload();
        } catch (NUnitEngineUnloadException) {}
        _runner?.Dispose();
        _runner = _engine.GetRunner(_testPackage);
        
        var nodes = await Task.Run(() => _runner?.Explore(TestFilter.Empty));

        XmlWriter writer = XmlWriter.Create("tests.xml", new XmlWriterSettings() { Indent = true});
        nodes?.WriteContentTo(writer);
        writer.Flush();
        writer.Dispose();

        return nodes;
    }

I also let write the xml return by ITestRunner.Explore(TestFilter)

<?xml version="1.0" encoding="utf-8"?>
<test-suite type="Assembly" id="0-1007" name="NUnitTests.dll" fullname="H:/MyApplication/sample/NUnitDemo/NUnitTests/bin/Debug/net7.0/NUnitTests.dll" runstate="Runnable" testcasecount="4">
  <environment framework-version="3.13.3.0" clr-version="7.0.5" os-version="Microsoft Windows 10.0.19045" platform="Win32NT" cwd="H:\MyApplication\MyApplication\bin\Debug\net7.0" machine-name="XXXX" user="myself" user-domain="XXXX" culture="de-DE" uiculture="de-DE" os-architecture="x64" />
  <settings>
    <setting name="NumberOfTestWorkers" value="16" />
  </settings>
  <properties>
    <property name="_PID" value="29016" />
    <property name="_APPDOMAIN" value="MyApplication" />
  </properties>
  <test-suite type="TestSuite" id="0-1008" name="NUnitTests" fullname="NUnitTests" runstate="Runnable" testcasecount="4">
    <test-suite type="TestFixture" id="0-1000" name="DemoTests" fullname="NUnitTests.DemoTests" classname="NUnitTests.DemoTests" runstate="Runnable" testcasecount="4">
      <test-suite type="ParameterizedMethod" id="0-1006" name="BaseDependency" fullname="NUnitTests.DemoTests.BaseDependency" classname="NUnitTests.DemoTests" runstate="Runnable" testcasecount="2">
        <test-case id="0-1004" name="BaseDependency(Cycle #1)" fullname="NUnitTests.DemoTests.BaseDependency(Cycle #1)" methodname="BaseDependency" classname="NUnitTests.DemoTests" runstate="Runnable" seed="1298419094" />
        <test-case id="0-1005" name="BaseDependency(Cycle #2)" fullname="NUnitTests.DemoTests.BaseDependency(Cycle #2)" methodname="BaseDependency" classname="NUnitTests.DemoTests" runstate="Runnable" seed="2074295330" />
      </test-suite>
      <test-suite type="ParameterizedMethod" id="0-1003" name="NoBaseDependency" fullname="NUnitTests.DemoTests.NoBaseDependency" classname="NUnitTests.DemoTests" runstate="Runnable" testcasecount="2">
        <test-case id="0-1001" name="NoBaseDependency(Cycle #1)" fullname="NUnitTests.DemoTests.NoBaseDependency(Cycle #1)" methodname="NoBaseDependency" classname="NUnitTests.DemoTests" runstate="Runnable" seed="1168845109" />
        <test-case id="0-1002" name="NoBaseDependency(Cycle #2)" fullname="NUnitTests.DemoTests.NoBaseDependency(Cycle #2)" methodname="NoBaseDependency" classname="NUnitTests.DemoTests" runstate="Runnable" seed="64791598" />
      </test-suite>
    </test-suite>
  </test-suite>
</test-suite>
0

There are 0 answers