Beispiel #1
0
        public void DiscoverTests(IEnumerable <string> sources, IDiscoveryContext discoveryContext, IMessageLogger logger, ITestCaseDiscoverySink discoverySink)
        {
            ChutzpahTracer.TraceInformation("Begin Test Adapter Discover Tests");

            var settingsProvider = discoveryContext.RunSettings.GetSettings(ChutzpahAdapterSettings.SettingsName) as ChutzpahAdapterSettingsService;
            var settings         = settingsProvider != null ? settingsProvider.Settings : new ChutzpahAdapterSettings();

            ChutzpahTracingHelper.Toggle(settings.EnabledTracing);

            var testOptions = new TestOptions
            {
                TestFileTimeoutMilliseconds = settings.TimeoutMilliseconds,
                TestingMode            = settings.TestingMode,
                MaxDegreeOfParallelism = settings.MaxDegreeOfParallelism
            };

            IList <TestError> errors;
            var testCases = testRunner.DiscoverTests(sources, testOptions, out errors);

            ChutzpahTracer.TraceInformation("Sending discovered tests to test case discovery sink");

            foreach (var testCase in testCases)
            {
                var vsTestCase = testCase.ToVsTestCase();
                discoverySink.SendTestCase(vsTestCase);
            }

            foreach (var error in errors)
            {
                logger.SendMessage(TestMessageLevel.Error, RunnerCallback.FormatFileErrorMessage(error));
            }

            ChutzpahTracer.TraceInformation("End Test Adapter Discover Tests");
        }
Beispiel #2
0
        public void RunTests(IEnumerable <string> sources, IRunContext runContext, IFrameworkHandle frameworkHandle)
        {
            ChutzpahTracer.TraceInformation("Begin Test Adapter Run Tests");


            var settingsProvider = runContext.RunSettings.GetSettings(ChutzpahAdapterSettings.SettingsName) as ChutzpahAdapterSettingsService;
            var settings         = settingsProvider != null ? settingsProvider.Settings : new ChutzpahAdapterSettings();

            ChutzpahTracingHelper.Toggle(settings.EnabledTracing);

            var testOptions = new TestOptions
            {
                TestFileTimeoutMilliseconds = settings.TimeoutMilliseconds,
                TestingMode            = settings.TestingMode,
                MaxDegreeOfParallelism = settings.MaxDegreeOfParallelism,
            };

            testOptions.CoverageOptions.Enabled = runContext.IsDataCollectionEnabled;

            var callback = new ParallelRunnerCallbackAdapter(new ExecutionCallback(frameworkHandle, runContext));

            testRunner.RunTests(sources, testOptions, callback);

            ChutzpahTracer.TraceInformation("End Test Adapter Run Tests");
        }
        public void DiscoverTests(IEnumerable <string> sources, IDiscoveryContext discoveryContext, IMessageLogger logger, ITestCaseDiscoverySink discoverySink)
        {
            if (Environment.GetEnvironmentVariable("ATTACH_DEBUGGER_CHUTZPAH") != null)
            {
                Debugger.Launch();
            }

            ChutzpahTracer.TraceInformation("Begin Test Adapter Discover Tests");

            var settingsProvider = discoveryContext.RunSettings.GetSettings(AdapterConstants.SettingsName) as ChutzpahAdapterSettingsProvider;
            var settings         = settingsProvider != null ? settingsProvider.Settings : new ChutzpahAdapterSettings();

            ChutzpahTracingHelper.Toggle(settings.EnabledTracing);

            var testOptions = new TestOptions
            {
                MaxDegreeOfParallelism           = settings.MaxDegreeOfParallelism,
                ChutzpahSettingsFileEnvironments = new ChutzpahSettingsFileEnvironments(settings.ChutzpahSettingsFileEnvironments)
            };


            ChutzpahTracer.TraceInformation("Sending discovered tests to test case discovery sink");

            var callback  = new ParallelRunnerCallbackAdapter(new DiscoveryCallback(logger, discoverySink));
            var testCases = testRunner.DiscoverTests(sources, testOptions, callback);


            ChutzpahTracer.TraceInformation("End Test Adapter Discover Tests");
        }
