Esempio n. 1
0
        private IChutzpahWebServerHost SetupWebServerHost(ConcurrentBag <TestContext> testContexts, TestOptions options)
        {
            var needsServer = options.Engine.GetValueOrDefault() != Engine.Phantom;

            IChutzpahWebServerHost webServerHost     = null;
            var contextUsingWebServer                = testContexts.Where(x => x.TestFileSettings.Server?.Enabled.GetValueOrDefault() == true).ToList();
            var contextWithChosenServerConfiguration = contextUsingWebServer.FirstOrDefault();

            if (contextWithChosenServerConfiguration == null && needsServer)
            {
                foreach (var testContext in testContexts)
                {
                    testContext.TestFileSettings.Server = ForcedChutzpahWebServerConfiguration.Instance;
                }

                contextUsingWebServer = testContexts.ToList();
                contextWithChosenServerConfiguration = testContexts.FirstOrDefault();
            }

            if (contextWithChosenServerConfiguration != null)
            {
                var webServerConfiguration = contextWithChosenServerConfiguration.TestFileSettings.Server;
                webServerHost = webServerFactory.CreateServer(webServerConfiguration, ActiveWebServerHost);

                // Stash host object on context for use in url generation
                contextUsingWebServer.ForEach(x => x.WebServerHost = webServerHost);
            }

            return(webServerHost);
        }
Esempio n. 2
0
        private IChutzpahWebServerHost SetupWebServerHost(ConcurrentBag <TestContext> testContexts, IChutzpahWebServerHost activeWebServerHost)
        {
            IChutzpahWebServerHost webServerHost     = null;
            var contextUsingWebServer                = testContexts.Where(x => x.TestFileSettings.Server != null && x.TestFileSettings.Server.Enabled.GetValueOrDefault()).ToList();
            var contextWithChosenServerConfiguration = contextUsingWebServer.FirstOrDefault();

            if (contextWithChosenServerConfiguration != null)
            {
                var webServerConfiguration = contextWithChosenServerConfiguration.TestFileSettings.Server;
                webServerHost = webServerFactory.CreateServer(webServerConfiguration, ActiveWebServerHost);

                // Stash host object on context for use in url generation
                contextUsingWebServer.ForEach(x => x.WebServerHost = webServerHost);
            }

            return(webServerHost);
        }
