/// <summary> /// Returns an implementation of <see cref="IFrontController"/> which can be used /// for both discovery and execution. /// </summary> /// <param name="projectAssembly">The test project assembly.</param> /// <param name="sourceInformationProvider">The source information provider. If <c>null</c>, uses the default (<see cref="T:Xunit.VisualStudioSourceInformationProvider"/>).</param> /// <param name="diagnosticMessageSink">The message sink which receives <see cref="_DiagnosticMessage"/> messages.</param> public static IFrontController ForDiscoveryAndExecution( XunitProjectAssembly projectAssembly, _ISourceInformationProvider?sourceInformationProvider = null, _IMessageSink?diagnosticMessageSink = null) { Guard.ArgumentNotNull(projectAssembly); var innerController = default(IFrontController); var assemblyFileName = projectAssembly.AssemblyFileName; var assemblyFolder = Path.GetDirectoryName(assemblyFileName); if (diagnosticMessageSink == null) { diagnosticMessageSink = _NullMessageSink.Instance; } #if NETFRAMEWORK if (sourceInformationProvider == null) { if (assemblyFileName == null) { sourceInformationProvider = _NullSourceInformationProvider.Instance; } else { sourceInformationProvider = new VisualStudioSourceInformationProvider(assemblyFileName, diagnosticMessageSink); } } if (assemblyFolder != null) { if (Directory.EnumerateFiles(assemblyFolder, "xunit.execution.*.dll").Any()) { innerController = Xunit2.ForDiscoveryAndExecution(projectAssembly, sourceInformationProvider, diagnosticMessageSink); } else { var xunitPath = Path.Combine(assemblyFolder, "xunit.dll"); if (File.Exists(xunitPath)) { innerController = Xunit1.ForDiscoveryAndExecution(projectAssembly, sourceInformationProvider, diagnosticMessageSink); } } } #else if (sourceInformationProvider == null) { sourceInformationProvider = _NullSourceInformationProvider.Instance; } innerController = Xunit2.ForDiscoveryAndExecution(projectAssembly, sourceInformationProvider, diagnosticMessageSink); #endif if (innerController == null) { throw new InvalidOperationException($"Unknown test framework: could not find xunit.dll (v1) or xunit.execution.*.dll (v2) in {assemblyFolder ?? "<unknown assembly folder>"}"); } return(new XunitFrontController(innerController)); }
public void FactAcceptanceTest() { string code = @" using System; using Xunit; namespace Namespace1 { public class Class1 { [Fact] [Trait(""Name!"", ""Value!"")] public void Trait() { } [Fact(Skip=""Skipping"")] public void Skipped() { } [Fact(DisplayName=""Custom Test Name"")] public void CustomName() { } } } namespace Namespace2 { public class OuterClass { public class Class2 { [Fact] public void TestMethod() { } } } } "; using (var assembly = new AcceptanceTestAssembly(code)) using (var controller = new Xunit2(assembly.FileName, null, true)) { var sink = new SpyMessageSink<IDiscoveryCompleteMessage>(); controller.Find(includeSourceInformation: false, messageSink: sink); sink.Finished.WaitOne(); ITestCase[] testCases = sink.Messages.OfType<ITestCaseDiscoveryMessage>().Select(tcdm => tcdm.TestCase).ToArray(); Assert.Equal(4, testCases.Length); ITestCase traitTest = Assert.Single(testCases, tc => tc.DisplayName == "Namespace1.Class1.Trait"); KeyValuePair<string, string> kvp = Assert.Single(traitTest.Traits); Assert.Equal("Name!", kvp.Key); Assert.Equal("Value!", kvp.Value); ITestCase skipped = Assert.Single(testCases, tc => tc.DisplayName == "Namespace1.Class1.Skipped"); Assert.Equal("Skipping", skipped.SkipReason); Assert.Single(testCases, tc => tc.DisplayName == "Custom Test Name"); Assert.Single(testCases, tc => tc.DisplayName == "Namespace2.OuterClass+Class2.TestMethod"); } }
// Factory methods /// <summary> /// Returns an implementation of <see cref="IFrontControllerDiscoverer"/> which can be /// used to discovery tests, including source-based discovery (note that xUnit.net v1 /// does not support source-based discovery). /// </summary> /// <param name="assemblyInfo">The assembly to use for discovery</param> /// <param name="projectAssembly">The test project assembly.</param> /// <param name="referenceList">The full path names of all referenced assemblies. This is used to /// search for references to specific xUnit.net reference assemblies to determine which version /// of xUnit.net the tests were written against.</param> /// <param name="sourceInformationProvider">The optional source information provider.</param> /// <param name="diagnosticMessageSink">The message sink which receives <see cref="_DiagnosticMessage"/> messages.</param> /// <returns></returns> public static IFrontControllerDiscoverer ForDiscovery( _IAssemblyInfo assemblyInfo, XunitProjectAssembly projectAssembly, IReadOnlyCollection <string> referenceList, _ISourceInformationProvider?sourceInformationProvider = null, _IMessageSink?diagnosticMessageSink = null) { Guard.ArgumentNotNull(assemblyInfo); Guard.ArgumentNotNull(projectAssembly); Guard.ArgumentNotNull(referenceList); var innerDiscoverer = default(IFrontControllerDiscoverer); var assemblyFileName = projectAssembly.AssemblyFileName; if (diagnosticMessageSink == null) { diagnosticMessageSink = _NullMessageSink.Instance; } if (sourceInformationProvider == null) { sourceInformationProvider = _NullSourceInformationProvider.Instance; #if NETFRAMEWORK if (assemblyFileName != null) { sourceInformationProvider = new VisualStudioSourceInformationProvider(assemblyFileName, diagnosticMessageSink); } #endif } var v2PathPattern = new Regex(@"^xunit\.execution\..*\.dll$"); var v2ExecutionReference = referenceList.FirstOrDefault(reference => v2PathPattern.IsMatch(Path.GetFileNameWithoutExtension(reference))); if (v2ExecutionReference != null) { innerDiscoverer = Xunit2.ForDiscovery(assemblyInfo, projectAssembly, v2ExecutionReference, sourceInformationProvider, diagnosticMessageSink); } #if NETFRAMEWORK if (referenceList.Any(reference => Path.GetFileNameWithoutExtension(reference) == "xunit.dll")) { innerDiscoverer = Xunit1.ForDiscoveryAndExecution(projectAssembly, sourceInformationProvider, diagnosticMessageSink); } #endif if (innerDiscoverer == null) { throw new InvalidOperationException($"Unknown test framework: could not find xunit.dll (v1) or xunit.execution.*.dll (v2) in assembly reference list"); } return(new XunitFrontController(innerDiscoverer)); }
public void NoTestMethods() { using (var assm = new AcceptanceTestAssembly(code: "")) using (var controller = new Xunit2(assm.FileName, null, true)) { var sink = new SpyMessageSink<IDiscoveryCompleteMessage>(); controller.Find(includeSourceInformation: false, messageSink: sink); sink.Finished.WaitOne(); Assert.False(sink.Messages.Any(msg => msg is ITestCaseDiscoveryMessage)); } }
public void TheoryWithInlineData() { string code = @" using System; using Xunit; public class TestClass { [Theory] [InlineData] [InlineData(42)] [InlineData(42, 21.12)] public void TestMethod(int x) { } } "; using (var assembly = new AcceptanceTestAssembly(code)) using (var controller = new Xunit2(assembly.FileName, null, true)) { var sink = new SpyMessageSink<IDiscoveryCompleteMessage>(); controller.Find(includeSourceInformation: false, messageSink: sink); sink.Finished.WaitOne(); string[] testCaseNames = sink.Messages.OfType<ITestCaseDiscoveryMessage>().Select(tcdm => tcdm.TestCase.DisplayName).ToArray(); Assert.Equal(3, testCaseNames.Length); Assert.Contains("TestClass.TestMethod(x: ???)", testCaseNames); Assert.Contains("TestClass.TestMethod(x: 42)", testCaseNames); Assert.Contains("TestClass.TestMethod(x: 42, ???: 21.12)", testCaseNames); } }
public void SingleTestMethod() { string code = @" using Xunit; public class Foo { [Fact] public void Bar() { } } "; using (var assm = new AcceptanceTestAssembly(code)) using (var controller = new Xunit2(assm.FileName, null, true)) { var sink = new SpyMessageSink<IDiscoveryCompleteMessage>(); controller.Find(includeSourceInformation: false, messageSink: sink); sink.Finished.WaitOne(); ITestCase testCase = sink.Messages.OfType<ITestCaseDiscoveryMessage>().Single().TestCase; Assert.Equal("Foo.Bar", testCase.DisplayName); } }
/// <summary> /// Initializes a new instance of the <see cref="XunitFrontController"/> class. /// </summary> /// <param name="assemblyFileName">The test assembly.</param> /// <param name="configFileName">The test assembly configuration file.</param> /// <param name="shadowCopy">If set to <c>true</c>, runs tests in a shadow copied app domain, which allows /// tests to be discovered and run without locking assembly files on disk.</param> public XunitFrontController(string assemblyFileName, string configFileName = null, bool shadowCopy = true) { xunit2 = new Xunit2(assemblyFileName, configFileName, shadowCopy); }