Beispiel #4
0
        /// <summary>
        /// Handler to react to project load/unload events.
        /// </summary>
        private void OnSolutionProjectChanged(object sender, SolutionEventsListenerEventArgs e)
        {
            if (e != null)
            {
                string projectPath = VsSolutionHelper.GetProjectPath(e.Project);

                var files = FindPotentialTestFiles(e.Project);
                if (e.ChangedReason == SolutionChangedReason.Load)
                {
                    ChutzpahTracer.TraceInformation("Project Loaded: '{0}'", projectPath);
                    UpdateChutzpahEnvironmentForProject(projectPath);
                    UpdateTestContainersAndFileWatchers(files, true);
                }
                else if (e.ChangedReason == SolutionChangedReason.Unload)
                {
                    ChutzpahTracer.TraceInformation("Project Unloaded: '{0}'", projectPath);
                    RemoveChutzpahEnvironmentForProject(projectPath);
                    UpdateTestContainersAndFileWatchers(files, false);
                }
            }

            // Do not fire OnTestContainersChanged here.
            // This will cause us to fire this event too early before the UTE is ready to process containers and will result in an exception.
            // The UTE will query all the TestContainerDiscoverers once the solution is loaded.
        }
Beispiel #5
0
        public void PrepareTestHarnessForCoverage(TestHarness harness, IFrameworkDefinition definition, ChutzpahTestSettingsFile testSettingsFile)
        {
            string blanketScriptName = GetBlanketScriptName(definition, testSettingsFile);

            // Construct array of scripts to exclude from instrumentation/coverage collection.
            var filesToExcludeFromCoverage = new List <string>();
            var filesToIncludeInCoverage   = new List <string>();
            var extensionMap = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            foreach (TestHarnessItem refScript in harness.ReferencedScripts.Where(rs => rs.HasFile))
            {
                // Skip files which the user is asking us to exclude
                if (!IsFileEligibleForInstrumentation(refScript.ReferencedFile.Path))
                {
                    filesToExcludeFromCoverage.Add(refScript.Attributes["src"]);
                }
                else
                {
                    refScript.Attributes["type"] = "text/blanket"; // prevent Phantom/browser parsing
                }


                // Build extension map for when we conver to regex the include/exclude patterns
                if (!string.IsNullOrEmpty(refScript.ReferencedFile.GeneratedFilePath))
                {
                    var sourceExtension = Path.GetExtension(refScript.ReferencedFile.Path);
                    extensionMap[sourceExtension] = ".js";
                }
            }

            // Construct array of scripts to exclude from instrumentation/coverage collection.
            filesToExcludeFromCoverage.AddRange(
                harness.TestFrameworkDependencies.Concat(harness.CodeCoverageDependencies)
                .Where(dep => dep.HasFile && IsScriptFile(dep.ReferencedFile))
                .Select(dep => dep.Attributes["src"])
                .Concat(excludePatterns.Select(f => ToRegex(f, extensionMap))));

            filesToIncludeInCoverage.AddRange(includePatterns.Select(f => ToRegex(f, extensionMap)));

            // Name the coverage object so that the JS runner can pick it up.
            harness.ReferencedScripts.Add(new Script(string.Format("window.{0}='_$blanket';", Constants.ChutzpahCoverageObjectReference)));

            // Configure Blanket.
            TestHarnessItem blanketMain = harness.CodeCoverageDependencies.Single(
                d => d.Attributes.ContainsKey("src") && (d.Attributes["src"].EndsWith(blanketScriptName) || d.Attributes["src"].Contains(blanketScriptName + "?")));


            string dataCoverNever = "[" + string.Join(",", filesToExcludeFromCoverage.Select(file => "'" + file + "'")) + "]";

            string dataCoverOnly = filesToIncludeInCoverage.Any()
                                   ? "[" + string.Join(",", filesToIncludeInCoverage.Select(file => "'" + file + "'")) + "]"
                                   : "//.*/";

            ChutzpahTracer.TraceInformation("Adding data-cover-never attribute to blanket: {0}", dataCoverNever);

            blanketMain.Attributes.Add("data-cover-flags", "ignoreError autoStart");
            blanketMain.Attributes.Add("data-cover-only", dataCoverOnly);
            blanketMain.Attributes.Add("data-cover-never", dataCoverNever);
            blanketMain.Attributes.Add("data-cover-timeout", testSettingsFile.CodeCoverageTimeout.HasValue ? testSettingsFile.CodeCoverageTimeout.Value.ToString() : "5000");
        }
        public ChutzpahWebServerHost CreateServer(ChutzpahWebServerConfiguration configuration)
        {
            if (ChutzpahWebServerHost.ActiveWebServer != null && ChutzpahWebServerHost.ActiveWebServer.RootPath.Equals(configuration.RootPath, StringComparison.OrdinalIgnoreCase))
            {
                // If the requested server is already running just re-use it
                return(ChutzpahWebServerHost.ActiveWebServer);
            }

            var hostConfiguration = new HostConfiguration
            {
                RewriteLocalhost = true,
                UrlReservations  = new UrlReservations {
                    CreateAutomatically = true
                }
            };

            var port = GetNextAvailablePort(configuration.DefaultPort.Value);
            var builtInDependencyFolder = fileProbe.BuiltInDependencyDirectory;

            ChutzpahTracer.TraceInformation("Creating Web Server Host at path {0} and port {1}", configuration.RootPath, port);

            var host = new NancyHost(new Uri(string.Format("http://localhost:{0}", port)), new NancySettingsBootstrapper(configuration.RootPath, builtInDependencyFolder), hostConfiguration);

            host.Start();
            var chutzpahWebServerHost = ChutzpahWebServerHost.Create(host, configuration.RootPath, port);

            return(chutzpahWebServerHost);
        }
