Skip to content
This repository was archived by the owner on Jan 11, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 62 additions & 4 deletions src/xunit.console.netcore/CommandLine.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using Xunit.ConsoleClient.Project;

namespace Xunit.ConsoleClient
{
Expand All @@ -14,18 +15,56 @@ protected CommandLine(string[] args, Predicate<string> fileExists = null)
fileExists = fileName => File.Exists(fileName);

for (var i = args.Length - 1; i >= 0; i--)
{
if (args[i][0] == '@')
{
// Parse response file
IList<string> rspArguments = ParseResponseFile(args[i].Substring(1));
for (int j = rspArguments.Count - 1; j >= 0; j--)
arguments.Push(rspArguments[j]);
continue;
}
arguments.Push(args[i]);
}

TeamCity = Environment.GetEnvironmentVariable("TEAMCITY_PROJECT_NAME") != null;
AppVeyor = Environment.GetEnvironmentVariable("APPVEYOR_API_URL") != null;
Project = Parse(fileExists);
}

/// <summary>
/// Parse a response file passed as a command-line arguments.
/// No verification here to make this completely opaque
/// </summary>
/// <param name="responseFile">Path to the response file</param>
/// <param name="arguments">The data structure in</param>
private IList<string> ParseResponseFile(string responseFile)
{

var argumentsList = new List<string>();

if (!File.Exists(responseFile))
throw new ArgumentException(String.Format("Response file {0} not found", responseFile));

// Add contents from the text file to the command line
foreach (string line in File.ReadAllLines(responseFile))
{
string cleanLine = line.Trim();
if (string.IsNullOrEmpty(cleanLine))
continue;
var rspArguments = cleanLine.Split();
foreach(string arg in rspArguments)
argumentsList.Add(arg);
}

return argumentsList;
}

public bool AppVeyor { get; protected set; }

public int? MaxParallelThreads { get; set; }

public XunitProject Project { get; protected set; }
public ExtendedXunitProject Project { get; protected set; }

public bool? ParallelizeAssemblies { get; protected set; }

Expand All @@ -40,9 +79,9 @@ protected CommandLine(string[] args, Predicate<string> fileExists = null)
public bool Wait { get; protected set; }


