/// <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(nameof(projectAssembly), projectAssembly); var innerController = default(IFrontController); var assemblyFileName = projectAssembly.AssemblyFilename; var assemblyFolder = Path.GetDirectoryName(assemblyFileName); if (diagnosticMessageSink == null) { diagnosticMessageSink = new _NullMessageSink(); } #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)); }
// 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, IEnumerable <string> referenceList, _ISourceInformationProvider?sourceInformationProvider = null, _IMessageSink?diagnosticMessageSink = null) { Guard.ArgumentNotNull(nameof(assemblyInfo), assemblyInfo); Guard.ArgumentNotNull(nameof(projectAssembly), projectAssembly); Guard.ArgumentNotNull(nameof(referenceList), referenceList); var innerDiscoverer = default(IFrontControllerDiscoverer); var assemblyFileName = projectAssembly.AssemblyFilename; if (diagnosticMessageSink == null) { diagnosticMessageSink = new _NullMessageSink(); } 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 Task <List <_MessageSinkMessage> > RunAsync(Type[] types) { var tcs = new TaskCompletionSource <List <_MessageSinkMessage> >(); ThreadPool.QueueUserWorkItem(async _ => { try { var diagnosticMessageSink = new _NullMessageSink(); await using var testFramework = new XunitTestFramework(diagnosticMessageSink, configFileName: null); using var discoverySink = SpyMessageSink <_DiscoveryComplete> .Create(); var assemblyInfo = Reflector.Wrap(Assembly.GetEntryAssembly() !); var discoverer = testFramework.GetDiscoverer(assemblyInfo); foreach (var type in types) { discoverer.Find(type.FullName !, discoverySink, _TestFrameworkOptions.ForDiscovery()); discoverySink.Finished.WaitOne(); discoverySink.Finished.Reset(); } var testCases = discoverySink.Messages.OfType <_TestCaseDiscovered>().Select(msg => msg.Serialization).ToArray(); using var runSink = SpyMessageSink <_TestAssemblyFinished> .Create(); var executor = testFramework.GetExecutor(assemblyInfo); executor.RunTests(testCases, runSink, _TestFrameworkOptions.ForExecution()); runSink.Finished.WaitOne(); tcs.TrySetResult(runSink.Messages.ToList()); } catch (Exception ex) { tcs.TrySetException(ex); } }); return(tcs.Task); }
/// <summary> /// Get the traits from a method. /// </summary> /// <param name="member">The member (method, field, etc.) to get the traits for.</param> /// <returns>A list of traits that are defined on the method.</returns> public static IReadOnlyList <KeyValuePair <string, string> > GetTraits(MemberInfo member) { Guard.ArgumentNotNull(nameof(member), member); var messageSink = new _NullMessageSink(); var result = new List <KeyValuePair <string, string> >(); foreach (var traitAttributeData in member.CustomAttributes) { var traitAttributeType = traitAttributeData.AttributeType; if (!typeof(ITraitAttribute).IsAssignableFrom(traitAttributeType)) { continue; } var discovererAttributeData = FindDiscovererAttributeType(traitAttributeType); if (discovererAttributeData == null) { continue; } var discoverer = ExtensibilityPointFactory.GetTraitDiscoverer(messageSink, Reflector.Wrap(discovererAttributeData)); if (discoverer == null) { continue; } var traits = discoverer.GetTraits(Reflector.Wrap(traitAttributeData)); if (traits != null) { result.AddRange(traits); } } return(result); }