Beispiel #7
0
        /// <summary>
        /// After a project is loaded or unloaded either add or remove from the file watcher
        /// all test potential items inside that project
        /// </summary>
        private void UpdateTestContainersAndFileWatchers(IEnumerable <TestFileCandidate> files, bool isAdd)
        {
            ChutzpahTracer.TraceInformation("Begin UpdateTestContainersAndFileWatchers");
            Parallel.ForEach(files, file =>
            {
                try
                {
                    if (isAdd)
                    {
                        ChutzpahTracer.TraceInformation("Adding watch on {0}", file.Path);
                        testFilesUpdateWatcher.AddWatch(file.Path);
                        AddTestContainerIfTestFile(file);
                    }
                    else
                    {
                        ChutzpahTracer.TraceInformation("Removing watch on {0}", file.Path);
                        testFilesUpdateWatcher.RemoveWatch(file.Path);
                        RemoveTestContainer(file);
                    }
                }
                catch (Exception e)
                {
                    ChutzpahTracer.TraceError(e, "Failed in UpdateTestContainersAndFileWatchers");
                }
            });

            ChutzpahTracer.TraceInformation("End UpdateTestContainersAndFileWatchers");
        }
Beispiel #8
0
        private IEnumerable <ITestContainer> GetTestContainers()
        {
            ChutzpahTracer.TraceInformation("Begin GetTestContainers");
            logger.Log("GetTestContainers() are called", "ChutzpahTestContainerDiscoverer", LogType.Information);

            ChutzpahTracingHelper.Toggle(settingsMapper.Settings.EnabledTracing);

            if (initialContainerSearch || forceFullContainerRefresh)
            {
                ChutzpahTracer.TraceInformation("Begin Initial test container search");
                logger.Log("Initial test container search", "ChutzpahTestContainerDiscoverer", LogType.Information);

                // Before the full container search we clear the settings cache to make sure
                // we are getting the latest version of the settings
                // If the user changes the settings file after this it will cause a full search again
                chutzpahTestSettingsService.ClearCache();

                cachedContainers.Clear();

                var jsFiles = FindPotentialTestFiles();
                UpdateTestContainersAndFileWatchers(jsFiles, true);
                initialContainerSearch    = false;
                forceFullContainerRefresh = false;

                ChutzpahTracer.TraceInformation("End Initial test container search");
            }


            ChutzpahTracer.TraceInformation("End GetTestContainers");
            return(cachedContainers.Values);
        }
Beispiel #9
0
        public void RunTests(IEnumerable <string> sources, IRunContext runContext, IFrameworkHandle frameworkHandle)
        {
            ChutzpahTracer.TraceInformation("Begin Test Adapter Run Tests");

            var settingsProvider = runContext.RunSettings.GetSettings(AdapterConstants.SettingsName) as ChutzpahAdapterSettingsProvider;
            var settings         = settingsProvider != null ? settingsProvider.Settings : new ChutzpahAdapterSettings();

            ChutzpahTracingHelper.Toggle(settings.EnabledTracing);

            var testOptions = new TestOptions
            {
                TestLaunchMode =
                    runContext.IsBeingDebugged ? TestLaunchMode.Custom:
                    settings.OpenInBrowser ? TestLaunchMode.FullBrowser:
                    TestLaunchMode.HeadlessBrowser,
                CustomTestLauncher               = runContext.IsBeingDebugged ? new VsDebuggerTestLauncher() : null,
                MaxDegreeOfParallelism           = runContext.IsBeingDebugged ? 1 : settings.MaxDegreeOfParallelism,
                ChutzpahSettingsFileEnvironments = new ChutzpahSettingsFileEnvironments(settings.ChutzpahSettingsFileEnvironments)
            };

            testOptions.CoverageOptions.Enabled = runContext.IsDataCollectionEnabled;

            var callback = new ParallelRunnerCallbackAdapter(new ExecutionCallback(frameworkHandle, runContext));

            testRunner.RunTests(sources, testOptions, callback);

            ChutzpahTracer.TraceInformation("End Test Adapter Run Tests");
        }
