private bool TryCreateInjectionControllerCore(ExceptionAggregator aggregator, out IXunitInjectionController controller) { var asm = Assembly.Load(_assemblyName); if (asm == null) { aggregator.Add(new InvalidOperationException($"Cannot load assembly: {_assemblyName}")); controller = null; return(false); } var typ = asm.GetType(_typeName); if (typ == null) { aggregator.Add(new InvalidOperationException($"Cannot find type: {_typeName}")); controller = null; return(false); } var method = typ.GetMethod(_methodName, BindingFlags.Static | BindingFlags.Public, Type.DefaultBinder, Type.EmptyTypes, new ParameterModifier[0]); if (method == null) { aggregator.Add(new InvalidOperationException($"Cannot find public static parameter-less method: {_methodName}")); controller = null; return(false); } if (method.ReturnType != typeof(IServiceProvider)) { aggregator.Add(new InvalidOperationException($"{_methodName} does not return an {nameof(IServiceProvider)}")); controller = null; return(false); } // Invoke the method var result = method.Invoke(null, new object[0]); if (result == null) { aggregator.Add(new InvalidOperationException($"{_methodName} returned null")); controller = null; return(false); } controller = new ServiceProviderXunitInjectionController((IServiceProvider)result); return(true); }
public bool TryCreateInjectionControllerForAssembly(ExceptionAggregator aggregator, IReflectionAssemblyInfo assembly, out IXunitInjectionController controller) { if (TryFindStartupType(assembly, out var type)) { // TODO: Use generic host? // Check for a ConfigureServices method var configureServicesMethod = type.GetMethod("ConfigureServices", BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new[] { typeof(IServiceCollection) }, new ParameterModifier[0]); if (configureServicesMethod == null) { aggregator.Add(new InvalidOperationException($"Could not find appropriate ConfigureServices method on TestStartup type {type.FullName}")); controller = null; return(false); } // Create the service collection var services = new ServiceCollection(); try { // Activate the type var startup = Activator.CreateInstance(type); // Configure the services configureServicesMethod.Invoke(startup, new object[] { services }); } catch (TargetInvocationException tex) { aggregator.Add(tex.InnerException); controller = null; return(false); } catch (Exception ex) { aggregator.Add(ex); controller = null; return(false); } // Create a ServiceProvider-based controller from the service provider controller = new ServiceProviderXunitInjectionController(services.BuildServiceProvider()); return(true); } aggregator.Add(new InvalidOperationException("Could not find TestStartup class in target assembly")); controller = null; return(false); }
public static TestableTestMethodRunner Create( IMessageBus messageBus = null, ITestCase[] testCases = null, RunSummary result = null, Exception aggregatorSeedException = null, bool cancelInRunTestCaseAsync = false) { if (testCases == null) { testCases = new[] { Mocks.TestCase <ClassUnderTest>("Passing") } } ; var firstTestCase = testCases.First(); var aggregator = new ExceptionAggregator(); if (aggregatorSeedException != null) { aggregator.Add(aggregatorSeedException); } return(new TestableTestMethodRunner( firstTestCase.TestMethod, (IReflectionTypeInfo)firstTestCase.TestMethod.TestClass.Class, (IReflectionMethodInfo)firstTestCase.TestMethod.Method, testCases, messageBus ?? new SpyMessageBus(), aggregator, new CancellationTokenSource(), result ?? new RunSummary(), cancelInRunTestCaseAsync )); }
public static TestableTestCollectionRunner Create( IMessageBus?messageBus = null, _ITestCase[]?testCases = null, RunSummary?result = null, Exception?aggregatorSeedException = null, bool cancelInRunTestClassAsync = false) { if (testCases == null) { testCases = new[] { Mocks.TestCase <ClassUnderTest>("Passing") } } ; var aggregator = new ExceptionAggregator(); if (aggregatorSeedException != null) { aggregator.Add(aggregatorSeedException); } return(new TestableTestCollectionRunner( testCases.First().TestCollection, testCases, messageBus ?? new SpyMessageBus(), new MockTestCaseOrderer(), aggregator, new CancellationTokenSource(), result ?? new RunSummary(), cancelInRunTestClassAsync )); }
public static TestableTestMethodRunner Create( IMessageBus?messageBus = null, _ITestCase[]?testCases = null, RunSummary?result = null, Exception?aggregatorSeedException = null, bool cancelInRunTestCaseAsync = false) { if (testCases == null) { testCases = new[] { Mocks.TestCase <ClassUnderTest>("Passing") } } ; var firstTestCase = testCases.First(); var aggregator = new ExceptionAggregator(); if (aggregatorSeedException != null) { aggregator.Add(aggregatorSeedException); } return(new TestableTestMethodRunner( firstTestCase.TestClass ?? throw new InvalidOperationException("testCase.TestClass must not be null"), firstTestCase.TestMethod ?? throw new InvalidOperationException("testCase.TestMethod must not be null"), firstTestCase.TestClass.Class as _IReflectionTypeInfo ?? throw new InvalidOperationException("testCase.TestClass.Class must be based on reflection"), firstTestCase.TestMethod.Method as _IReflectionMethodInfo ?? throw new InvalidOperationException("testCase.TestMethod.Method must be based on reflection"), testCases, messageBus ?? new SpyMessageBus(), aggregator, new CancellationTokenSource(), result ?? new RunSummary(), cancelInRunTestCaseAsync )); }
public static TestableTestRunner Create(IMessageBus messageBus, ITestCase testCase = null, string displayName = null, string skipReason = null, decimal runTime = 0m, string output = "", Exception aggregatorSeedException = null, Action lambda = null) { var aggregator = new ExceptionAggregator(); if (aggregatorSeedException != null) { aggregator.Add(aggregatorSeedException); } if (testCase == null) { testCase = Mocks.TestCase <object>("ToString"); } var test = Mocks.Test(testCase, displayName); return(new TestableTestRunner( test, messageBus, typeof(object), new object[0], typeof(object).GetMethod("ToString"), new object[0], skipReason, aggregator, new CancellationTokenSource(), runTime, output, lambda)); }
public static async Task Invoke(this Func <Task> action, ExceptionAggregator aggregator, ExecutionTimer timer) { var oldSyncContext = SynchronizationContext.Current; try { var asyncSyncContext = new AsyncTestSyncContext(oldSyncContext); SetSynchronizationContext(asyncSyncContext); await aggregator?.RunAsync( () => timer.AggregateAsync( async() => { await action(); var ex = await asyncSyncContext.WaitForCompletionAsync(); if (ex != null) { aggregator.Add(ex); } })); } finally { SetSynchronizationContext(oldSyncContext); } }
private async Task <RunSummary> RunAsyncCore(VsixTestCase testCase, IMessageBus messageBus, ExceptionAggregator aggregator) { if (!EnsureConnected(testCase, messageBus)) { return(new RunSummary { Failed = 1, }); } var xunitTest = new XunitTest(testCase, testCase.DisplayName); try { var remoteBus = _remoteBuses.GetOrAdd(messageBus, bus => { var instance = new RemoteMessageBus(bus); _remoteObjects.Add(instance); return(instance); }); var outputBus = new TraceOutputMessageBus(remoteBus); var summary = await Task.Run( () => _runner.Run(testCase, outputBus)) .TimeoutAfter(testCase.TimeoutSeconds * 1000); if (summary.Exception != null) { aggregator.Add(summary.Exception); } return(summary.ToRunSummary()); } catch (Exception ex) { if (ex is RemotingException || ex is TimeoutException) { Stop(); } aggregator.Add(ex); messageBus.QueueMessage(new TestFailed(xunitTest, 0, ex.Message, ex)); return(new RunSummary { Failed = 1 }); } }
// This method is called by the xUnit test framework class es to run the test case. We will do the // loop here, forwarding on to the implementation in XunitTestCase to do the heavy lifting. We will // continue to re-run the test until the aggregator has an error (meaning that some internal error // condition happened), or the test runs without failure, or we've hit the maximum number of tries. /// <inheritdoc /> public override async Task <RunSummary> RunAsync( IMessageSink diagnosticMessageSink, IMessageBus messageBus, object[] constructorArguments, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource) { int runCount = 0; while (true) { // This is really the only tricky bit: we need to capture and delay messages (since those will // contain run status) until we know we've decided to accept the final result; var delayedMessageBus = new DelayedMessageBus(messageBus); try { var summary = await base.RunAsync( diagnosticMessageSink, delayedMessageBus, constructorArguments, aggregator, cancellationTokenSource).WithTimeout(30_000); if (aggregator.HasExceptions || summary.Failed == 0 || ++runCount >= _maxRetries) { delayedMessageBus.Dispose(); // Sends all the delayed messages return(summary); } } catch (TimeoutException ex) { if (++runCount >= _maxRetries) { var runSummary = new RunSummary { Total = 1, Failed = 1 }; aggregator.Add(ex); if (!delayedMessageBus.QueueMessage(new TestCleanupFailure( new XunitTest(this, DisplayName), aggregator.ToException() !))) { cancellationTokenSource.Cancel(); } delayedMessageBus.Dispose(); // Sends all the delayed messages return(runSummary); } } diagnosticMessageSink.OnMessage( new DiagnosticMessage("Execution of '{0}' failed (attempt #{1}), retrying...", DisplayName, runCount)); GC.Collect(); await Task.Delay(100); } }
public static ExceptionAggregator CreateExceptionAggregator(Exception exception) { var aggregator = new ExceptionAggregator(); if (exception != null) { if (exception is AggregateException aggregateException) { foreach (var innerException in aggregateException.InnerExceptions) { aggregator.Add(innerException); } } else { aggregator.Add(exception); } } return(aggregator); }
private bool TryCreateInjectionControllerCore(ExceptionAggregator aggregator, out IXunitInjectionController controller) { var asm = Assembly.Load(_assemblyName); if (asm == null) { aggregator.Add(new InvalidOperationException($"Cannot load assembly: {_assemblyName}")); controller = null; return(false); } var typ = asm.GetType(_typeName); if (typ == null) { aggregator.Add(new InvalidOperationException($"Cannot find type: {_typeName}")); controller = null; return(false); } controller = (IXunitInjectionController)Activator.CreateInstance(typ); return(true); }
public static TestableTestCaseRunner Create(IMessageBus messageBus, ITestCase testCase = null, RunSummary result = null, Exception aggregatorSeedException = null) { var aggregator = new ExceptionAggregator(); if (aggregatorSeedException != null) { aggregator.Add(aggregatorSeedException); } return(new TestableTestCaseRunner( testCase ?? Mocks.TestCase <Object>("ToString"), messageBus, aggregator, new CancellationTokenSource(), result ?? new RunSummary() )); }
public static TestableTestClassRunner Create( IMessageBus messageBus = null, ITestCase[] testCases = null, ITestCaseOrderer orderer = null, ConstructorInfo constructor = null, object[] availableArguments = null, RunSummary result = null, Exception aggregatorSeedException = null, bool cancelInRunTestMethodAsync = false) { if (testCases == null) { testCases = new[] { Mocks.TestCase <ClassUnderTest>("Passing") } } ; if (availableArguments == null) { availableArguments = new object[0]; } var firstTest = testCases.First(); var aggregator = new ExceptionAggregator(); if (aggregatorSeedException != null) { aggregator.Add(aggregatorSeedException); } return(new TestableTestClassRunner( firstTest.TestMethod.TestClass, (IReflectionTypeInfo)firstTest.TestMethod.TestClass.Class, testCases, new List <IMessageSinkMessage>(), messageBus ?? new SpyMessageBus(), orderer ?? new MockTestCaseOrderer(), aggregator, new CancellationTokenSource(), constructor, availableArguments, result ?? new RunSummary(), cancelInRunTestMethodAsync )); }
protected override async Task AfterTestCaseStartingAsync() { await base.AfterTestCaseStartingAsync(); try { var scenarioAttributes = TestCase.TestMethod.GetScenarioAttributes(DiagnosticMessageSink); if (!scenarioAttributes.Any()) { throw new InvalidOperationException( $"No scenario specified for {TestCase.TestMethod.TestClass.Class.Name}.{TestCase.TestMethod.Method.Name}. Make sure to add at least one ScenarioAttribute to the test method or class."); } foreach (var scenarioAttribute in scenarioAttributes) { IScenarioIdentifier scenarioIdentifier = null; var testRunnerAggregator = new ExceptionAggregator(Aggregator); var skipReason = scenarioAttribute.GetNamedArgument <string>("Skip"); try { var scenarioDiscoverer = ScenarioDiscovererFactory.GetDiscoverer(DiagnosticMessageSink, scenarioAttribute); scenarioIdentifier = scenarioDiscoverer.GetScenarioIdentifier(scenarioAttribute); } catch (Exception exception) { scenarioIdentifier = new DummyScenarioDiscoverer().GetScenarioIdentifier(scenarioAttribute); testRunnerAggregator.Add(exception); } var test = CreateTest(TestCase, scenarioIdentifier); var testRunner = new ScenarioTestRunner(test, DiagnosticMessageSink, MessageBus, TestClass, ConstructorArguments, TestMethod, TestMethodArguments, skipReason, BeforeAfterAttributes, testRunnerAggregator, CancellationTokenSource); _testRunners.Add(testRunner); } } catch (Exception ex) { ScenarioDiscoveryException = ex; } }
public static TestableTestClassRunner Create( IMessageBus?messageBus = null, _ITestCase[]?testCases = null, ITestCaseOrderer?orderer = null, ConstructorInfo?constructor = null, object[]?availableArguments = null, RunSummary?result = null, Exception?aggregatorSeedException = null, bool cancelInRunTestMethodAsync = false) { if (testCases == null) { testCases = new[] { Mocks.TestCase <ClassUnderTest>("Passing") } } ; if (availableArguments == null) { availableArguments = new object[0]; } var firstTest = testCases.First(); var aggregator = new ExceptionAggregator(); if (aggregatorSeedException != null) { aggregator.Add(aggregatorSeedException); } return(new TestableTestClassRunner( firstTest.TestClass ?? throw new InvalidOperationException("testCase.TestClass must not be null"), firstTest.TestClass.Class as _IReflectionTypeInfo ?? throw new InvalidOperationException("testCase.TestClass.Class must be based on reflection"), testCases, messageBus ?? new SpyMessageBus(), orderer ?? new MockTestCaseOrderer(), aggregator, new CancellationTokenSource(), constructor, availableArguments, result ?? new RunSummary(), cancelInRunTestMethodAsync )); }
public bool TryGetConstructorArgument(ExceptionAggregator exceptionAggregator, ConstructorInfo constructor, int index, ParameterInfo parameter, out object argumentValue) { try { // Try to resolve it out of the service provider var service = _serviceProvider.GetService(parameter.ParameterType); if (service != null) { argumentValue = service; return(true); } } catch (Exception ex) { exceptionAggregator.Add(ex); } argumentValue = null; return(false); }
public bool TryGetConstructorArgument(IServiceProvider provider, ExceptionAggregator aggregator, out object?argumentValue) { argumentValue = null; try { argumentValue = provider.GetService(Parameter.ParameterType); } catch (Exception ex) { aggregator.Add(ex); return(true); } if (argumentValue != null) { return(true); } if (Parameter.HasDefaultValue) { argumentValue = Parameter.DefaultValue; } else if (Parameter.IsOptional) { argumentValue = GetDefaultValue(Parameter.ParameterType); } else if (Parameter.GetCustomAttribute <ParamArrayAttribute>() != null) { argumentValue = Array.CreateInstance(Parameter.ParameterType, new int[1]); } else { return(false); } return(true); }
protected internal static object?[] CreateTestClassConstructorArguments(IServiceProvider provider, object?[] constructorArguments, ExceptionAggregator aggregator) { var unusedArguments = new List <Tuple <int, ParameterInfo> >(); Func <IReadOnlyList <Tuple <int, ParameterInfo> >, string>?formatConstructorArgsMissingMessage = null; var args = new object?[constructorArguments.Length]; for (var index = 0; index < constructorArguments.Length; index++) { if (constructorArguments[index] is DependencyInjectionTestClassRunner.DelayArgument delay) { formatConstructorArgsMissingMessage = delay.FormatConstructorArgsMissingMessage; if (delay.TryGetConstructorArgument(provider, aggregator, out var arg)) { args[index] = arg; } else { unusedArguments.Add(Tuple.Create(index, delay.Parameter)); } } else { args[index] = constructorArguments[index]; } } if (unusedArguments.Count > 0 && formatConstructorArgsMissingMessage != null) { aggregator.Add(new TestClassException(formatConstructorArgsMissingMessage(unusedArguments))); } return(args); }