Esempio n. 3
0
        private void ExecuteTestContexts(
            TestOptions options,
            TestExecutionMode testExecutionMode,
            ITestMethodRunnerCallback callback,
            ConcurrentBag <TestContext> testContexts,
            ParallelOptions parallelOptions,
            ConcurrentQueue <TestFileSummary> testFileSummaries,
            TestCaseSummary overallSummary,
            IChutzpahWebServerHost webServerHost)
        {
            Parallel.ForEach(
                testContexts,
                parallelOptions,
                testContext =>
            {
                ChutzpahTracer.TraceInformation("Start test run for {0} in {1} mode", testContext.FirstInputTestFile, testExecutionMode);

                testContext.TaskId = Task.CurrentId.GetValueOrDefault();
                try
                {
                    try
                    {
                        testHarnessBuilder.CreateTestHarness(testContext, options);
                    }
                    catch (IOException)
                    {
                        // Mark this creation failed so we do not try to clean it up later
                        // This is to work around a bug in TestExplorer that runs chutzpah in parallel on
                        // the same files
                        // TODO(mmanela): Re-evalute if this is needed once they fix that bug
                        testContext.TestHarnessCreationFailed = true;
                        ChutzpahTracer.TraceWarning("Marking test harness creation failed for harness {0} and test file {1}", testContext.TestHarnessPath, testContext.FirstInputTestFile);
                        throw;
                    }

                    if (options.TestLaunchMode == TestLaunchMode.FullBrowser)
                    {
                        ChutzpahTracer.TraceInformation(
                            "Launching test harness '{0}' for file '{1}' in a browser",
                            testContext.TestHarnessPath,
                            testContext.FirstInputTestFile);

                        // Allow override from command line.
                        var browserArgs = testContext.TestFileSettings.BrowserArguments;
                        if (!string.IsNullOrWhiteSpace(options.OpenInBrowserArgs))
                        {
                            var path    = BrowserPathHelper.GetBrowserPath(options.OpenInBrowserName);
                            browserArgs = new Dictionary <string, string>
                            {
                                { Path.GetFileNameWithoutExtension(path), options.OpenInBrowserArgs }
                            };
                        }

                        process.LaunchFileInBrowser(testContext, testContext.TestHarnessPath, options.OpenInBrowserName, browserArgs);
                    }
                    else if (options.TestLaunchMode == TestLaunchMode.HeadlessBrowser)
                    {
                        ChutzpahTracer.TraceInformation(
                            "Invoking headless browser on test harness '{0}' for file '{1}'",
                            testContext.TestHarnessPath,
                            testContext.FirstInputTestFile);

                        callback.TestContextStarted(testContext);

                        var testSummaries = InvokeTestRunner(
                            options,
                            testContext,
                            testExecutionMode,
                            callback);

                        callback.TestContextFinished(testContext);

                        foreach (var testSummary in testSummaries)
                        {
                            ChutzpahTracer.TraceInformation(
                                "Test harness '{0}' for file '{1}' finished with {2} passed, {3} failed and {4} errors",
                                testContext.TestHarnessPath,
                                testSummary.Path,
                                testSummary.PassedCount,
                                testSummary.FailedCount,
                                testSummary.Errors.Count);

                            ChutzpahTracer.TraceInformation(
                                "Finished running headless browser on test harness '{0}' for file '{1}'",
                                testContext.TestHarnessPath,
                                testSummary.Path);

                            testFileSummaries.Enqueue(testSummary);
                        }
                    }
                    else if (options.TestLaunchMode == TestLaunchMode.Custom)
                    {
                        if (options.CustomTestLauncher == null)
                        {
                            throw new ArgumentNullException("TestOptions.CustomTestLauncher");
                        }
                        ChutzpahTracer.TraceInformation(
                            "Launching custom test on test harness '{0}' for file '{1}'",
                            testContext.TestHarnessPath,
                            testContext.FirstInputTestFile);
                        options.CustomTestLauncher.LaunchTest(testContext);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }
                }
                catch (Exception e)
                {
                    var error = new TestError
                    {
                        InputTestFile = testContext.InputTestFiles.FirstOrDefault(),
                        Message       = e.ToString()
                    };

                    overallSummary.Errors.Add(error);
                    callback.FileError(testContext, error);

                    ChutzpahTracer.TraceError(e, "Error during test execution of {0}", testContext.FirstInputTestFile);
                }
                finally
                {
                    ChutzpahTracer.TraceInformation("Finished test run for {0} in {1} mode", testContext.FirstInputTestFile, testExecutionMode);
                }
            });


            // Clean up test context
            foreach (var testContext in testContexts)
            {
                // Don't clean up context if in debug mode
                if (!m_debugEnabled &&
                    !testContext.TestHarnessCreationFailed &&
                    options.TestLaunchMode != TestLaunchMode.FullBrowser &&
                    options.TestLaunchMode != TestLaunchMode.Custom)
                {
                    try
                    {
                        ChutzpahTracer.TraceInformation("Cleaning up test context for {0}", testContext.FirstInputTestFile);
                        testContextBuilder.CleanupContext(testContext);
                    }
                    catch (Exception e)
                    {
                        ChutzpahTracer.TraceError(e, "Error cleaning up test context for {0}", testContext.FirstInputTestFile);
                    }
                }
            }

            if (webServerHost != null &&
                options.TestLaunchMode != TestLaunchMode.FullBrowser &&
                options.TestLaunchMode != TestLaunchMode.Custom)
            {
                webServerHost.Dispose();
            }
        }