Beispiel #10
0
        private ChutzpahWebServerHost BuildHost(string rootPath, int defaultPort, string builtInDependencyFolder)
        {
            var attemptLimit = Constants.WebServerCreationAttemptLimit;
            var success      = false;

            do
            {
                // We can try multiple times to build the webserver. The reason is there is a possible race condition where
                // between when we find a free port and when we start the server that port may have been taken. To mitigate this we
                // can retry to hopefully avoid this issue.
                attemptLimit--;
                var port = FindFreePort(defaultPort);

                try
                {
                    ChutzpahTracer.TraceInformation("Creating Web Server Host at path {0} and port {1}", rootPath, port);
                    var host = new WebHostBuilder()
                               .UseUrls($"http://localhost:{port}")
                               .UseContentRoot(rootPath)
                               .UseWebRoot("")
                               .UseKestrel()
                               .Configure((app) =>
                    {
                        var env = (IHostingEnvironment)app.ApplicationServices.GetService(typeof(IHostingEnvironment));
                        app.UseStaticFiles(new StaticFileOptions
                        {
                            OnPrepareResponse     = AddFileCacheHeaders,
                            ServeUnknownFileTypes = true,
                            FileProvider          = new ChutzpahServerFileProvider(env.ContentRootPath, builtInDependencyFolder)
                        });
                        app.Run(async(context) =>
                        {
                            if (context.Request.Path == "/")
                            {
                                await context.Response.WriteAsync($"Chutzpah Web Server (Version { Assembly.GetEntryAssembly().GetName().Version})");
                            }
                            else
                            {
                                context.Response.StatusCode = (int)HttpStatusCode.NotFound;
                            }
                        });
                    })
                               .Build();

                    host.Start();
                    success = true;

                    return(ChutzpahWebServerHost.Create(host, rootPath, port));
                }
                catch (Exception ex) when(attemptLimit > 0)
                {
                    ChutzpahTracer.TraceError(ex, "Unable to create web server host at path {0} and port {1}. Trying again...", rootPath, port);
                }
            }while (!success && attemptLimit > 0);


            throw new ChutzpahException("Failed to create web server. This should never be hit!");
        }
Beispiel #11
0
 /// <summary>
 /// Fire Events to Notify testcontainerdiscoverer listeners that containers have changed.
 /// This is the push notification VS uses to update the unit test window.
 ///
 /// The initialContainerSearch check is meant to prevent us from notifying VS about updates
 /// until it is ready
 /// </summary>
 private void OnTestContainersChanged()
 {
     ChutzpahTracer.TraceInformation("Begin OnTestContainersChanged");
     if (TestContainersUpdated != null && !initialContainerSearch)
     {
         TestContainersUpdated(this, EventArgs.Empty);
     }
     ChutzpahTracer.TraceInformation("End OnTestContainersChanged");
 }
Beispiel #12
0
 public void Dispose()
 {
     try
     {
         ChutzpahTracer.TraceInformation("Tearing down Web Server Host at path {0} and port {1}", RootPath, Port);
         IsRunning = false;
         WebHost.Dispose();
     }
     catch (Exception e)
     {
         ChutzpahTracer.TraceError(e, "Error tearing down Web Server Host at path {0} and port {1}", RootPath, Port);
     }
 }
Beispiel #13
0
        /// <summary>
        /// Handler to react to test file Add/remove/rename andcontents changed events
        /// </summary>
        private void OnProjectItemChanged(object sender, TestFileChangedEventArgs e)
        {
            ChutzpahTracer.TraceInformation("Begin OnProjectItemChanged");
            if (e != null)
            {
                // If a chutzpah.json file changed then we set the flag to
                // ensure next time get
                if (fileProbe.IsChutzpahSettingsFile(e.File.Path))
                {
                    forceFullContainerRefresh = true;
                    return;
                }

                // Don't do anything for files we are sure can't be test files
                if (!HasTestFileExtension(e.File.Path))
                {
                    return;
                }

                logger.Log(string.Format("Changed detected for {0} with change type of {1}", e.File, e.ChangedReason),
                           "ChutzpahTestContainerDiscoverer",
                           LogType.Information);

                switch (e.ChangedReason)
                {
                case TestFileChangedReason.Added:
                    ChutzpahTracer.TraceInformation("Adding watch on {0}", e.File.Path);
                    testFilesUpdateWatcher.AddWatch(e.File.Path);
                    AddTestContainerIfTestFile(e.File);

                    break;

                case TestFileChangedReason.Removed:
                    ChutzpahTracer.TraceInformation("Removing watch on {0}", e.File.Path);
                    testFilesUpdateWatcher.RemoveWatch(e.File.Path);
                    RemoveTestContainer(e.File);

                    break;

                case TestFileChangedReason.Changed:
                    AddTestContainerIfTestFile(e.File);
                    break;
                }

                OnTestContainersChanged();
            }

            ChutzpahTracer.TraceInformation("End OnProjectItemChanged");
        }
