/// <summary> /// Initializes a new instance of the <see cref="XunitTestCaseRunner"/> class. /// </summary> /// <param name="testCase">The test case to be run.</param> /// <param name="displayName">The display name of the test case.</param> /// <param name="skipReason">The skip reason, if the test is to be skipped.</param> /// <param name="constructorArguments">The arguments to be passed to the test class constructor.</param> /// <param name="testMethodArguments">The arguments to be passed to the test method.</param> /// <param name="messageBus">The message bus to report run status to.</param> /// <param name="aggregator">The exception aggregator used to run code and collect exceptions.</param> /// <param name="cancellationTokenSource">The task cancellation token source, used to cancel the test run.</param> public XunitTestCaseRunner(IXunitTestCase testCase, string displayName, string skipReason, object[] constructorArguments, object[] testMethodArguments, IMessageBus messageBus, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource) : base(testCase, messageBus, aggregator, cancellationTokenSource) { DisplayName = displayName; SkipReason = skipReason; ConstructorArguments = constructorArguments; TestClass = TestCase.TestMethod.TestClass.Class.ToRuntimeType(); TestMethod = TestCase.Method.ToRuntimeMethod(); ParameterInfo[] parameters = TestMethod.GetParameters(); Type[] parameterTypes = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { parameterTypes[i] = parameters[i].ParameterType; } TestMethodArguments = Reflector.ConvertArguments(testMethodArguments, parameterTypes); beforeAfterAttributes = TestClass.GetTypeInfo().GetCustomAttributes(typeof(BeforeAfterTestAttribute)) .Concat(TestMethod.GetCustomAttributes(typeof(BeforeAfterTestAttribute))) .Cast <BeforeAfterTestAttribute>() .ToList(); }
/// <summary> /// Initializes a new instance of the <see cref="XunitTestCaseRunner"/> class. /// </summary> /// <param name="testCase">The test case to be run.</param> /// <param name="displayName">The display name of the test case.</param> /// <param name="skipReason">The skip reason, if the test is to be skipped.</param> /// <param name="constructorArguments">The arguments to be passed to the test class constructor.</param> /// <param name="testMethodArguments">The arguments to be passed to the test method.</param> /// <param name="messageBus">The message bus to report run status to.</param> /// <param name="aggregator">The exception aggregator used to run code and collect exceptions.</param> /// <param name="cancellationTokenSource">The task cancellation token source, used to cancel the test run.</param> public XunitTestCaseRunner(IXunitTestCase testCase, string displayName, string skipReason, object[] constructorArguments, object[] testMethodArguments, IMessageBus messageBus, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource) : base(testCase, messageBus, aggregator, cancellationTokenSource) { DisplayName = displayName; SkipReason = skipReason; ConstructorArguments = constructorArguments; TestClass = GetRuntimeClass(); TestMethod = GetRuntimeMethod(); var parameterTypes = TestMethod.GetParameters().Select(p => p.ParameterType).ToArray(); TestMethodArguments = Reflector.ConvertArguments(testMethodArguments, parameterTypes); beforeAfterAttributes = TestClass.GetTypeInfo().GetCustomAttributes(typeof(BeforeAfterTestAttribute)) .Concat(TestMethod.GetCustomAttributes(typeof(BeforeAfterTestAttribute))) .Cast <BeforeAfterTestAttribute>() .ToList(); }
/// <summary> /// Initializes a new instance of the <see cref="XunitTestCaseRunner"/> class. /// </summary> /// <param name="testCase">The test case to be run.</param> /// <param name="displayName">The display name of the test case.</param> /// <param name="skipReason">The skip reason, if the test is to be skipped.</param> /// <param name="constructorArguments">The arguments to be passed to the test class constructor.</param> /// <param name="testMethodArguments">The arguments to be passed to the test method.</param> /// <param name="messageBus">The message bus to report run status to.</param> /// <param name="aggregator">The exception aggregator used to run code and collect exceptions.</param> /// <param name="cancellationTokenSource">The task cancellation token source, used to cancel the test run.</param> public XunitTestCaseRunner(IXunitTestCase testCase, string displayName, string skipReason, object[] constructorArguments, object[] testMethodArguments, IMessageBus messageBus, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource) : base(testCase, messageBus, aggregator, cancellationTokenSource) { DisplayName = displayName; SkipReason = skipReason; ConstructorArguments = constructorArguments; TestClass = TestCase.TestMethod.TestClass.Class.ToRuntimeType(); TestMethod = TestCase.Method.ToRuntimeMethod(); var parameters = TestMethod.GetParameters(); var parameterTypes = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { parameterTypes[i] = parameters[i].ParameterType; } TestMethodArguments = Reflector.ConvertArguments(testMethodArguments, parameterTypes); }
/// <summary> /// Invokes the test method on the given test class instance. This method sets up support for "async void" /// test methods, ensures that the test method has the correct number of arguments, then calls <see cref="CallTestMethod"/> /// to do the actual method invocation. It ensure that any async test method is fully completed before returning, and /// returns the measured clock time that the invocation took. /// </summary> /// <param name="testClassInstance">The test class instance</param> /// <returns>Returns the time taken to invoke the test method</returns> protected virtual async Task <decimal> InvokeTestMethodAsync(object testClassInstance) { var oldSyncContext = SynchronizationContext.Current; try { var asyncSyncContext = new AsyncTestSyncContext(oldSyncContext); SetSynchronizationContext(asyncSyncContext); await Aggregator.RunAsync( () => Timer.AggregateAsync( async() => { var parameterCount = TestMethod.GetParameters().Length; var valueCount = TestMethodArguments == null ? 0 : TestMethodArguments.Length; if (parameterCount != valueCount) { Aggregator.Add( new InvalidOperationException( $"The test method expected {parameterCount} parameter value{(parameterCount == 1 ? "" : "s")}, but {valueCount} parameter value{(valueCount == 1 ? "" : "s")} {(valueCount == 1 ? "was" : "were")} provided." ) ); } else { var result = CallTestMethod(testClassInstance); var task = GetTaskFromResult(result); if (task != null) { if (task.Status == TaskStatus.Created) { throw new InvalidOperationException("Test method returned a non-started Task (tasks must be started before being returned)"); } await task; } else { var ex = await asyncSyncContext.WaitForCompletionAsync(); if (ex != null) { Aggregator.Add(ex); } } } } ) ); } finally { SetSynchronizationContext(oldSyncContext); } return(Timer.Total); }
/// <summary> /// Invokes the test method on the given test class instance. /// </summary> /// <param name="testClassInstance">The test class instance</param> /// <returns>Returns the time taken to invoke the test method</returns> public virtual async Task <decimal> InvokeTestMethodAsync(object testClassInstance) { var oldSyncContext = SynchronizationContext.Current; try { var asyncSyncContext = new AsyncTestSyncContext(oldSyncContext); SetSynchronizationContext(asyncSyncContext); await Aggregator.RunAsync( () => Timer.AggregateAsync( async() => { var parameterCount = TestMethod.GetParameters().Length; var valueCount = TestMethodArguments == null ? 0 : TestMethodArguments.Length; if (parameterCount != valueCount) { Aggregator.Add( new InvalidOperationException( String.Format("The test method expected {0} parameter value{1}, but {2} parameter value{3} {4} provided.", parameterCount, parameterCount == 1 ? "" : "s", valueCount, valueCount == 1 ? "" : "s", valueCount == 1 ? "was" : "were")) ); } else { var result = TestMethod.Invoke(testClassInstance, TestMethodArguments); var task = result as Task; if (task != null) { await task; } else { var ex = await asyncSyncContext.WaitForCompletionAsync(); if (ex != null) { Aggregator.Add(ex); } } } } ) ); } finally { SetSynchronizationContext(oldSyncContext); } return(Timer.Total); }
/// <summary> /// Initializes a new instance of the <see cref="XunitTestCaseRunner"/> class. /// </summary> /// <param name="testCase">The test case to be run.</param> /// <param name="displayName">The display name of the test case.</param> /// <param name="skipReason">The skip reason, if the test is to be skipped.</param> /// <param name="constructorArguments">The arguments to be passed to the test class constructor.</param> /// <param name="testMethodArguments">The arguments to be passed to the test method.</param> /// <param name="messageBus">The message bus to report run status to.</param> /// <param name="aggregator">The exception aggregator used to run code and collect exceptions.</param> /// <param name="cancellationTokenSource">The task cancellation token source, used to cancel the test run.</param> public XunitTestCaseRunner(IXunitTestCase testCase, string displayName, string skipReason, object[] constructorArguments, object[] testMethodArguments, IMessageBus messageBus, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource) : base(testCase, messageBus, aggregator, cancellationTokenSource) { DisplayName = displayName; SkipReason = skipReason; ConstructorArguments = constructorArguments; TestClass = TestCase.TestMethod.TestClass.Class.ToRuntimeType(); TestMethod = TestCase.Method.ToRuntimeMethod(); var parameters = TestMethod.GetParameters(); var parameterTypes = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { parameterTypes[i] = parameters[i].ParameterType; } testMethodArguments = TypeUtility.ResolveMethodArguments(TestMethod, testMethodArguments); TestMethodArguments = Reflector.ConvertArguments(testMethodArguments, parameterTypes); IEnumerable <Attribute> beforeAfterTestCollectionAttributes; var collectionDefinition = testCase.TestMethod.TestClass.TestCollection.CollectionDefinition as IReflectionTypeInfo; if (collectionDefinition != null) { beforeAfterTestCollectionAttributes = collectionDefinition.Type.GetTypeInfo().GetCustomAttributes(typeof(BeforeAfterTestAttribute)); } else { beforeAfterTestCollectionAttributes = Enumerable.Empty <Attribute>(); } beforeAfterAttributes = beforeAfterTestCollectionAttributes .Concat(TestClass.GetTypeInfo().GetCustomAttributes(typeof(BeforeAfterTestAttribute))) .Concat(TestMethod.GetCustomAttributes(typeof(BeforeAfterTestAttribute))) .Cast <BeforeAfterTestAttribute>() .ToList(); }