示例#1
0
        public string ScreenRecordingTestSettingsFile(string JobName)
        {
            var TestSettingsFile = "";

            if (RecordScreen != null)
            {
                var TestSettingsId = Guid.NewGuid();

                // Create test settings.
                TestSettingsFile = TestRunner.TestsResultsPath + "\\" + JobName + ".testsettings";
                TestCleanupUtils.CopyOnWrite(TestSettingsFile);
                File.WriteAllText(TestSettingsFile, @"<?xml version=""1.0"" encoding=""UTF-8""?>
<TestSettings id=""" + TestSettingsId + @""" name=""JobName"" xmlns=""http://microsoft.com/schemas/VisualStudio/TeamTest/2010"">
    <Description>Run " + JobName + @" With Screen Recording.</Description>
    <NamingScheme baseName=""ScreenRecordings"" appendTimeStamp=""false"" useDefault=""false""/>
    <Execution>
    <AgentRule name=""LocalMachineDefaultRole"">
        <DataCollectors>
        <DataCollector uri=""datacollector://microsoft/VideoRecorder/1.0"" assemblyQualifiedName=""Microsoft.VisualStudio.TestTools.DataCollection.VideoRecorder.VideoRecorderDataCollector, Microsoft.VisualStudio.TestTools.DataCollection.VideoRecorder, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"" friendlyName=""Screen and Voice Recorder"">
            <Configuration>
            <MediaRecorder sendRecordedMediaForPassedTestCase=""false"" xmlns=""""/>
            </Configuration>
        </DataCollector>
        </DataCollectors>
    </AgentRule>
    </Execution>
</TestSettings>
");
            }
            return(TestSettingsFile);
        }
示例#2
0
        string ProgressFeedback(StreamReader reader)
        {
            var    result    = "";
            string writePath = Environment.ExpandEnvironmentVariables(ProgressFeedbackFilePath);

            TestCleanupUtils.WaitForFileUnlock(writePath);
            TestCleanupUtils.CopyOnWrite(writePath);
            string startMessageText = $"Starting pull at {DateTime.Now.ToLongTimeString()} on {DateTime.Now.ToLongDateString()}:";
            var    startMessage     = Encoding.UTF8.GetBytes(startMessageText);

            File.WriteAllText(writePath, startMessageText);
            using (var fileWriteStream = new FileStream(writePath, FileMode.Open, FileAccess.Write, FileShare.Read))
            {
                fileWriteStream.Position = startMessage.Length;
                while (!reader.EndOfStream)
                {
                    var readChar = (char)reader.Read();
                    result += readChar;
                    fileWriteStream.WriteByte((byte)readChar);
                }
                byte[] finishedMessage = Encoding.UTF8.GetBytes($"Finished pull at {DateTime.Now.ToLongTimeString()} on {DateTime.Now.ToLongDateString()}.");
                fileWriteStream.Write(finishedMessage, 0, finishedMessage.Length);
            }
            return(result);
        }
示例#3
0
        public void RetryTestFailures(string jobName, string testAssembliesList, List <string> TestAssembliesDirectories, string testSettingsFile, string FullTRXFilePath, int currentRetryCount)
        {
            TestRunner.TestsResultsPath = Path.Combine(TestRunner.TestsResultsPath, "..", NumberToWords(currentRetryCount) + "RetryTestResults");
            TestRunner.TestsResultsPath = Path.GetFullPath((new Uri(TestRunner.TestsResultsPath)).LocalPath);
            if (ciRemoteContainerLauncher != null)
            {
                ciRemoteContainerLauncher.LogOutputDirectory = TestRunner.TestsResultsPath;
            }

            TestCleanupUtils.WaitForFileUnlock(FullTRXFilePath);
            TestRunner.TestList = "";
            var         TestFailures = new List <string>();
            XmlDocument trxContent   = new XmlDocument();

            trxContent.Load(FullTRXFilePath);
            var namespaceManager = new XmlNamespaceManager(trxContent.NameTable);

            namespaceManager.AddNamespace("a", "http://microsoft.com/schemas/VisualStudio/TeamTest/2010");
            if (trxContent.DocumentElement.SelectNodes("/a:TestRun/a:TestDefinitions/a:UnitTest/a:TestMethod", namespaceManager).Count > 0)
            {
                foreach (XmlNode TestResult in trxContent.DocumentElement.SelectNodes("/a:TestRun/a:Results/a:UnitTestResult", namespaceManager))
                {
                    if (TestResult.Attributes["outcome"] == null || TestResult.Attributes["outcome"].InnerText == "Failed")
                    {
                        TestFailures.Add(TestResult.Attributes["testName"].InnerXml);
                    }
                }
            }
            else
            {
                Console.WriteLine($"Error parsing /TestRun/Results/UnitTestResult from trx file at {FullTRXFilePath}");
            }
            string TestRunnerPath;

            if (TestFailures.Count > 0)
            {
                TestRunner.TestList = string.Join(",", TestFailures);
                TestRunnerPath      = TestRunner.WriteTestRunner(jobName, "", "", testAssembliesList, testSettingsFile, Path.Combine(TestRunner.TestsResultsPath, "RetryResults"), RecordScreen != null, JobSpecs);
            }
            else
            {
                Console.WriteLine($"No failing tests found to retry in trx file at {FullTRXFilePath}");
                return;
            }
            Console.WriteLine($"Re-running all test failures in \"{FullTRXFilePath}\".");
            var retryResults = RunTests(jobName, testAssembliesList, TestAssembliesDirectories, testSettingsFile, TestRunnerPath);

            if (!string.IsNullOrEmpty(retryResults) && retryResults != FullTRXFilePath)
            {
                TestResultsMerger.MergeRetryResults(FullTRXFilePath, retryResults);
            }
            else
            {
                Console.WriteLine($"{TestRunnerPath} did not produce a test result trx file in {TestRunner.TestsResultsPath}");
            }
        }
示例#4
0
        public string DotCoverRunner(string JobName, List <string> TestAssembliesDirectories)
        {
            // Write DotCover Runner XML
            var DotCoverSnapshotFile = Path.Combine(TestRunner.TestsResultsPath, $"{JobName} DotCover Output.dcvr");

            TestCleanupUtils.CopyOnWrite(DotCoverSnapshotFile);
            var DotCoverArgs = @"<AnalyseParams>
    <TargetExecutable>" + TestRunner.TestsResultsPath + "\\..\\Run " + JobName + @".bat</TargetExecutable>
    <Output>" + DotCoverSnapshotFile + @"</Output>
    <Scope>";

            foreach (var TestAssembliesDirectory in TestAssembliesDirectories)
            {
                DotCoverArgs += @"
        <ScopeEntry>" + TestAssembliesDirectory + @"\*.dll</ScopeEntry>
        <ScopeEntry>" + TestAssembliesDirectory + @"\*.exe</ScopeEntry>";
            }
            DotCoverArgs += @"
    </Scope>
    <Filters>
        <ExcludeFilters>
            <FilterEntry>
                <ModuleMask>*.tests</ModuleMask>
                <ModuleMask>*.specs</ModuleMask>
            </FilterEntry>
        </ExcludeFilters>
        <AttributeFilters>
            <AttributeFilterEntry>
                <ClassMask>System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute</ClassMask>
            </AttributeFilterEntry>
        </AttributeFilters>
    </Filters>
</AnalyseParams>";
            var DotCoverRunnerXMLPath = Path.Combine(TestRunner.TestsResultsPath, JobName + " DotCover Runner.xml");

            TestCleanupUtils.CopyOnWrite(DotCoverRunnerXMLPath);
            File.WriteAllText(DotCoverRunnerXMLPath, DotCoverArgs);

            // Create full DotCover argument string.
            var DotCoverLogFile = TestRunner.TestsResultsPath + "\\DotCover.xml.log";

            TestCleanupUtils.CopyOnWrite(DotCoverLogFile);
            var FullArgsList = $" cover \"{DotCoverRunnerXMLPath}\" /LogFile=\"{DotCoverLogFile}\"";

            // Write DotCover Runner Batch File
            var DotCoverRunnerPath = $"{TestRunner.TestsResultsPath}\\Run {JobName} DotCover.bat";

            TestCleanupUtils.CopyOnWrite(DotCoverRunnerPath);
            File.WriteAllText(DotCoverRunnerPath, $"\"{DotCoverPath}\"{FullArgsList}");
            return(DotCoverRunnerPath);
        }
示例#5
0
        void WaitForStudioStart(string StudioFolderPath)
        {
            var StudioStartedFilePath = Path.Combine(StudioFolderPath, "StudioStarted");

            TestCleanupUtils.WaitForFileExist(StudioStartedFilePath);
            if (!(File.Exists(StudioStartedFilePath)))
            {
                throw new Exception("Studio Cannot Start.");
            }
            else
            {
                Console.WriteLine("Studio has started.");
            }
        }
示例#6
0
        void WaitForServerStart(string ServerFolderPath)
        {
            var ServerStartedFilePath = ServerFolderPath + "\\ServerStarted";

            TestCleanupUtils.WaitForFileExist(ServerStartedFilePath);
            if (!(File.Exists(ServerStartedFilePath)))
            {
                throw new Exception("Server Cannot Start.");
            }
            else
            {
                Console.WriteLine("Server has started.");
            }
        }
示例#7
0
        public void StartStudio()
        {
            if (string.IsNullOrEmpty(StudioPath))
            {
                throw new FileNotFoundException("Cannot find Warewolf Studio. To run the studio provide a path to the Warewolf Studio exe file as a commandline parameter like this: -StudioPath");
            }
            var StudioLogFile = Environment.ExpandEnvironmentVariables("%LocalAppData%\\Warewolf\\Studio Logs\\Warewolf Studio.log");

            TestCleanupUtils.CopyOnWrite(StudioLogFile);
            if (!ApplyDotCover)
            {
                Process.Start(StudioPath);
            }
            else
            {
                var StudioBinDir          = Path.GetDirectoryName(StudioPath);
                var RunnerXML             = @"
<AnalyseParams>
    <TargetExecutable>" + StudioPath + @"</TargetExecutable>
    <Output>" + Environment.ExpandEnvironmentVariables("%LocalAppData%") + @"\Warewolf\Studio Logs\dotCover.dcvr</Output>
    <Scope>
        <ScopeEntry>" + StudioBinDir + @"\*.dll</ScopeEntry>
        <ScopeEntry>" + StudioBinDir + @"\*.exe</ScopeEntry>
    </Scope>
    <Filters>
        <ExcludeFilters>
            <FilterEntry>
                <ModuleMask>*.tests</ModuleMask>
                <ModuleMask>*.specs</ModuleMask>
            </FilterEntry>
        </ExcludeFilters>
        <AttributeFilters>
            <AttributeFilterEntry>
                <ClassMask>System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute</ClassMask>
            </AttributeFilterEntry>
        </AttributeFilters>
    </Filters>
</AnalyseParams>
";
                var DotCoverRunnerXMLPath = TestRunner.TestsResultsPath + "\\Studio DotCover Runner.xml";
                TestCleanupUtils.CopyOnWrite(DotCoverRunnerXMLPath);
                File.WriteAllText(DotCoverRunnerXMLPath, RunnerXML);
                Process.Start(DotCoverPath, "cover \"" + DotCoverRunnerXMLPath + "\" /LogFile=\"" + TestRunner.TestsResultsPath + "\\StudioDotCover.log\"");
            }
            try
            {
                WaitForStudioStart(Path.GetDirectoryName(StudioPath));
            }
            catch (Exception)
            {
                if (!ApplyDotCover)
                {
                    Process.Start(StudioPath);
                }
                else
                {
                    Process.Start(DotCoverPath, "cover \"" + TestRunner.TestsResultsPath + "\\Studio DotCover Runner.xml\" /LogFile=\"" + TestRunner.TestsResultsPath + "\\StudioDotCover.log\"");
                }
                WaitForStudioStart(Path.GetDirectoryName(StudioPath));
            }
        }
示例#8
0
        public void InstallServer()
        {
            //Find Server
            if (string.IsNullOrEmpty(ServerPath))
            {
                bool foundServer = TryFindWarewolfServerExe(out string serverPath);
                if (foundServer)
                {
                    ServerPath = serverPath;
                }
                else
                {
                    throw new ArgumentException($"No server found. Make sure your server is compiled and try again.");
                }
            }
            else
            {
                if (!File.Exists(ServerPath))
                {
                    throw new ArgumentException($"No server found at {ServerPath}. Make sure your server is compiled and try again.");
                }
            }
            Console.WriteLine("Will now stop any currently running Warewolf servers and studios. Resources will be backed up to " + TestRunner.TestsResultsPath + ".");
            if (string.IsNullOrEmpty(ResourcesType))
            {
                Console.WriteLine("\nWhat type of resources would you like to install the server with?");
                var options = new[] {
                    "[u]UITests: Use these resources for running UI Tests. (This is the default)",
                    "[s]ServerTests: Use these resources for running everything except unit tests and Coded UI tests.",
                    "[r]Release: Use these resources for Warewolf releases.",
                    "[l]Load: Use these resources for Desktop UI Load Testing."
                };
                foreach (var option in options)
                {
                    Console.WriteLine();
                    var originalColour = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.Write(option.Substring(0, 3));
                    Console.ForegroundColor = originalColour;
                    Console.Write(option.Substring(3, option.Length - 3));
                }
                Console.WriteLine("\n\nOr Press Enter to use default (UITest)...");

                ResourcesType = WindowUtils.PromptForUserInput();
                if (ResourcesType == "" || ResourcesType.ToLower() == "u")
                {
                    ResourcesType = "UITests";
                }
                if (ResourcesType.ToLower() == "s")
                {
                    ResourcesType = "ServerTests";
                }
                if (ResourcesType.ToLower() == "r")
                {
                    ResourcesType = "Release";
                }
                if (ResourcesType.ToLower() == "l")
                {
                    ResourcesType = "Load";
                }
            }

            string resourcesPath = Path.Combine(Path.GetDirectoryName(ServerPath), $"Resources - {ResourcesType}");

            if (!Directory.Exists(resourcesPath))
            {
                throw new ArgumentException($"Invalid resource type. Folder not found {resourcesPath}");
            }

            if (!StartServerAsConsole)
            {
                var ServerService = ServiceController.GetServices().Any(serviceController => serviceController.ServiceName.Equals("Warewolf Server"));
                if (!ApplyDotCover)
                {
                    if (!ServerService)
                    {
                        Process.Start("sc.exe", "create \"Warewolf Server\" binPath= \"" + ServerPath + "\" start= demand");
                    }
                    else
                    {
                        Console.WriteLine("Configuring service to " + ServerPath);
                        Process.Start("sc.exe", "config \"Warewolf Server\" binPath= \"" + ServerPath + "\" start= demand");
                    }
                }
                else
                {
                    var ServerBinDir = Path.GetDirectoryName(ServerPath);
                    var RunnerXML    = @"<AnalyseParams>
    <TargetExecutable>" + ServerPath + @"</TargetExecutable>
    <Output>" + Environment.ExpandEnvironmentVariables("%ProgramData%") + @"\Warewolf\Server Log\dotCover.dcvr</Output>
    <Scope>
	    <ScopeEntry>"     + ServerBinDir + @"\*.dll</ScopeEntry>
	    <ScopeEntry>"     + ServerBinDir + @"\*.exe</ScopeEntry>
    </Scope>
    <Filters>
        <ExcludeFilters>
            <FilterEntry>
                <ModuleMask>*.tests</ModuleMask>
                <ModuleMask>*.specs</ModuleMask>
            </FilterEntry>
        </ExcludeFilters>
        <AttributeFilters>
            <AttributeFilterEntry>
                <ClassMask>System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute</ClassMask>
            </AttributeFilterEntry>
        </AttributeFilters>
    </Filters>
</AnalyseParams>";

                    var DotCoverRunnerXMLPath = TestRunner.TestsResultsPath + "\\Server DotCover Runner.xml";
                    TestCleanupUtils.CopyOnWrite(DotCoverRunnerXMLPath);
                    File.WriteAllText(DotCoverRunnerXMLPath, RunnerXML);
                    RunServerWithDotcoverScript = "\\\"" + DotCoverPath + "\\\" cover \\\"" + DotCoverRunnerXMLPath + "\\\" /LogFile=\\\"" + TestRunner.TestsResultsPath + "\\ServerDotCover.log\\\"";
                    if (!ServerService)
                    {
                        Process.Start("sc.exe", "create \"Warewolf Server\" binPath= \"" + RunServerWithDotcoverScript + "\" start= demand");
                    }
                    else
                    {
                        Console.WriteLine("Configuring service to " + RunServerWithDotcoverScript);
                        Process.Start("sc.exe", "config \"Warewolf Server\" binPath= \"" + RunServerWithDotcoverScript + "\"");
                    }
                }
            }
            if (!string.IsNullOrEmpty(ServerUsername) && string.IsNullOrEmpty(ServerPassword))
            {
                Process.Start("sc.exe", "config \"Warewolf Server\" obj= \"" + ServerUsername + "\"");
            }
            if (!string.IsNullOrEmpty(ServerUsername) && !string.IsNullOrEmpty(ServerPassword))
            {
                Process.Start("sc.exe", "config \"Warewolf Server\" obj= \"" + ServerUsername + "\" password= \"" + ServerPassword + "\"");
            }

            var ResourcePathSpecs = new List <string>();

            foreach (var ServerPathSpec in ServerPathSpecs)
            {
                if (ServerPathSpec.EndsWith(ServerExeName))
                {
                    ResourcePathSpecs.Add(ServerPathSpec.Replace(ServerExeName, "Resources - " + ResourcesType));
                }
            }
            var ResourcesDirectory = FindFileInParent(ResourcePathSpecs);

            if (ResourcesDirectory != "" && ResourcesDirectory != Path.GetDirectoryName(ServerPath) + "\\" + Path.GetFileName(ResourcesDirectory))
            {
                RecursiveFolderCopy(ResourcesDirectory, Path.GetDirectoryName(ServerPath));
            }
        }
示例#9
0
        public static void MoveArtifactsToTestResults(this TestLauncher build, bool DotCover, bool Server, bool Studio)
        {
            if (build.Cleanup)
            {
                foreach (var FullTRXFilePath in Directory.GetFiles(build.TestRunner.TestsResultsPath, "*.trx"))
                {
                    XmlDocument trxContent = new XmlDocument();
                    trxContent.Load(FullTRXFilePath);
                    var namespaceManager = new XmlNamespaceManager(trxContent.NameTable);
                    namespaceManager.AddNamespace("a", "http://microsoft.com/schemas/VisualStudio/TeamTest/2010");
                    if (trxContent.DocumentElement.SelectSingleNode("/a:TestRun/a:ResultSummary", namespaceManager).Attributes["outcome"].Value != "Completed")
                    {
                        WriteFailingTestPlaylist($"{build.TestRunner.TestsResultsPath}\\{build.JobName} Failures.playlist", FullTRXFilePath, trxContent, namespaceManager);
                    }
                }
            }

            if (Studio)
            {
                string studioLogFile = Environment.ExpandEnvironmentVariables(@"%LocalAppData%\Warewolf\Studio Logs\Warewolf Studio.log");
                WaitForFileUnlock(studioLogFile);
                MoveFileToTestResults(studioLogFile, $"{build.JobName} Studio.log", build.TestRunner.TestsResultsPath);
            }
            if (Studio && DotCover)
            {
                var StudioSnapshot = Environment.ExpandEnvironmentVariables(@"%LocalAppData%\Warewolf\Studio Logs\dotCover.dcvr");
                Console.WriteLine($"Trying to move Studio coverage snapshot file from {StudioSnapshot} to {build.TestRunner.TestsResultsPath}\\{build.JobName} Studio DotCover.dcvr");
                var exists = WaitForFileExist(StudioSnapshot);
                if (exists)
                {
                    var locked = WaitForFileUnlock(StudioSnapshot);
                    if (!(locked))
                    {
                        Console.WriteLine($"Moving Studio coverage snapshot file from StudioSnapshot to {build.TestRunner.TestsResultsPath}\\{build.JobName} Studio DotCover.dcvr");
                        CopyOnWrite($"{build.TestRunner.TestsResultsPath}\\{build.JobName} Studio DotCover.dcvr");
                        File.Move(StudioSnapshot, $"{build.TestRunner.TestsResultsPath}\\{build.JobName} Studio DotCover.dcvr");
                    }
                    else
                    {
                        Console.WriteLine("Studio Coverage Snapshot File is locked.");
                    }
                }
                else
                {
                    throw new FileNotFoundException($"Studio coverage snapshot not found at {StudioSnapshot}");
                }
                if (File.Exists(Environment.ExpandEnvironmentVariables(@"%LocalAppData%\Warewolf\Studio Logs\dotCover.log")))
                {
                    MoveFileToTestResults(Environment.ExpandEnvironmentVariables(@"%LocalAppData%\Warewolf\Studio Logs\dotCover.log"), $"{build.JobName} Studio DotCover.log", build.TestRunner.TestsResultsPath);
                }
            }
            if (Server)
            {
                string serverLogFile = Environment.ExpandEnvironmentVariables(@"%ProgramData%\Warewolf\Server Log\wareWolf-Server.log");
                WaitForFileUnlock(serverLogFile);
                MoveFileToTestResults(serverLogFile, $"{build.JobName} Server.log", build.TestRunner.TestsResultsPath);

                string myWarewolfIoLogFile = Environment.ExpandEnvironmentVariables(@"%ProgramData%\Warewolf\Server Log\my.warewolf.io.log");
                WaitForFileUnlock(serverLogFile);
                MoveFileToTestResults(myWarewolfIoLogFile, $"{build.JobName} my.warewolf.io Server.log", build.TestRunner.TestsResultsPath);

                string myWarewolfIoErrorsLogFile = Environment.ExpandEnvironmentVariables(@"%ProgramData%\Warewolf\Server Log\my.warewolf.io.errors.log");
                WaitForFileUnlock(myWarewolfIoErrorsLogFile);
                MoveFileToTestResults(myWarewolfIoErrorsLogFile, $"{build.JobName} my.warewolf.io Server Errors.log", build.TestRunner.TestsResultsPath);
            }
            if (Server && DotCover)
            {
                var ServerSnapshot = Environment.ExpandEnvironmentVariables(@"%ProgramData%\Warewolf\Server Log\dotCover.dcvr");
                Console.WriteLine($"Trying to move Server coverage snapshot file from {ServerSnapshot} to {build.TestRunner.TestsResultsPath}\\{build.JobName} Server DotCover.dcvr");
                var exists = WaitForFileExist(ServerSnapshot);
                if (exists)
                {
                    var locked = WaitForFileUnlock(ServerSnapshot);
                    if (!locked)
                    {
                        Console.WriteLine($"Moving Server coverage snapshot file from {ServerSnapshot} to {build.TestRunner.TestsResultsPath}\\{build.JobName} Server DotCover.dcvr");
                        MoveFileToTestResults(ServerSnapshot, $"{build.JobName} Server DotCover.dcvr", build.TestRunner.TestsResultsPath);
                    }
                    else
                    {
                        Console.WriteLine("Server Coverage Snapshot File still locked after retrying for 2 minutes.");
                    }
                }
                if (File.Exists(Environment.ExpandEnvironmentVariables(@"%ProgramData%\Warewolf\Server Log\dotCover.log")))
                {
                    TestCleanupUtils.MoveFileToTestResults(Environment.ExpandEnvironmentVariables(@"%ProgramData%\Warewolf\Server Log\dotCover.log"), $"{build.JobName} Server DotCover.log", build.TestRunner.TestsResultsPath);
                }
                if (File.Exists(Environment.ExpandEnvironmentVariables(@"%ProgramData%\Warewolf\Server Log\my.warewolf.io.log")))
                {
                    TestCleanupUtils.MoveFileToTestResults(Environment.ExpandEnvironmentVariables(@"%ProgramData%\Warewolf\Server Log\my.warewolf.io.log"), $"{build.JobName} my.warewolf.io.log", build.TestRunner.TestsResultsPath);
                }
                if (File.Exists(Environment.ExpandEnvironmentVariables(@"%ProgramData%\Warewolf\Server Log\my.warewolf.io.errors.log")))
                {
                    TestCleanupUtils.MoveFileToTestResults(Environment.ExpandEnvironmentVariables(@"%ProgramData%\Warewolf\Server Log\my.warewolf.io.errors.log"), $"{build.JobName} my.warewolf.io Errors.log", build.TestRunner.TestsResultsPath);
                }
            }
            if (Server && Studio && DotCover)
            {
                build.TestCoverageMerger.MergeCoverageSnapshots(new List <string> {
                    Path.Combine(build.TestRunner.TestsResultsPath, $"{build.JobName} Server DotCover.dcvr"), Path.Combine(build.TestRunner.TestsResultsPath, $"{build.JobName} Studio DotCover.dcvr")
                }, Path.Combine(build.TestRunner.TestsResultsPath, $"{build.JobName} Merged Server and Studio DotCover"), Path.Combine(build.TestRunner.TestsResultsPath, "ServerAndStudioDotCoverSnapshot"), build.DotCoverPath);
            }
            if (build.RecordScreen != null)
            {
                MoveScreenRecordingsToTestResults(build.TestRunner.TestsResultsPath);
            }
            foreach (var scriptFile in Directory.GetFiles(Path.GetDirectoryName(build.TestRunner.TestsResultsPath)))
            {
                if (Path.GetFileName(scriptFile).StartsWith("Run ") && Path.GetExtension(scriptFile) == ".bat")
                {
                    TestCleanupUtils.MoveFileToTestResults(scriptFile, Path.GetFileName(scriptFile), build.TestRunner.TestsResultsPath);
                }
            }
        }