Beispiel #14
0
        private IEnumerable <TestFileCandidate> FindPotentialTestFiles()
        {
            try
            {
                ChutzpahTracer.TraceInformation("Begin enumerating loaded projects for test files");
                var solution       = (IVsSolution)serviceProvider.GetService(typeof(SVsSolution));
                var loadedProjects = solution.EnumerateLoadedProjects(__VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION).OfType <IVsProject>();

                return(loadedProjects.SelectMany(FindPotentialTestFiles).ToList());
            }
            finally
            {
                ChutzpahTracer.TraceInformation("End enumerating loaded projects for test files");
            }
        }
Beispiel #15
0
        /// <summary>
        /// Will remove a test container for a given file path
        /// </summary>
        /// <param name="file"></param>
        private void RemoveTestContainer(TestFileCandidate file)
        {
            // If a settings file don't add a container
            if (fileProbe.IsChutzpahSettingsFile(file.Path))
            {
                return;
            }

            ITestContainer container;
            var            res = cachedContainers.TryRemove(file.Path, out container);

            if (res)
            {
                ChutzpahTracer.TraceInformation("Removed test container for '{0}'", file.Path);
            }
        }
        /// <summary>
        /// Will remove a test container for a given file path
        /// </summary>
        /// <param name="file"></param>
        private void RemoveTestContainer(TestFileCandidate file)
        {
            // If a settings file don't add a container
            if (fileProbe.IsChutzpahSettingsFile(file.Path))
            {
                return;
            }

            var index = cachedContainers.FindIndex(x => x.Source.Equals(file.Path, StringComparison.OrdinalIgnoreCase));

            if (index >= 0)
            {
                ChutzpahTracer.TraceInformation("Removed test container for '{0}'", file.Path);
                cachedContainers.RemoveAt(index);
            }
        }
 public void Dispose()
 {
     try
     {
         ChutzpahTracer.TraceInformation("Tearing down Web Server Host at path {0} and port {1}", RootPath, Port);
         NancyHost.Dispose();
     }
     catch (Exception e)
     {
         ChutzpahTracer.TraceError(e, "Error tearing down Web Server Host at path {0} and port {1}", RootPath, Port);
     }
     finally
     {
         // Set active server to null
         Interlocked.Exchange(ref activeWebServer, null);
     }
 }
Beispiel #18
0
        public void PrepareTestHarnessForCoverage(TestHarness harness, IFrameworkDefinition definition, ChutzpahTestSettingsFile testSettingsFile)
        {
            string blanketScriptName = GetBlanketScriptName(definition, testSettingsFile);

            // Construct array of scripts to exclude from instrumentation/coverage collection.
            var filesToExcludeFromCoverage =
                harness.TestFrameworkDependencies.Concat(harness.CodeCoverageDependencies)
                .Where(dep => dep.HasFile && IsScriptFile(dep.ReferencedFile))
                .Select(dep => dep.Attributes["src"])
                .Concat(excludePatterns.Select(ToRegex))
                .ToList();

            var filesToIncludeInCoverage = includePatterns.Select(ToRegex).ToList();

            foreach (TestHarnessItem refScript in harness.ReferencedScripts.Where(rs => rs.HasFile))
            {
                // Exclude files which the user is asking us to ignores
                if (!IsFileEligibleForInstrumentation(refScript.ReferencedFile.Path))
                {
                    filesToExcludeFromCoverage.Add(refScript.Attributes["src"]);
                }
                else
                {
                    refScript.Attributes["type"] = "text/blanket"; // prevent Phantom/browser parsing
                }
            }

            // Name the coverage object so that the JS runner can pick it up.
            harness.ReferencedScripts.Add(new Script(string.Format("window.{0}='_$blanket';", Constants.ChutzpahCoverageObjectReference)));

            // Configure Blanket.
            TestHarnessItem blanketMain = harness.CodeCoverageDependencies.Single(
                d => d.Attributes.ContainsKey("src") && d.Attributes["src"].EndsWith(blanketScriptName));

            string dataCoverNever = "[" + string.Join(",", filesToExcludeFromCoverage.Select(file => "'" + file + "'")) + "]";

            string dataCoverOnly = filesToIncludeInCoverage.Any()
                                   ? "[" + string.Join(",", filesToIncludeInCoverage.Select(file => "'" + file + "'")) + "]"
                                   : "//.*/";

            ChutzpahTracer.TraceInformation("Adding data-cover-never attribute to blanket: {0}", dataCoverNever);

            blanketMain.Attributes.Add("data-cover-flags", "ignoreError autoStart");
            blanketMain.Attributes.Add("data-cover-only", dataCoverOnly);
            blanketMain.Attributes.Add("data-cover-never", dataCoverNever);
        }
Beispiel #19
0
        /// <summary>
        /// Adds a test container for the given file if it is a test file.
        /// This will first remove any existing container for that file
        /// </summary>
        /// <param name="file"></param>
        private void AddTestContainerIfTestFile(TestFileCandidate file)
        {
            // If a settings file don't add a container
            if (fileProbe.IsChutzpahSettingsFile(file.Path))
            {
                return;
            }

            var isTestFile = IsTestFile(file.Path);

            RemoveTestContainer(file); // Remove if there is an existing container

            if (isTestFile)
            {
                ChutzpahTracer.TraceInformation("Added test container for '{0}'", file.Path);
                var container = new JsTestContainer(this, file.Path.ToLowerInvariant(), AdapterConstants.ExecutorUri);
                cachedContainers[container.Source] = container;
            }
        }
        /// <summary>
        /// Comapre this test container to another one
        /// They are the same if same source and timestamp
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public int CompareTo(ITestContainer other)
        {
            var testContainer = other as JsTestContainer;

            if (testContainer == null)
            {
                return(-1);
            }

            var result = String.Compare(this.Source, testContainer.Source, StringComparison.OrdinalIgnoreCase);

            if (result != 0)
            {
                return(result);
            }

            ChutzpahTracer.TraceInformation("Test container comparision {0} vs {1} for {2}", this.timeStamp, testContainer.timeStamp, this.Source);

            return(this.timeStamp.CompareTo(testContainer.timeStamp));
        }
        private IEnumerable <TestFileCandidate> FindPotentialTestFiles(IVsProject project)
        {
            string projectPath = VsSolutionHelper.GetProjectPath(project);

            try
            {
                ChutzpahTracer.TraceInformation("Begin selecting potential test files from project '{0}'", projectPath);
                return((from item in VsSolutionHelper.GetProjectItems(project)
                        let hasTestExtension = HasTestFileExtension(item)
                                               let isChutzpahSettingsFile = fileProbe.IsChutzpahSettingsFile(item)
                                                                            where !fileProbe.IsTemporaryChutzpahFile(item) && (hasTestExtension || isChutzpahSettingsFile)
                                                                            select new TestFileCandidate
                {
                    Path = item
                }).ToList());
            }
            finally
            {
                ChutzpahTracer.TraceInformation("End selecting potential test files from project '{0}'", projectPath);
            }
        }
        /// <summary>
        /// After a project is loaded or unloaded either add or remove from the file watcher
        /// all test potential items inside that project
        /// </summary>
        private void UpdateTestContainersAndFileWatchers(IEnumerable <TestFileCandidate> files, bool isAdd)
        {
            ChutzpahTracer.TraceInformation("Begin UpdateTestContainersAndFileWatchers");
            foreach (var file in files)
            {
                if (isAdd)
                {
                    ChutzpahTracer.TraceInformation("Adding watch on {0}", file.Path);
                    testFilesUpdateWatcher.AddWatch(file.Path);
                    AddTestContainerIfTestFile(file);
                }
                else
                {
                    ChutzpahTracer.TraceInformation("Removing watch on {0}", file.Path);
                    testFilesUpdateWatcher.RemoveWatch(file.Path);
                    RemoveTestContainer(file);
                }
            }

            ChutzpahTracer.TraceInformation("End UpdateTestContainersAndFileWatchers");
        }
