private async Task <decimal> InvokeTestMethodAsync(ExceptionAggregator aggregator, ITestOutputHelper output)
        {
            var collectDump     = TestMethod.GetCustomAttribute <CollectDumpAttribute>() != null;
            var repeatAttribute = GetRepeatAttribute(TestMethod);

            if (!typeof(LoggedTestBase).IsAssignableFrom(TestClass) || repeatAttribute == null)
            {
                return(await new LoggedTestInvoker(Test, MessageBus, TestClass, ConstructorArguments, TestMethod, TestMethodArguments, BeforeAfterAttributes, aggregator, CancellationTokenSource, output, null, collectDump).RunAsync());
            }

            return(await RunRepeatTestInvoker(aggregator, output, collectDump, repeatAttribute));
        }
        protected override object CallTestMethod(object testClassInstance)
        {
            var asyncSyncContext = (AsyncTestSyncContext)SynchronizationContext.Current;

            //
            // Run the test method inside of our iterator.  Note that BenchmarkIterator.Run ensures that only one test
            // method is running at any given time, so we don't need extra synchronization here.
            //
            var benchmarkAttr = (BenchmarkAttribute)TestMethod.GetCustomAttribute(typeof(BenchmarkAttribute));
            var iterator      = new BenchmarkIteratorImpl(DisplayName, benchmarkAttr.InnerIterationCount);

            return(iterator.RunAsync(async() =>
            {
                var success = false;
                BenchmarkEventSource.Log.BenchmarkStart(BenchmarkConfiguration.Instance.RunId, DisplayName);
                try
                {
                    var result = TestMethod.Invoke(testClassInstance, TestMethodArguments);

                    var task = result as Task;
                    if (task != null)
                    {
                        await task;
                        success = true;
                    }
                    else
                    {
                        var ex = await asyncSyncContext.WaitForCompletionAsync();
                        if (ex == null)
                        {
                            success = true;
                        }
                        else
                        {
                            Aggregator.Add(ex);
                        }
                    }

                    if (iterator.IterationStopReason == "NoIterations")
                    {
                        success = false;
                        throw new Exception("Benchmark did not execute any iterations.  Please use one of the iteration methods in Microsoft.Xunit.Performance.Benchmark");
                    }
                }
                finally
                {
                    var stopReason = success ? iterator.IterationStopReason : "TestFailed";
                    BenchmarkEventSource.Log.BenchmarkStop(BenchmarkConfiguration.Instance.RunId, DisplayName, stopReason);
                    BenchmarkEventSource.Log.Flush();
                }
            }));
        }
Example #3
0
        private async Task <decimal> InvokeTestMethodAsync(ExceptionAggregator aggregator, ITestOutputHelper output)
        {
            var retryAttribute = GetRetryAttribute(TestMethod);
            var collectDump    = TestMethod.GetCustomAttribute <CollectDumpAttribute>() != null;

            if (!typeof(LoggedTestBase).IsAssignableFrom(TestClass) || retryAttribute == null)
            {
                return(await new LoggedTestInvoker(Test, MessageBus, TestClass, ConstructorArguments, TestMethod, TestMethodArguments, BeforeAfterAttributes, aggregator, CancellationTokenSource, output, null, collectDump).RunAsync());
            }

            var retryPredicateMethodName = retryAttribute.RetryPredicateName;
            var retryPredicateMethod     = TestClass.GetMethod(retryPredicateMethodName,
                                                               BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
                                                               null,
                                                               new Type[] { typeof(Exception) },
                                                               null)
                                           ?? throw new InvalidOperationException($"No valid static retry predicate method {retryPredicateMethodName} was found on the type {TestClass.FullName}.");

            if (retryPredicateMethod.ReturnType != typeof(bool))
            {
                throw new InvalidOperationException($"Retry predicate method {retryPredicateMethodName} on {TestClass.FullName} does not return bool.");
            }

            var retryContext = new RetryContext()
            {
                Limit  = retryAttribute.RetryLimit,
                Reason = retryAttribute.RetryReason,
            };

            var retryAggregator   = new ExceptionAggregator();
            var loggedTestInvoker = new LoggedTestInvoker(Test, MessageBus, TestClass, ConstructorArguments, TestMethod, TestMethodArguments, BeforeAfterAttributes, retryAggregator, CancellationTokenSource, output, retryContext, collectDump);
            var totalTime         = 0.0M;

            do
            {
                retryAggregator.Clear();
                totalTime += await loggedTestInvoker.RunAsync();

                retryContext.CurrentIteration++;
            }while (retryAggregator.HasExceptions &&
                    retryContext.CurrentIteration < retryContext.Limit &&
                    (retryPredicateMethod.IsStatic
                    ? (bool)retryPredicateMethod.Invoke(null, new object[] { retryAggregator.ToException() })
                    : (bool)retryPredicateMethod.Invoke(retryContext.TestClassInstance, new object[] { retryAggregator.ToException() }))
                    );

            aggregator.Aggregate(retryAggregator);
            return(totalTime);
        }
Example #4
0
        protected override object CreateTestClass()
        {
            var testClass = base.CreateTestClass();

            if (testClass is LoggedTest loggedTestClass)
            {
                var classType         = loggedTestClass.GetType();
                var logLevelAttribute = TestMethod.GetCustomAttribute <LogLevelAttribute>() as LogLevelAttribute;
                var testName          = TestMethodArguments.Aggregate(TestMethod.Name, (a, b) => $"{a}-{(b ?? "null")}");

                // Try resolving ITestOutputHelper from constructor arguments
                loggedTestClass.TestOutputHelper = ConstructorArguments?.SingleOrDefault(a => typeof(ITestOutputHelper).IsAssignableFrom(a.GetType())) as ITestOutputHelper;

                var useShortClassName = TestMethod.DeclaringType.GetCustomAttribute <ShortClassNameAttribute>()
                                        ?? TestMethod.DeclaringType.Assembly.GetCustomAttribute <ShortClassNameAttribute>();
                var resolvedClassName = useShortClassName == null ? classType.FullName : classType.Name;
                // None resolved so create a new one and retain a reference to it for initialization/uninitialization
                if (loggedTestClass.TestOutputHelper == null)
                {
                    loggedTestClass.TestOutputHelper = _output = new TestOutputHelper();
                    _output.Initialize(MessageBus, Test);
                }

                AssemblyTestLog
                .ForAssembly(classType.GetTypeInfo().Assembly)
                .StartTestLog(
                    loggedTestClass.TestOutputHelper,
                    resolvedClassName,
                    out var loggerFactory,
                    logLevelAttribute?.LogLevel ?? LogLevel.Trace,
                    out var resolvedTestName,
                    testName);

                // internal for testing
                loggedTestClass.ResolvedTestMethodName = resolvedTestName;
                loggedTestClass.ResolvedTestClassName  = resolvedClassName;

                loggedTestClass.LoggerFactory = loggerFactory;
                loggedTestClass.Logger        = loggerFactory.CreateLogger(classType);
                loggedTestClass.TestSink      = new TestSink();
                loggerFactory.AddProvider(new TestLoggerProvider(loggedTestClass.TestSink));

                loggedTestClass.AdditionalSetup();
            }

            return(testClass);
        }