Esempio n. 4
0
        private TestCaseSummary ProcessTestPaths(IEnumerable <string> testPaths,
                                                 TestOptions options,
                                                 TestExecutionMode testExecutionMode,
                                                 ITestMethodRunnerCallback callback,
                                                 IChutzpahWebServerHost activeWebServerHost = null)
        {
            var overallSummary = new TestCaseSummary();

            options.TestExecutionMode = testExecutionMode;
            options.DebugEnabled      = m_debugEnabled;

            stopWatch.Start();
            if (testPaths == null)
            {
                throw new ArgumentNullException("testPaths");
            }
            if (fileProbe.FindFilePath(TestRunnerJsName) == null)
            {
                throw new FileNotFoundException("Unable to find test runner base js file: " + TestRunnerJsName);
            }

            // Concurrent list to collect test contexts
            var testContexts = new ConcurrentBag <TestContext>();

            // Concurrent collection used to gather the parallel results from
            var testFileSummaries  = new ConcurrentQueue <TestFileSummary>();
            var resultCount        = 0;
            var cancellationSource = new CancellationTokenSource();


            try
            {
                // Given the input paths discover the potential test files
                var scriptPaths = FindTestFiles(testPaths, options);

                // Group the test files by their chutzpah.json files. Then check if those settings file have batching mode enabled.
                // If so, we keep those tests in a group together to be used in one context
                // Otherwise, we put each file in its own test group so each get their own context
                var testRunConfiguration = BuildTestRunConfiguration(scriptPaths, options);

                ConfigureTracing(testRunConfiguration);

                var parallelism = testRunConfiguration.MaxDegreeOfParallelism.HasValue
                                    ? Math.Min(options.MaxDegreeOfParallelism, testRunConfiguration.MaxDegreeOfParallelism.Value)
                                    : options.MaxDegreeOfParallelism;

                var parallelOptions = new ParallelOptions {
                    MaxDegreeOfParallelism = parallelism, CancellationToken = cancellationSource.Token
                };

                ChutzpahTracer.TraceInformation("Chutzpah run started in mode {0} with parallelism set to {1}", testExecutionMode, parallelOptions.MaxDegreeOfParallelism);

                // Build test contexts in parallel given a list of files each
                BuildTestContexts(options, testRunConfiguration.TestGroups, parallelOptions, cancellationSource, resultCount, testContexts, callback, overallSummary);

                // Compile the test contexts
                if (!PerformBatchCompile(callback, testContexts))
                {
                    return(overallSummary);
                }

                // Find the first test context with a web server configuration and use it
                var webServerHost = SetupWebServerHost(testContexts, options);
                ActiveWebServerHost = webServerHost;

                // Build test harness for each context and execute it in parallel
                ExecuteTestContexts(options, testExecutionMode, callback, testContexts, parallelOptions, testFileSummaries, overallSummary, webServerHost);


                // Gather TestFileSummaries into TaseCaseSummary
                foreach (var fileSummary in testFileSummaries)
                {
                    overallSummary.Append(fileSummary);
                }

                stopWatch.Stop();
                overallSummary.SetTotalRunTime((int)stopWatch.Elapsed.TotalMilliseconds);

                overallSummary.TransformResult = transformProcessor.ProcessTransforms(testContexts, overallSummary);

                ChutzpahTracer.TraceInformation(
                    "Chutzpah run finished with {0} passed, {1} failed and {2} errors",
                    overallSummary.PassedCount,
                    overallSummary.FailedCount,
                    overallSummary.Errors.Count);

                return(overallSummary);
            }
            catch (Exception e)
            {
                callback.ExceptionThrown(e);

                ChutzpahTracer.TraceError(e, "Unhandled exception during Chutzpah test run");

                return(overallSummary);
            }
            finally
            {
                // Clear the settings file cache since in VS Chutzpah is not unloaded from memory.
                // If we don't clear then the user can never update the file.
                testSettingsService.ClearCache();
            }
        }
        public IChutzpahWebServerHost CreateServer(ChutzpahWebServerConfiguration configuration, IChutzpahWebServerHost activeWebServerHost)
        {
            if (activeWebServerHost != null &&
                activeWebServerHost.IsRunning &&
                activeWebServerHost.RootPath.Equals(configuration.RootPath, StringComparison.OrdinalIgnoreCase))
            {
                // If the requested server is already running just re-use it
                return(activeWebServerHost);
            }

            var builtInDependencyFolder = fileProbe.BuiltInDependencyDirectory;


            return(BuildHost(configuration.RootPath, configuration.DefaultPort.Value, builtInDependencyFolder));
        }