Beispiel #23
0
        public override void TestSuiteFinished(TestCaseSummary testResultsSummary)
        {
            base.TestSuiteFinished(testResultsSummary);

            if (!runContext.IsDataCollectionEnabled || testResultsSummary.CoverageObject == null)
            {
                return;
            }

            try
            {
                // If we do not have a solutiondirectory, we assume that we are running in tfs build
                // In that case we only write to the testrundirectory and do not open a browser
                if (string.IsNullOrEmpty(runContext.SolutionDirectory))
                {
                    ChutzpahTracer.TraceInformation("Chutzpah runs in TFSBuild, writing coverage file to {0}", runContext.TestRunDirectory);

                    var directory = runContext.TestRunDirectory;
                    CoverageOutputGenerator.WriteHtmlFile(directory, testResultsSummary.CoverageObject);
                    CoverageOutputGenerator.WriteJsonFile(directory, testResultsSummary.CoverageObject);
                }
                else
                {
                    ChutzpahTracer.TraceInformation("Chutzpah runs not in TFSBuild opening coverage file in browser");

                    var directory        = runContext.SolutionDirectory;
                    var coverageHtmlFile = CoverageOutputGenerator.WriteHtmlFile(directory, testResultsSummary.CoverageObject);
                    var processHelper    = new ProcessHelper();

                    processHelper.LaunchFileInBrowser(coverageHtmlFile);
                }
            }
            catch (Exception e)
            {
                frameworkHandle.SendMessage(TestMessageLevel.Error, string.Format("Error while writing coverage output: {0}", e));
            }
        }
