[XHarness] Add filtering support to the NUnit and xUnit runners. (#5262)
First step to get to the point in which we can filter the execution of the bcl tests via filters. This commit adds the filtering support to the runners, which later will be used by xharness to pass those tests filtered. The end goal is to not skip a complete assembly but just those failing tests.
This commit is contained in:
Родитель
7360d4f7a7
Коммит
20328ca84b
|
@ -139,6 +139,9 @@
|
|||
<Compile Include="templates\common\TestRunner.NUnit\NUnitTestRunner.cs">
|
||||
<Link>TestRunner.NUnit\NUnitTestRunner.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.NUnit\ClassOrNamespaceFilter.cs">
|
||||
<Link>TestRunner.NUnit\ClassOrNamespaceFilter.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.Core\Extensions.Bool.cs">
|
||||
<Link>TestRunner.Core\Extensions.Bool.cs</Link>
|
||||
</Compile>
|
||||
|
@ -166,6 +169,12 @@
|
|||
<Compile Include="templates\common\TestRunner.Core\TestRunner.cs">
|
||||
<Link>TestRunner.Core\TestRunner.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.Core\TestRunSelector.cs">
|
||||
<Link>TestRunner.Core\TestRunSelector.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.Core\TestRunSelectorType.cs">
|
||||
<Link>TestRunner.Core\TestRunSelectorType.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.xUnit\XUnitFilter.cs">
|
||||
<Link>TestRunner.xUnit\XUnitFilter.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
@ -210,6 +210,9 @@
|
|||
<Compile Include="templates\common\TestRunner.NUnit\NUnitTestRunner.cs">
|
||||
<Link>TestRunner.NUnit\NUnitTestRunner.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.NUnit\ClassOrNamespaceFilter.cs">
|
||||
<Link>TestRunner.NUnit\ClassOrNamespaceFilter.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.Core\Extensions.Bool.cs">
|
||||
<Link>TestRunner.Core\Extensions.Bool.cs</Link>
|
||||
</Compile>
|
||||
|
@ -237,6 +240,12 @@
|
|||
<Compile Include="templates\common\TestRunner.Core\TestRunner.cs">
|
||||
<Link>TestRunner.Core\TestRunner.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.Core\TestRunSelector.cs">
|
||||
<Link>TestRunner.Core\TestRunSelector.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.Core\TestRunSelectorType.cs">
|
||||
<Link>TestRunner.Core\TestRunSelectorType.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.xUnit\XUnitFilter.cs">
|
||||
<Link>TestRunner.xUnit\XUnitFilter.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
@ -184,9 +184,18 @@
|
|||
<Compile Include="templates\common\TestRunner.Core\TestRunner.cs">
|
||||
<Link>TestRunner.Core\TestRunner.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.Core\TestRunSelector.cs">
|
||||
<Link>TestRunner.Core\TestRunSelector.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.Core\TestRunSelectorType.cs">
|
||||
<Link>TestRunner.Core\TestRunSelectorType.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.NUnit\NUnitTestRunner.cs">
|
||||
<Link>TestRunner.NUnit\NUnitTestRunner.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.NUnit\ClassOrNamespaceFilter.cs">
|
||||
<Link>TestRunner.NUnit\ClassOrNamespaceFilter.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.xUnit\XUnitFilter.cs">
|
||||
<Link>TestRunner.xUnit\XUnitFilter.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
@ -222,6 +222,9 @@
|
|||
<Compile Include="templates\common\TestRunner.NUnit\NUnitTestRunner.cs">
|
||||
<Link>TestRunner.NUnit\NUnitTestRunner.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.NUnit\ClassOrNamespaceFilter.cs">
|
||||
<Link>TestRunner.NUnit\ClassOrNamespaceFilter.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.Core\Extensions.Bool.cs">
|
||||
<Link>TestRunner.Core\Extensions.Bool.cs</Link>
|
||||
</Compile>
|
||||
|
@ -249,6 +252,12 @@
|
|||
<Compile Include="templates\common\TestRunner.Core\TestRunner.cs">
|
||||
<Link>TestRunner.Core\TestRunner.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.Core\TestRunSelector.cs">
|
||||
<Link>TestRunner.Core\TestRunSelector.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.Core\TestRunSelectorType.cs">
|
||||
<Link>TestRunner.Core\TestRunSelectorType.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="templates\common\TestRunner.xUnit\XUnitFilter.cs">
|
||||
<Link>TestRunner.xUnit\XUnitFilter.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
|
||||
namespace Xamarin.iOS.UnitTests
|
||||
{
|
||||
public class TestRunSelector
|
||||
{
|
||||
public string Assembly { get; set; }
|
||||
public string Value { get; set; }
|
||||
public TestRunSelectorType Type { get; set; }
|
||||
public bool Include { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
|
||||
namespace Xamarin.iOS.UnitTests
|
||||
{
|
||||
public enum TestRunSelectorType
|
||||
{
|
||||
Assembly,
|
||||
Namespace,
|
||||
Class,
|
||||
Single,
|
||||
}
|
||||
}
|
|
@ -17,6 +17,8 @@ namespace Xamarin.iOS.UnitTests
|
|||
public long FilteredTests { get; protected set; } = 0;
|
||||
public bool RunInParallel { get; set; } = false;
|
||||
public string TestsRootDirectory { get; set; }
|
||||
public bool RunAllTestsByDefault { get; set; } = true;
|
||||
public bool LogExcludedTests { get; set; }
|
||||
public TextWriter Writer { get; set; }
|
||||
public List<TestFailureInfo> FailureInfos { get; } = new List<TestFailureInfo> ();
|
||||
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using NUnit.Framework.Api;
|
||||
using NUnit.Framework.Internal;
|
||||
using NUnit.Framework.Internal.Filters;
|
||||
|
||||
namespace Xamarin.iOS.UnitTests.NUnit
|
||||
{
|
||||
public class ClassOrNamespaceFilter : TestFilter
|
||||
{
|
||||
bool isClassFilter;
|
||||
List <string> names;
|
||||
|
||||
public ClassOrNamespaceFilter (string name, bool isClassFilter)
|
||||
{
|
||||
AddName (name);
|
||||
this.isClassFilter = isClassFilter;
|
||||
}
|
||||
|
||||
public ClassOrNamespaceFilter (IEnumerable<string> names, bool isClassFilter)
|
||||
{
|
||||
if (names == null)
|
||||
throw new ArgumentNullException (nameof (names));
|
||||
|
||||
this.isClassFilter = isClassFilter;
|
||||
foreach (string n in names) {
|
||||
string name = n?.Trim ();
|
||||
if (String.IsNullOrEmpty (name))
|
||||
continue;
|
||||
|
||||
AddName (name);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddName (string name)
|
||||
{
|
||||
if (String.IsNullOrEmpty (name))
|
||||
throw new ArgumentException ("must not be null or empty", nameof (name));
|
||||
|
||||
if (names == null)
|
||||
names = new List <string> ();
|
||||
if (names.Contains (name))
|
||||
return;
|
||||
|
||||
names.Add (name);
|
||||
}
|
||||
|
||||
public override bool Match (ITest test)
|
||||
{
|
||||
if (test == null || names == null || names.Count == 0)
|
||||
return false;
|
||||
|
||||
if (test.FixtureType == null)
|
||||
return false; // It's probably an assembly name, all tests will have a fixture
|
||||
|
||||
if (isClassFilter)
|
||||
return NameMatches (test.FixtureType.FullName);
|
||||
|
||||
int dot = test.FixtureType.FullName.LastIndexOf ('.');
|
||||
if (dot < 1)
|
||||
return false;
|
||||
|
||||
return NameMatches (test.FixtureType.FullName.Substring (0, dot));
|
||||
}
|
||||
|
||||
bool NameMatches (string name)
|
||||
{
|
||||
foreach (string n in names) {
|
||||
if (n == null)
|
||||
continue;
|
||||
if (String.Compare (name, n, StringComparison.Ordinal) == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
|
@ -21,9 +22,11 @@ namespace Xamarin.iOS.UnitTests.NUnit
|
|||
{
|
||||
Dictionary<string, object> builderSettings;
|
||||
TestSuiteResult results;
|
||||
bool runAssemblyByDefault;
|
||||
|
||||
public ITestFilter Filter { get; set; } = TestFilter.Empty;
|
||||
public bool GCAfterEachFixture { get; set; }
|
||||
public Dictionary<string, bool> AssemblyFilters { get; set; }
|
||||
|
||||
protected override string ResultsFileName { get; set; } = "TestResults.NUnit.xml";
|
||||
|
||||
|
@ -36,23 +39,31 @@ namespace Xamarin.iOS.UnitTests.NUnit
|
|||
{
|
||||
if (testAssemblies == null)
|
||||
throw new ArgumentNullException (nameof (testAssemblies));
|
||||
|
||||
|
||||
if (AssemblyFilters == null || AssemblyFilters.Count == 0)
|
||||
runAssemblyByDefault = true;
|
||||
else
|
||||
runAssemblyByDefault = AssemblyFilters.Values.Any (v => !v);
|
||||
|
||||
var builder = new NUnitLiteTestAssemblyBuilder ();
|
||||
var runner = new NUnitLiteTestAssemblyRunner (builder, new FinallyDelegate ());
|
||||
var testSuite = new TestSuite (NSBundle.MainBundle.BundleIdentifier);
|
||||
results = new TestSuiteResult (testSuite);
|
||||
|
||||
TotalTests = 0;
|
||||
foreach (TestAssemblyInfo assemblyInfo in testAssemblies) {
|
||||
if (assemblyInfo == null || assemblyInfo.Assembly == null)
|
||||
if (assemblyInfo == null || assemblyInfo.Assembly == null || !ShouldRunAssembly (assemblyInfo))
|
||||
continue;
|
||||
|
||||
|
||||
if (!runner.Load (assemblyInfo.Assembly, builderSettings)) {
|
||||
OnWarning ($"Failed to load tests from assembly '{assemblyInfo.Assembly}");
|
||||
continue;
|
||||
}
|
||||
if (runner.LoadedTest is NUnitTest tests)
|
||||
if (runner.LoadedTest is NUnitTest tests) {
|
||||
TotalTests += tests.TestCaseCount;
|
||||
testSuite.Add (tests);
|
||||
|
||||
}
|
||||
|
||||
// Messy API. .Run returns ITestResult which is, in reality, an instance of TestResult since that's
|
||||
// what WorkItem returns and we need an instance of TestResult to add it to TestSuiteResult. So, cast
|
||||
// the return to TestResult and hope for the best.
|
||||
|
@ -73,9 +84,45 @@ namespace Xamarin.iOS.UnitTests.NUnit
|
|||
results.AddResult (testResult);
|
||||
}
|
||||
|
||||
// NUnitLite doesn't report filtered tests at all, but we can calculate here
|
||||
FilteredTests = TotalTests - ExecutedTests;
|
||||
LogFailureSummary ();
|
||||
}
|
||||
|
||||
bool ShouldRunAssembly (TestAssemblyInfo assemblyInfo)
|
||||
{
|
||||
if (assemblyInfo == null)
|
||||
return false;
|
||||
|
||||
if (AssemblyFilters == null || AssemblyFilters.Count == 0)
|
||||
return true;
|
||||
|
||||
bool include;
|
||||
if (AssemblyFilters.TryGetValue (assemblyInfo.FullPath, out include))
|
||||
return ReportFilteredAssembly (assemblyInfo, include);
|
||||
|
||||
string fileName = Path.GetFileName (assemblyInfo.FullPath);
|
||||
if (AssemblyFilters.TryGetValue (fileName, out include))
|
||||
return ReportFilteredAssembly (assemblyInfo, include);
|
||||
|
||||
fileName = Path.GetFileNameWithoutExtension (assemblyInfo.FullPath);
|
||||
if (AssemblyFilters.TryGetValue (fileName, out include))
|
||||
return ReportFilteredAssembly (assemblyInfo, include);
|
||||
|
||||
return runAssemblyByDefault;
|
||||
}
|
||||
|
||||
bool ReportFilteredAssembly (TestAssemblyInfo assemblyInfo, bool include)
|
||||
{
|
||||
if (LogExcludedTests) {
|
||||
const string included = "Included";
|
||||
const string excluded = "Excluded";
|
||||
|
||||
OnInfo ($"[FILTER] {(include ? included : excluded)} assembly: {assemblyInfo.FullPath}");
|
||||
}
|
||||
return include;
|
||||
}
|
||||
|
||||
public bool Pass (ITest test)
|
||||
{
|
||||
return true;
|
||||
|
|
|
@ -1,28 +1,128 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Xamarin.iOS.UnitTests.XUnit
|
||||
{
|
||||
public class XUnitFilter
|
||||
{
|
||||
public string TraitName { get; }
|
||||
public string TraitValue { get; }
|
||||
public string TestCaseName { get; }
|
||||
public bool Exclude { get; }
|
||||
public XUnitFilterType FilterType { get; }
|
||||
public string AssemblyName { get; private set; }
|
||||
public string SelectorName { get; private set; }
|
||||
public string SelectorValue { get; private set; }
|
||||
|
||||
public XUnitFilter (string testCaseName, bool exclude)
|
||||
public bool Exclude { get; private set; }
|
||||
public XUnitFilterType FilterType { get; private set; }
|
||||
|
||||
public static XUnitFilter CreateSingleFilter (string singleTestName, bool exclude, string assemblyName = null)
|
||||
{
|
||||
FilterType = XUnitFilterType.TypeName;
|
||||
TestCaseName = testCaseName;
|
||||
Exclude = exclude;
|
||||
if (String.IsNullOrEmpty (singleTestName))
|
||||
throw new ArgumentException("must not be null or empty", nameof (singleTestName));
|
||||
|
||||
return new XUnitFilter {
|
||||
AssemblyName = assemblyName,
|
||||
SelectorValue = singleTestName,
|
||||
FilterType = XUnitFilterType.Single,
|
||||
Exclude = exclude
|
||||
};
|
||||
}
|
||||
|
||||
public XUnitFilter (string traitName, string traitValue, bool exclude)
|
||||
public static XUnitFilter CreateAssemblyFilter (string assemblyName, bool exclude)
|
||||
{
|
||||
FilterType = XUnitFilterType.Trait;
|
||||
TraitName = traitName;
|
||||
TraitValue = traitValue;
|
||||
Exclude = exclude;
|
||||
if (String.IsNullOrEmpty (assemblyName))
|
||||
throw new ArgumentException("must not be null or empty", nameof (assemblyName));
|
||||
|
||||
return new XUnitFilter {
|
||||
AssemblyName = assemblyName,
|
||||
FilterType = XUnitFilterType.Assembly,
|
||||
Exclude = exclude
|
||||
};
|
||||
}
|
||||
|
||||
public static XUnitFilter CreateNamespaceFilter (string namespaceName, bool exclude, string assemblyName = null)
|
||||
{
|
||||
if (String.IsNullOrEmpty (namespaceName))
|
||||
throw new ArgumentException("must not be null or empty", nameof (namespaceName));
|
||||
|
||||
return new XUnitFilter {
|
||||
AssemblyName = assemblyName,
|
||||
SelectorValue = namespaceName,
|
||||
FilterType = XUnitFilterType.Namespace,
|
||||
Exclude = exclude
|
||||
};
|
||||
}
|
||||
|
||||
public static XUnitFilter CreateClassFilter (string className, bool exclude, string assemblyName = null)
|
||||
{
|
||||
if (String.IsNullOrEmpty (className))
|
||||
throw new ArgumentException("must not be null or empty", nameof (className));
|
||||
|
||||
return new XUnitFilter {
|
||||
AssemblyName = assemblyName,
|
||||
SelectorValue = className,
|
||||
FilterType = XUnitFilterType.TypeName,
|
||||
Exclude = exclude
|
||||
};
|
||||
}
|
||||
|
||||
public static XUnitFilter CreateTraitFilter (string traitName, string traitValue, bool exclude)
|
||||
{
|
||||
if (String.IsNullOrEmpty (traitName))
|
||||
throw new ArgumentException("must not be null or empty", nameof (traitName));
|
||||
|
||||
return new XUnitFilter {
|
||||
AssemblyName = null,
|
||||
SelectorName = traitName,
|
||||
SelectorValue = traitValue ?? String.Empty,
|
||||
FilterType = XUnitFilterType.Trait,
|
||||
Exclude = exclude
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
var sb = new StringBuilder ("XUnitFilter [");
|
||||
|
||||
sb.Append ($"Type: {FilterType}; ");
|
||||
sb.Append (Exclude ? "exclude" : "include");
|
||||
|
||||
if (!String.IsNullOrEmpty (AssemblyName))
|
||||
sb.Append ($"; AssemblyName: {AssemblyName}");
|
||||
|
||||
switch (FilterType) {
|
||||
case XUnitFilterType.Assembly:
|
||||
break;
|
||||
|
||||
case XUnitFilterType.Namespace:
|
||||
AppendDesc ("Namespace", SelectorValue);
|
||||
break;
|
||||
|
||||
case XUnitFilterType.Single:
|
||||
AppendDesc ("Method", SelectorValue);
|
||||
break;
|
||||
|
||||
case XUnitFilterType.Trait:
|
||||
AppendDesc ("Trait name", SelectorName);
|
||||
AppendDesc ("Trait value", SelectorValue);
|
||||
break;
|
||||
|
||||
case XUnitFilterType.TypeName:
|
||||
AppendDesc ("Class", SelectorValue);
|
||||
break;
|
||||
|
||||
default:
|
||||
sb.Append ("; Unknown filter type");
|
||||
break;
|
||||
}
|
||||
sb.Append (']');
|
||||
|
||||
return sb.ToString ();
|
||||
|
||||
void AppendDesc (string name, string value)
|
||||
{
|
||||
if (String.IsNullOrEmpty (value))
|
||||
return;
|
||||
|
||||
sb.Append ($"; {name}: {value}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
|
||||
namespace Xamarin.iOS.UnitTests.XUnit
|
||||
{
|
||||
|
@ -6,5 +6,8 @@ namespace Xamarin.iOS.UnitTests.XUnit
|
|||
{
|
||||
Trait,
|
||||
TypeName,
|
||||
Assembly,
|
||||
Single,
|
||||
Namespace,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace Xamarin.iOS.UnitTests.XUnit
|
|||
|
||||
XElement assembliesElement;
|
||||
List<XUnitFilter> filters;
|
||||
bool runAssemblyByDefault;
|
||||
|
||||
public XUnitResultFileFormat ResultFileFormat { get; set; } = XUnitResultFileFormat.NUnit;
|
||||
public AppDomainSupport AppDomainSupport { get; set; } = AppDomainSupport.Denied;
|
||||
|
@ -677,9 +678,23 @@ namespace Xamarin.iOS.UnitTests.XUnit
|
|||
if (testAssemblies == null)
|
||||
throw new ArgumentNullException (nameof (testAssemblies));
|
||||
|
||||
if (filters != null && filters.Count > 0) {
|
||||
do_log ("Configured filters:");
|
||||
foreach (XUnitFilter filter in filters) {
|
||||
do_log ($" {filter}");
|
||||
}
|
||||
}
|
||||
|
||||
List<XUnitFilter> assemblyFilters = filters?.Where (sel => sel != null && sel.FilterType == XUnitFilterType.Assembly)?.ToList ();
|
||||
if (assemblyFilters == null || assemblyFilters.Count == 0) {
|
||||
runAssemblyByDefault = true;
|
||||
assemblyFilters = null;
|
||||
} else
|
||||
runAssemblyByDefault = assemblyFilters.Any (f => f != null && f.Exclude);
|
||||
|
||||
assembliesElement = new XElement ("assemblies");
|
||||
foreach (TestAssemblyInfo assemblyInfo in testAssemblies) {
|
||||
if (assemblyInfo == null || assemblyInfo.Assembly == null)
|
||||
if (assemblyInfo == null || assemblyInfo.Assembly == null || !ShouldRunAssembly (assemblyInfo))
|
||||
continue;
|
||||
|
||||
if (String.IsNullOrEmpty (assemblyInfo.FullPath)) {
|
||||
|
@ -703,6 +718,50 @@ namespace Xamarin.iOS.UnitTests.XUnit
|
|||
}
|
||||
|
||||
LogFailureSummary ();
|
||||
|
||||
bool ShouldRunAssembly (TestAssemblyInfo assemblyInfo)
|
||||
{
|
||||
if (assemblyInfo == null)
|
||||
return false;
|
||||
|
||||
if (assemblyFilters == null)
|
||||
return true;
|
||||
|
||||
foreach (XUnitFilter filter in assemblyFilters) {
|
||||
if (String.Compare (filter.AssemblyName, assemblyInfo.FullPath, StringComparison.Ordinal) == 0)
|
||||
return ReportFilteredAssembly (assemblyInfo, filter);
|
||||
|
||||
string fileName = Path.GetFileName (assemblyInfo.FullPath);
|
||||
if (String.Compare (fileName, filter.AssemblyName, StringComparison.Ordinal) == 0)
|
||||
return ReportFilteredAssembly (assemblyInfo, filter);
|
||||
|
||||
string filterExtension = Path.GetExtension (filter.AssemblyName);
|
||||
if (String.IsNullOrEmpty (filterExtension) ||
|
||||
(String.Compare (filterExtension, ".exe", StringComparison.OrdinalIgnoreCase) != 0 &&
|
||||
String.Compare (filterExtension, ".dll", StringComparison.OrdinalIgnoreCase) != 0)) {
|
||||
string asmName = $"{filter.AssemblyName}.dll";
|
||||
if (String.Compare (asmName, fileName, StringComparison.Ordinal) == 0)
|
||||
return ReportFilteredAssembly (assemblyInfo, filter);
|
||||
|
||||
asmName = $"{filter.AssemblyName}.exe";
|
||||
if (String.Compare (asmName, fileName, StringComparison.Ordinal) == 0)
|
||||
return ReportFilteredAssembly (assemblyInfo, filter);
|
||||
}
|
||||
}
|
||||
|
||||
return runAssemblyByDefault;
|
||||
}
|
||||
|
||||
bool ReportFilteredAssembly (TestAssemblyInfo assemblyInfo, XUnitFilter filter)
|
||||
{
|
||||
if (LogExcludedTests) {
|
||||
const string included = "Included";
|
||||
const string excluded = "Excluded";
|
||||
|
||||
OnInfo ($"[FILTER] {(filter.Exclude ? excluded : included)} assembly: {assemblyInfo.FullPath}");
|
||||
}
|
||||
return !filter.Exclude;
|
||||
}
|
||||
}
|
||||
|
||||
public override string WriteResultsToFile ()
|
||||
|
@ -863,42 +922,88 @@ namespace Xamarin.iOS.UnitTests.XUnit
|
|||
|
||||
bool IsIncluded (ITestCase testCase)
|
||||
{
|
||||
if (testCase.Traits == null || testCase.Traits.Count == 0)
|
||||
return true;
|
||||
|
||||
if (testCase == null)
|
||||
return false;
|
||||
|
||||
bool haveTraits = testCase.Traits != null && testCase.Traits.Count > 0;
|
||||
foreach (XUnitFilter filter in filters) {
|
||||
List<string> values;
|
||||
if (filter == null)
|
||||
continue;
|
||||
|
||||
if (filter.FilterType == XUnitFilterType.Trait) {
|
||||
if (!testCase.Traits.TryGetValue (filter.TraitName, out values))
|
||||
if (!haveTraits || !testCase.Traits.TryGetValue (filter.SelectorName, out values))
|
||||
continue;
|
||||
|
||||
if (values == null || values.Count == 0) {
|
||||
// We have no values and the filter doesn't specify one - that means we match on
|
||||
// the trait name only.
|
||||
if (String.IsNullOrEmpty (filter.TraitValue))
|
||||
return !filter.Exclude;
|
||||
if (String.IsNullOrEmpty (filter.SelectorValue))
|
||||
return ReportFilteredTest (filter);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (values.Contains (filter.TraitValue, StringComparer.OrdinalIgnoreCase))
|
||||
return !filter.Exclude;
|
||||
if (values.Contains (filter.SelectorValue, StringComparer.OrdinalIgnoreCase))
|
||||
return ReportFilteredTest (filter);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (filter.FilterType == XUnitFilterType.TypeName) {
|
||||
Logger.Info ($"IsIncluded: filter: '{filter.TestCaseName}', test case name: {testCase.DisplayName}");
|
||||
if (String.Compare (testCase.DisplayName, filter.TestCaseName, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
return !filter.Exclude;
|
||||
string testClassName = testCase.TestMethod?.TestClass?.Class?.Name?.Trim ();
|
||||
if (String.IsNullOrEmpty (testClassName))
|
||||
continue;
|
||||
|
||||
if (String.Compare (testClassName, filter.SelectorValue, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
return ReportFilteredTest (filter);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (filter.FilterType == XUnitFilterType.Single) {
|
||||
if (String.Compare (testCase.DisplayName, filter.SelectorValue, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
return ReportFilteredTest (filter);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (filter.FilterType == XUnitFilterType.Namespace) {
|
||||
string testClassName = testCase.TestMethod?.TestClass?.Class?.Name?.Trim ();
|
||||
if (String.IsNullOrEmpty (testClassName))
|
||||
continue;
|
||||
|
||||
int dot = testClassName.LastIndexOf ('.');
|
||||
if (dot <= 0)
|
||||
continue;
|
||||
|
||||
string testClassNamespace = testClassName.Substring (0, dot);
|
||||
if (String.Compare (testClassNamespace, filter.SelectorValue, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
return ReportFilteredTest (filter);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (filter.FilterType == XUnitFilterType.Assembly) {
|
||||
continue; // Ignored: handled elsewhere
|
||||
}
|
||||
|
||||
throw new InvalidOperationException ($"Unsupported filter type {filter.FilterType}");
|
||||
}
|
||||
|
||||
return true;
|
||||
return RunAllTestsByDefault;
|
||||
|
||||
bool ReportFilteredTest (XUnitFilter filter)
|
||||
{
|
||||
if (LogExcludedTests) {
|
||||
const string included = "Included";
|
||||
const string excluded = "Excluded";
|
||||
|
||||
string selector;
|
||||
if (filter.FilterType == XUnitFilterType.Trait)
|
||||
selector = $"'{filter.SelectorName}':'{filter.SelectorValue}'";
|
||||
else
|
||||
selector = $"'{filter.SelectorValue}'";
|
||||
|
||||
do_log ($"[FILTER] {(filter.Exclude ? excluded : included)} test (filtered by {filter.FilterType}; {selector}): {testCase.DisplayName}");
|
||||
}
|
||||
return !filter.Exclude;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче