Пример #1
0
 private void StateChangedHandler(object sender, ParserStateEventArgs e)
 {
     if (!CanRun || e.IsError)
     {
         refreshBackoff = false;
     }
     // CanRun returned true already, only refresh tests if we're not backed off
     else if (!refreshBackoff && e.OldState != ParserState.Busy)
     {
         refreshBackoff = true;
         Tests          = TestDiscovery.GetAllTests(_state);
         _uiDispatcher.InvokeAsync(() => TestsRefreshed?.Invoke(this, EventArgs.Empty));
     }
 }
Пример #2
0
        private void StateChangedHandler(object sender, ParserStateEventArgs e)
        {
            if (e.OldState == ParserState.Started)
            {
                _uiDispatcher.InvokeAsync(() => TestsRefreshStarted?.Invoke(this, EventArgs.Empty));
                return;
            }

            if (!CanRun || e.IsError)
            {
                _listening = true;
            }
            // CanRun returned true already, only refresh tests if we're not backed off
            else if (_listening && e.OldState != ParserState.Busy)
            {
                _listening = false;
                var updates = TestDiscovery.GetAllTests(_state).ToList();
                var run     = new List <TestMethod>();
                var known   = new Dictionary <TestMethod, TestOutcome>();

                foreach (var test in updates)
                {
                    var match = _lastRun.FirstOrDefault(ut => ut.Equals(test));
                    if (match != null)
                    {
                        run.Add(match);
                    }

                    if (_knownOutcomes.ContainsKey(test))
                    {
                        known.Add(test, _knownOutcomes[test]);
                    }
                }

                _tests         = updates;
                _lastRun       = run;
                _knownOutcomes = known;
                _uiDispatcher.InvokeAsync(() => TestsRefreshed?.Invoke(this, EventArgs.Empty));
            }
        }
Пример #3
0
        private void RunWhileSuspendedOnUiThread(IEnumerable <TestMethod> tests)
        {
            var testMethods = tests as IList <TestMethod> ?? tests.ToList();

            if (!testMethods.Any())
            {
                return;
            }

            _lastRun.Clear();

            try
            {
                EnsureRubberduckIsReferencedForEarlyBoundTests();
            }
            catch (InvalidOperationException e)
            {
                Logger.Warn(e);
                foreach (var test in testMethods)
                {
                    OnTestCompleted(test, new TestResult(TestOutcome.Failed, AssertMessages.Prerequisite_EarlyBindingReferenceMissing));
                }
                return;
            }

            var overallTime = new Stopwatch();

            overallTime.Start();
            try
            {
                var testsByModule = testMethods.GroupBy(test => test.Declaration.QualifiedName.QualifiedModuleName)
                                    .ToDictionary(grouping => grouping.Key, grouping => grouping.ToList());

                foreach (var moduleName in testsByModule.Keys)
                {
                    var testInitialize = TestDiscovery.FindTestInitializeMethods(moduleName, _state).ToList();
                    var testCleanup    = TestDiscovery.FindTestCleanupMethods(moduleName, _state).ToList();

                    var moduleTestMethods = testsByModule[moduleName];

                    var fakes = _fakesFactory.Create();
                    using (var typeLibWrapper = _wrapperProvider.TypeLibWrapperFromProject(moduleName.ProjectId))
                    {
                        try
                        {
                            _declarationRunner.RunDeclarations(typeLibWrapper, TestDiscovery.FindModuleInitializeMethods(moduleName, _state));
                        }
                        catch (COMException ex)
                        {
                            Logger.Error(ex, "Unexpected COM exception while initializing tests for module {0}. The module will be skipped.", moduleName.Name);
                            foreach (var method in moduleTestMethods)
                            {
                                OnTestCompleted(method, new TestResult(TestOutcome.Unknown, AssertMessages.TestRunner_ModuleInitializeFailure));
                            }
                            continue;
                        }
                        foreach (var test in moduleTestMethods)
                        {
                            OnTestStarted(test);

                            // no need to run setup/teardown for ignored tests
                            if (test.Declaration.Annotations.Any(a => a.Annotation is IgnoreTestAnnotation))
                            {
                                OnTestCompleted(test, new TestResult(TestOutcome.Ignored));
                                continue;
                            }

                            try
                            {
                                fakes.StartTest();
                                try
                                {
                                    _declarationRunner.RunDeclarations(typeLibWrapper, testInitialize);
                                }
                                catch (COMException trace)
                                {
                                    OnTestCompleted(test, new TestResult(TestOutcome.Inconclusive, AssertMessages.TestRunner_TestInitializeFailure));
                                    Logger.Trace(trace, "Unexpected COMException when running TestInitialize");
                                    continue;
                                }

                                // The message pump is flushed here to catch cancellation requests. This is the only place inside the main test running
                                // loop where this is "safe" to do - any other location risks either potentially misses test teardown or risks not knowing
                                // what teardown needs to be done via VBA.
                                _uiDispatcher.FlushMessageQueue();

                                if (CancellationRequested)
                                {
                                    RunTestCleanup(typeLibWrapper, testCleanup);
                                    fakes.StopTest();
                                    break;
                                }

                                var result = RunTestMethod(typeLibWrapper, test);

                                // we can trigger this event, because cleanup can fail without affecting the result
                                OnTestCompleted(test, result);

                                RunTestCleanup(typeLibWrapper, testCleanup);
                            }
                            finally
                            {
                                fakes.StopTest();
                            }
                        }
                        try
                        {
                            _declarationRunner.RunDeclarations(typeLibWrapper, TestDiscovery.FindModuleCleanupMethods(moduleName, _state));
                        }
                        catch (COMException ex)
                        {
                            // FIXME somehow notify the user of this mess
                            Logger.Error(ex,
                                         "Unexpected COM exception while cleaning up tests for module {0}. Aborting any further unit tests",
                                         moduleName.Name);
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // FIXME somehow notify the user of this mess
                Logger.Error(ex, "Unexpected expection while running unit tests; unit tests will be aborted");
            }

            CancellationRequested = false;
            overallTime.Stop();

            TestRunCompleted?.Invoke(this, new TestRunCompletedEventArgs(overallTime.ElapsedMilliseconds));
        }
Пример #4
0
        private void RunWhileSuspended(IEnumerable <TestMethod> tests)
        {
            var testMethods = tests as IList <TestMethod> ?? tests.ToList();

            if (!testMethods.Any())
            {
                return;
            }
            LastRun.Clear();
            foreach (var resultAggregator in resultsByOutcome.Values)
            {
                resultAggregator.Clear();
            }
            try
            {
                EnsureRubberduckIsReferencedForEarlyBoundTests();
            }
            catch (InvalidOperationException e)
            {
                Logger.Warn(e);
                foreach (var test in testMethods)
                {
                    OnTestCompleted(test, new TestResult(TestOutcome.Failed, AssertMessages.Prerequisite_EarlyBindingReferenceMissing, 0));
                }
                return;
            }

            var overallTime = new Stopwatch();

            overallTime.Start();
            try
            {
                var testsByModule = testMethods.GroupBy(test => test.Declaration.QualifiedName.QualifiedModuleName)
                                    .ToDictionary(grouping => grouping.Key, grouping => grouping.ToList());

                foreach (var moduleName in testsByModule.Keys)
                {
                    var testInitialize = TestDiscovery.FindTestInitializeMethods(moduleName, _state).ToList();
                    var testCleanup    = TestDiscovery.FindTestCleanupMethods(moduleName, _state).ToList();

                    var moduleTestMethods = testsByModule[moduleName];

                    var fakes = _fakesFactory.Create();
                    using (var typeLibWrapper = _wrapperProvider.TypeLibWrapperFromProject(moduleName.ProjectId))
                    {
                        try
                        {
                            _declarationRunner.RunDeclarations(typeLibWrapper, TestDiscovery.FindModuleInitializeMethods(moduleName, _state));
                        }
                        catch (COMException ex)
                        {
                            Logger.Error(ex, "Unexpected COM exception while initializing tests for module {0}. The module will be skipped.", moduleName.Name);
                            foreach (var method in moduleTestMethods)
                            {
                                OnTestCompleted(method, new TestResult(TestOutcome.Unknown, AssertMessages.TestRunner_ModuleInitializeFailure));
                            }
                            continue;
                        }
                        foreach (var test in moduleTestMethods)
                        {
                            // no need to run setup/teardown for ignored tests
                            if (test.Declaration.Annotations.Any(a => a.AnnotationType == AnnotationType.IgnoreTest))
                            {
                                OnTestCompleted(test, new TestResult(TestOutcome.Ignored));
                                continue;
                            }

                            try
                            {
                                fakes.StartTest();
                                try
                                {
                                    _declarationRunner.RunDeclarations(typeLibWrapper, testInitialize);
                                }
                                catch (COMException trace)
                                {
                                    OnTestCompleted(test, new TestResult(TestOutcome.Inconclusive, AssertMessages.TestRunner_TestInitializeFailure));
                                    Logger.Trace(trace, "Unexpected COMException when running TestInitialize");
                                    continue;
                                }
                                var result = RunTestMethod(typeLibWrapper, test);
                                // we can trigger this event, because cleanup can fail without affecting the result
                                OnTestCompleted(test, result);
                                try
                                {
                                    _declarationRunner.RunDeclarations(typeLibWrapper, testCleanup);
                                }
                                catch (COMException cleanupFail)
                                {
                                    // Apparently the user doesn't need to know when test results for subsequent tests could be incorrect
                                    Logger.Trace(cleanupFail, "Unexpected COMException when running TestCleanup");
                                }
                            }
                            finally
                            {
                                fakes.StopTest();
                            }
                        }
                        try
                        {
                            _declarationRunner.RunDeclarations(typeLibWrapper, TestDiscovery.FindModuleCleanupMethods(moduleName, _state));
                        }
                        catch (COMException ex)
                        {
                            // FIXME somehow notify the user of this mess
                            Logger.Error(ex,
                                         "Unexpected COM exception while cleaning up tests for module {0}. Aborting any further unit tests",
                                         moduleName.Name);
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // FIXME somehow notify the user of this mess
                Logger.Error(ex, "Unexpected expection while running unit tests; unit tests will be aborted");
            }
            overallTime.Stop();
            TestRunCompleted?.Invoke(this, new TestRunCompletedEventArgs(overallTime.ElapsedMilliseconds));
        }