Beispiel #24
0
        public void Compile(IEnumerable <TestContext> testContexts)
        {
            // Group the test contexts by test settings to run batch aware settings like compile
            // For each test settings file that defines a compile step we will run it and update
            // testContexts reference files accordingly.
            var groupedTestContexts = testContexts.GroupBy(x => x.TestFileSettings);

            foreach (var contextGroup in groupedTestContexts)
            {
                var testSettings = contextGroup.Key;

                // If there is no compile setting then nothing to do here
                if (testSettings.Compile == null)
                {
                    continue;
                }

                // Build the mapping from source to output files and gather properties about them
                var filePropeties = (
                    from file in contextGroup.SelectMany(x => x.ReferencedFiles).Distinct()
                    where testSettings.Compile.Extensions.Any(x => file.Path.EndsWith(x, StringComparison.OrdinalIgnoreCase))
                    let sourceProperties = GetFileProperties(file.Path)
                                           let sourceHasOutput = !testSettings.Compile.ExtensionsWithNoOutput.Any(x => file.Path.EndsWith(x, StringComparison.OrdinalIgnoreCase))
                                                                 let outputPath = GetOutputPath(file.Path, testSettings.Compile)
                                                                                  let outputProperties = sourceHasOutput ? GetFileProperties(outputPath) : null
                                                                                                         select new SourceCompileInfo {
                    SourceProperties = sourceProperties, OutputProperties = outputProperties, SourceHasOutput = sourceHasOutput
                }).ToList();

                var outputPathMap = filePropeties
                                    .Where(x => x.SourceHasOutput)
                                    .ToDictionary(x => x.SourceProperties.Path, x => x.OutputProperties.Path, StringComparer.OrdinalIgnoreCase);

                // Check if the batch compile is needed
                var shouldCompile = CheckIfCompileIsNeeded(testSettings, filePropeties);

                // Run the batch compile if necessary
                if (shouldCompile)
                {
                    if (testSettings.Compile.Mode == BatchCompileMode.Executable)
                    {
                        RunBatchCompile(testSettings);
                    }
                    else if (testSettings.Compile.Mode == BatchCompileMode.External)
                    {
                        ChutzpahTracer.TraceError("Chutzpah determined generated .js files are missing but the compile mode is External so Chutzpah can't compile them. Test results may be wrong.");
                    }
                }
                else
                {
                    ChutzpahTracer.TraceInformation("Skipping batch compile since all files are supdate to date for {0}", testSettings.SettingsFileName);
                }

                // Now that compile finished set generated path on  all files who match the compiled extensions
                var filesToUpdate = contextGroup.SelectMany(x => x.ReferencedFiles)
                                    .Where(x => outputPathMap.ContainsKey(x.Path));

                foreach (var file in filesToUpdate)
                {
                    var outputPath = outputPathMap[file.Path];
                    if (outputPath != null && fileSystem.FileExists(outputPath))
                    {
                        file.GeneratedFilePath = outputPath;
                        ChutzpahTracer.TraceInformation("Found generated path for {0} at {1}", file.Path, outputPath);
                    }
                    else
                    {
                        ChutzpahTracer.TraceWarning("Couldn't find generated path for {0} at {1}", file.Path, outputPath);
                    }

                    if (!string.IsNullOrWhiteSpace(file.GeneratedFilePath))
                    {
                        file.SourceMapFilePath = testSettings.Compile.UseSourceMaps ? sourceMapDiscoverer.FindSourceMap(file.GeneratedFilePath) : null;
                    }
                }
            }
        }
        public void Compile(IEnumerable <TestContext> testContexts, ITestMethodRunnerCallback callback = null)
        {
            // Group the test contexts by test settings to run batch aware settings like compile
            // For each test settings file that defines a compile step we will run it and update
            // testContexts reference files accordingly.
            var groupedTestContexts = testContexts.GroupBy(x => x.TestFileSettings);

            foreach (var contextGroup in groupedTestContexts)
            {
                var testSettings = contextGroup.Key;

                // If there is no compile setting then nothing to do here
                if (testSettings.Compile == null)
                {
                    continue;
                }

                // Build the mapping from source to output files and gather properties about them
                var filePropeties = (
                    from file in contextGroup.SelectMany(x => x.ReferencedFiles).Where(x => !x.IsBuiltInDependency).Distinct()
                    where testSettings.Compile.Extensions.Any(x => file.Path.EndsWith(x, StringComparison.OrdinalIgnoreCase))
                    let sourceProperties = GetFileProperties(file.Path)
                                           let sourceHasOutput = !testSettings.Compile.ExtensionsWithNoOutput.Any(x => file.Path.EndsWith(x, StringComparison.OrdinalIgnoreCase))
                                                                 let outputPath = GetOutputPath(file.Path, testSettings.Compile)
                                                                                  let outputProperties = sourceHasOutput ? GetFileProperties(outputPath) : null
                                                                                                         select new SourceCompileInfo {
                    SourceProperties = sourceProperties, OutputProperties = outputProperties, SourceHasOutput = sourceHasOutput
                }).ToList();

                var outputPathMap = filePropeties
                                    .Where(x => x.SourceHasOutput)
                                    .ToDictionary(x => x.SourceProperties.Path, x => x.OutputProperties.Path, StringComparer.OrdinalIgnoreCase);

                // Check if the batch compile is needed
                var shouldCompile = CheckIfCompileIsNeeded(testSettings, filePropeties);

                // Run the batch compile if necessary
                if (shouldCompile)
                {
                    if (testSettings.Compile.Mode == BatchCompileMode.Executable)
                    {
                        RunBatchCompile(testSettings);
                    }
                    else
                    {
                        ChutzpahTracer.TraceWarning("Chutzpah determined generated .js files are missing but the compile mode is External so Chutzpah can't compile them. Test results may be wrong.");
                    }
                }
                else
                {
                    ChutzpahTracer.TraceInformation("Skipping batch compile since all files are update to date for {0}", testSettings.SettingsFileName);
                }

                // Now that compile finished set generated path on  all files who match the compiled extensions
                var filesToUpdate = contextGroup.SelectMany(x => x.ReferencedFiles)
                                    .Where(x => outputPathMap.ContainsKey(x.Path));

                foreach (var file in filesToUpdate)
                {
                    var outputPath = outputPathMap[file.Path];
                    if (outputPath != null && fileSystem.FileExists(outputPath))
                    {
                        file.GeneratedFilePath = outputPath;
                        ChutzpahTracer.TraceInformation("Found generated path for {0} at {1}", file.Path, outputPath);
                    }
                    else
                    {
                        // If we could not find the file at the configured path attempt to see if it co-located
                        ChutzpahTracer.TraceInformation("Unable to find generated path at configured location so attempting to see if generated file is co-located.");
                        var coLocatedOutputPath = Path.ChangeExtension(file.Path, ".js");
                        if (fileSystem.FileExists(coLocatedOutputPath))
                        {
                            file.GeneratedFilePath = coLocatedOutputPath;
                            ChutzpahTracer.TraceInformation("Found generated path for {0} at {1}", file.Path, coLocatedOutputPath);
                        }
                        else
                        {
                            var error = string.Format("Couldn't find generated path for {0} at {1} or at {2}", file.Path, outputPath, coLocatedOutputPath);
                            ChutzpahTracer.TraceError(error);

                            if (!testSettings.Compile.IgnoreMissingFiles.GetValueOrDefault())
                            {
                                // Throw and fail here since if we cant find the file we cannot be sure anything will run
                                var exception = new FileNotFoundException(error, outputPath);
                                callback.ExceptionThrown(exception, outputPath);
                            }
                        }
                    }

                    if (!string.IsNullOrWhiteSpace(file.GeneratedFilePath))
                    {
                        file.SourceMapFilePath = testSettings.Compile.UseSourceMaps.GetValueOrDefault() ? sourceMapDiscoverer.FindSourceMap(file.GeneratedFilePath) : null;
                    }
                }
            }
        }
Beispiel #26
0
 /// <summary>
 /// The solution was unloaded so we need to indicate that next time containers are requested we do a full search
 /// </summary>
 private void SolutionListenerOnSolutionUnloaded(object sender, EventArgs eventArgs)
 {
     ChutzpahTracer.TraceInformation("Solution Unloaded...");
     initialContainerSearch = true;
 }