Skip to content

Commit

Permalink
Allow specifying Test Selection Language filters in VSTest runsettings
Browse files Browse the repository at this point in the history
This allows using `dotnet test` as a drop in replacement for a
nunit-console run with the `--where` option.

i.e.:

`nunit-console SomeTests.dll --where "cat == SomeCategory"`
becomes
`dotnet vstest SomeTests.dll -- NUnit.Where="cat == SomeCategory"`
or
`dotnet test SomeTests.csproj -- NUnit.Where="cat == SomeCategory"`
  • Loading branch information
mletterle committed Dec 13, 2019
1 parent 32666d8 commit caec049
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 6 deletions.
3 changes: 3 additions & 0 deletions src/NUnitTestAdapter/AdapterSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public interface IAdapterSettings
IDictionary<string, string> TestProperties { get; }
string InternalTraceLevel { get; }
string WorkDirectory { get; }
string Where { get; }
int DefaultTimeout { get; }
int NumberOfTestWorkers { get; }
bool ShadowCopyFiles { get; }
Expand Down Expand Up @@ -157,6 +158,7 @@ public AdapterSettings(TestLogger logger)
public string InternalTraceLevel { get; private set; }

public string WorkDirectory { get; private set; }
public string Where { get; private set; }
public string TestOutputXml { get; private set; }
public bool UseTestOutputXml => !string.IsNullOrEmpty(TestOutputXml);
public int DefaultTimeout { get; private set; }
Expand Down Expand Up @@ -254,6 +256,7 @@ public void Load(string settingsXml)
InternalTraceLevel = GetInnerTextWithLog(nunitNode, nameof(InternalTraceLevel), "Off", "Error", "Warning",
"Info", "Verbose", "Debug");
WorkDirectory = GetInnerTextWithLog(nunitNode, nameof(WorkDirectory));
Where = GetInnerTextWithLog(nunitNode, nameof(Where));
DefaultTimeout = GetInnerTextAsInt(nunitNode, nameof(DefaultTimeout), 0);
NumberOfTestWorkers = GetInnerTextAsInt(nunitNode, nameof(NumberOfTestWorkers), -1);
ShadowCopyFiles = GetInnerTextAsBool(nunitNode, nameof(ShadowCopyFiles), false);
Expand Down
5 changes: 3 additions & 2 deletions src/NUnitTestAdapter/NUnit3TestExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@ public void RunTests(IEnumerable<string> sources, IRunContext runContext, IFrame
try
{
var assemblyPath = Path.IsPathRooted(assemblyName) ? assemblyName : Path.Combine(Directory.GetCurrentDirectory(), assemblyName);
var filter = CreateTestFilterBuilder().FilterByWhere(Settings.Where);

RunAssembly(assemblyPath, null, TestFilter.Empty);
RunAssembly(assemblyPath, null, filter);
}
catch (Exception ex)
{
Expand Down Expand Up @@ -145,7 +146,7 @@ public void RunTests(IEnumerable<TestCase> tests, IRunContext runContext, IFrame
var assemblyPath = Path.IsPathRooted(assemblyName) ? assemblyName : Path.Combine(Directory.GetCurrentDirectory(), assemblyName);

var filterBuilder = CreateTestFilterBuilder();
var filter = filterBuilder.MakeTestFilter(assemblyGroup);
var filter = filterBuilder.FilterByList(assemblyGroup);

RunAssembly(assemblyPath, assemblyGroup, filter);
}
Expand Down
20 changes: 16 additions & 4 deletions src/NUnitTestAdapter/NUnitTestFilterBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,30 @@ public TestFilter ConvertTfsFilterToNUnitFilter(TfsTestFilter tfsFilter, List<Te
var filteredTestCases = tfsFilter.CheckFilter(loadedTestCases);
var testCases = filteredTestCases as TestCase[] ?? filteredTestCases.ToArray();
//TestLog.Info(string.Format("TFS Filter detected: LoadedTestCases {0}, Filterered Test Cases {1}", loadedTestCases.Count, testCases.Count()));
return MakeTestFilter(testCases);
return FilterByList(testCases);
}

public TestFilter MakeTestFilter(IEnumerable<TestCase> testCases)
public TestFilter FilterByWhere(string where)
{
if (testCases.Count() == 0)
return NoTestsFound;
ITestFilterBuilder filterBuilder = _filterService.GetTestFilterBuilder();

if(!string.IsNullOrEmpty(where))
{
filterBuilder.SelectWhere(where);
}

return filterBuilder.GetFilter();

}

public TestFilter FilterByList(IEnumerable<TestCase> testCases)
{
ITestFilterBuilder filterBuilder = _filterService.GetTestFilterBuilder();

foreach (TestCase testCase in testCases)
{
filterBuilder.AddTest(testCase.FullyQualifiedName);
}

return filterBuilder.GetFilter();
}
Expand Down
7 changes: 7 additions & 0 deletions src/NUnitTestAdapterTests/AdapterSettingsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -367,5 +367,12 @@ public void LiveUnitTestingDataCollector()
Assert.That(_settings.NumberOfTestWorkers, Is.Zero);
Assert.True(_settings.InProcDataCollectorsAvailable);
}

[Test]
public void WhereCanBeSet()
{
_settings.Load("<RunSettings><NUnit><Where>cat == SomeCategory and namespace == SomeNamespace or cat != SomeOtherCategory</Where></NUnit></RunSettings>");
Assert.That(_settings.Where, Is.EqualTo("cat == SomeCategory and namespace == SomeNamespace or cat != SomeOtherCategory"));
}
}
}
11 changes: 11 additions & 0 deletions src/NUnitTestAdapterTests/Fakes/FakeRunSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,15 @@ public FakeRunSettingsForTestOutputAndWorkDir(string testOutput,string workDir)
public override string SettingsXml => $"<RunSettings><NUnit><WorkDirectory>{_workDir}</WorkDirectory><TestOutputXml>{_testOutput}</TestOutputXml></NUnit></RunSettings>";
}