static XunitProject GetProjectFile(List<Tuple<string, string>> assemblies)
static ExtendedXunitProject GetProjectFile(List<Tuple<string, string>> assemblies)
{
var result = new XunitProject();
var result = new ExtendedXunitProject();

foreach (var assembly in assemblies)
result.Add(new XunitProjectAssembly
Expand All @@ -65,7 +104,7 @@ public static CommandLine Parse(params string[] args)
return new CommandLine(args);
}

protected XunitProject Parse(Predicate<string> fileExists)
protected ExtendedXunitProject Parse(Predicate<string> fileExists)
{
var assemblies = new List<Tuple<string, string>>();

Expand Down Expand Up @@ -223,6 +262,25 @@ protected XunitProject Parse(Predicate<string> fileExists)

project.Filters.IncludedMethods.Add(option.Value);
}
else if (optionName == "-skipmethod")
{
if (option.Value == null)
throw new ArgumentException("missing argument for -skipmethod");
project.Filters.ExcludedMethods.Add(option.Value);

}
else if (optionName == "-skipclass")
{
if (option.Value == null)
throw new ArgumentException("missing argument for -skipclass");
project.Filters.ExcludedClasses.Add(option.Value);
}
else if (optionName == "-skipnamespace")
{
if (option.Value == null)
throw new ArgumentException("missing argument for -skipnamespace");
project.Filters.ExcludedNamespaces.Add(option.Value);
}
else
{
if (option.Value == null)
Expand Down
59 changes: 59 additions & 0 deletions src/xunit.console.netcore/Filters/ExtendedXunitFilters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Xunit.Abstractions;

namespace Xunit.ConsoleClient.Filters
{
/// <summary>
/// Wrapper class, which hides XunitFilters' Filter method and adds logic to exclude methods or namespaces
/// </summary>
public class ExtendedXunitFilters : XunitFilters
{
public HashSet<string> ExcludedMethods { get; private set; }
public HashSet<string> ExcludedClasses { get; private set; }
public HashSet<string> ExcludedNamespaces { get; private set; }

public ExtendedXunitFilters() : base()
{
ExcludedMethods = new HashSet<string>();
ExcludedClasses = new HashSet<string>();
ExcludedNamespaces = new HashSet<string>();
}

/// <summary>
/// Determine whether a passed test case should run
/// </summary>
/// <param name="testCase">Test case to filter</param>
/// <returns>Boolean - True runs the test case, False skips</returns>
public new bool Filter(ITestCase testCase)
{
// Exclusions supersede inclusions - i.e. if a method/class/namespace is both included and excluded it won't run
return FilterExcludedMethodsAndClasses(testCase) && base.Filter(testCase);
}

bool FilterExcludedMethodsAndClasses(ITestCase testCase)
{
// If no explicit exclusions have been defined, return true
if (ExcludedMethods.Count == 0 && ExcludedClasses.Count == 0 && ExcludedNamespaces.Count == 0)
return true;

if (ExcludedClasses.Count != 0 && ExcludedClasses.Contains(testCase.TestMethod.TestClass.Class.Name))
return false;

var methodName = $"{testCase.TestMethod.TestClass.Class.Name}.{testCase.TestMethod.Method.Name}";

if (ExcludedMethods.Count != 0 && ExcludedMethods.Contains(methodName))
return false;

if (ExcludedNamespaces.Count != 0 && ExcludedNamespaces.Any(a => testCase.TestMethod.TestClass.Class.Name.StartsWith($"{a}.", StringComparison.Ordinal)))
return false;

return true;
}

}
}
6 changes: 4 additions & 2 deletions src/xunit.console.netcore/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
using System.Reflection;
using System.Threading.Tasks;
using System.Xml.Linq;
using Xunit.ConsoleClient.Filters;
using Xunit.ConsoleClient.Project;

namespace Xunit.ConsoleClient
{
Expand Down Expand Up @@ -175,7 +177,7 @@ static void PrintUsage()
);
}

static int RunProject(string defaultDirectory, XunitProject project, bool teamcity, bool appVeyor, bool showProgress, bool? parallelizeAssemblies, bool? parallelizeTestCollections, int? maxThreadCount)
static int RunProject(string defaultDirectory, ExtendedXunitProject project, bool teamcity, bool appVeyor, bool showProgress, bool? parallelizeAssemblies, bool? parallelizeTestCollections, int? maxThreadCount)
{
XElement assembliesElement = null;
var xmlTransformers = TransformFactory.GetXmlTransformers(project);
Expand Down Expand Up @@ -280,7 +282,7 @@ static XmlTestExecutionVisitor CreateVisitor(object consoleLock, string defaultD
return new StandardOutputVisitor(consoleLock, defaultDirectory, assemblyElement, () => cancel, completionMessages, showProgress);
}

static XElement ExecuteAssembly(object consoleLock, string defaultDirectory, XunitProjectAssembly assembly, bool needsXml, bool teamCity, bool appVeyor, bool showProgress, bool? parallelizeTestCollections, int? maxThreadCount, XunitFilters filters)
static XElement ExecuteAssembly(object consoleLock, string defaultDirectory, XunitProjectAssembly assembly, bool needsXml, bool teamCity, bool appVeyor, bool showProgress, bool? parallelizeTestCollections, int? maxThreadCount, ExtendedXunitFilters filters)
{
if (cancel)
return null;
Expand Down
18 changes: 18 additions & 0 deletions src/xunit.console.netcore/Project/ExtendedXunitProject.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit.ConsoleClient.Filters;

namespace Xunit.ConsoleClient.Project
{
public class ExtendedXunitProject : XunitProject
{
public new ExtendedXunitFilters Filters { get; private set; }
public ExtendedXunitProject() : base()
{
Filters = new ExtendedXunitFilters();
}
}
}
3 changes: 2 additions & 1 deletion src/xunit.console.netcore/Utility/TransformFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Reflection;
using System.Xml;
using System.Xml.Linq;
using Xunit.ConsoleClient.Project;

#if !NETCORE
using System.Configuration;
Expand Down Expand Up @@ -50,7 +51,7 @@ public static List<Transform> AvailableTransforms
get { return instance.availableTransforms.Values.ToList(); }
}

public static List<Action<XElement>> GetXmlTransformers(XunitProject project)
public static List<Action<XElement>> GetXmlTransformers(ExtendedXunitProject project)
{
return project.Output.Select(output => new Action<XElement>(xml => instance.availableTransforms[output.Key].OutputHandler(xml, output.Value))).ToList();
}
Expand Down
2 changes: 2 additions & 0 deletions src/xunit.console.netcore/xunit.console.netcore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
<Link>Common\TestDiscoveryVisitor.cs</Link>
</Compile>
<Compile Include="CommandLine.cs" />
<Compile Include="Filters\ExtendedXunitFilters.cs" />
<Compile Include="Program.cs" />
<Compile Include="Project\ExtendedXunitProject.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RunnerCallbacks\RunnerCallback.cs" />
<Compile Include="RunnerCallbacks\StandardRunnerCallback.cs" />
Expand Down