class FakeRunSettingsForWhere : FakeRunSettings
{
private readonly string _where;

public FakeRunSettingsForWhere(string where)
{
_where = where;
}
public override string SettingsXml => $"<RunSettings><NUnit><Where>{_where}</Where></NUnit></RunSettings>";
}

}
42 changes: 42 additions & 0 deletions src/NUnitTestAdapterTests/TestExecutionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,48 @@ private int GetCount(TestOutcome outcome)
}


[Category("TestExecution")]
public class TestFilteringTests
{
private string MockAssemblyPath;
[OneTimeSetUp]
public void LoadMockassembly()
{
MockAssemblyPath = Path.Combine(TestContext.CurrentContext.TestDirectory, "mock-assembly.dll");

// Sanity check to be sure we have the correct version of mock-assembly.dll
Assert.That(MockAssembly.TestsAtRuntime, Is.EqualTo(MockAssembly.Tests),
"The reference to mock-assembly.dll appears to be the wrong version");
}

[TestCase("", 35)]
[TestCase(null, 35)]
[TestCase("cat == Special", 1)]
[TestCase("cat == MockCategory", 2)]
[TestCase("method =~ MockTest?", 5)]
[TestCase("method =~ MockTest? and cat != MockCategory", 3)]
[TestCase("namespace == ThisNamespaceDoesNotExist", 0)]
[TestCase("test==NUnit.Tests.Assemblies.MockTestFixture", MockTestFixture.Tests, TestName = "{m}_MockTestFixture")]
[TestCase("test==NUnit.Tests.IgnoredFixture and method == Test2", 1, TestName = "{m}_IgnoredFixture")]
[TestCase("class==NUnit.Tests.Assemblies.MockTestFixture", MockTestFixture.Tests)]
[TestCase("name==MockTestFixture", MockTestFixture.Tests + NUnit.Tests.TestAssembly.MockTestFixture.Tests)]
[TestCase("cat==FixtureCategory", MockTestFixture.Tests)]
public void TestsWhereShouldFilter(string filter, int expectedCount)
{
// Create a fake environment.
var context = new FakeRunContext(new FakeRunSettingsForWhere(filter));
var fakeFramework = new FakeFrameworkHandle();

var executor = TestAdapterUtils.CreateExecutor();
executor.RunTests(new[] { MockAssemblyPath }, context, fakeFramework);

var completedRuns = fakeFramework.Events.Where(e => e.EventType == FakeFrameworkHandle.EventType.RecordEnd);

Assert.That(completedRuns, Has.Exactly(expectedCount).Items);

}

}

[Category("TestExecution")]
public class TestExecutionTests
Expand Down

0 comments on commit caec049

Please sign in to comment.