public override async Task ExecuteAsync(IOperationExecutionContext context)
        {
            var fileOps = context.Agent.GetService<IFileOperationsExecuter>();
            var testFilePath = context.ResolvePath(this.TestFile);
            this.LogDebug("Test file: " + testFilePath);

            var exePath = context.ResolvePath(this.ExePath);
            this.LogDebug("Exe path: " + exePath);

            if (!fileOps.FileExists(testFilePath))
            {
                this.LogError($"Test file {testFilePath} does not exist.");
                return;
            }

            if (!fileOps.FileExists(exePath))
            {
                this.LogError($"NUnit runner not found at {exePath}.");
                return;
            }

            string outputPath;
            if (string.IsNullOrEmpty(this.CustomXmlOutputPath))
                outputPath = context.WorkingDirectory;
            else
                outputPath = context.ResolvePath(this.CustomXmlOutputPath);

            this.LogDebug("Output directory: " + outputPath);

            var testResultsXmlFile = fileOps.CombinePath(outputPath, "TestResult.xml");
            this.LogDebug("Output file: " + testResultsXmlFile);

            var args = this.IsNUnit3
                ? $"\"{testFilePath}\" --work:\"{outputPath}\""
                : $"\"{testFilePath}\" /xml:\"{outputPath}\"";

            if (!string.IsNullOrEmpty(this.AdditionalArguments))
            {
                this.LogDebug("Additional arguments: " + this.AdditionalArguments);
                args += " " + this.AdditionalArguments;
            }

            try
            {
                this.LogDebug("Run tests");
                await this.ExecuteCommandLineAsync(
                    context,
                    new RemoteProcessStartInfo
                    {
                        FileName = exePath,
                        Arguments = args,
                        WorkingDirectory = context.WorkingDirectory
                    }
                );


                this.LogDebug($"Read file: {testResultsXmlFile}");
                XDocument xdoc;
                using (var stream = fileOps.OpenFile(testResultsXmlFile, FileMode.Open, FileAccess.Read))
                {
                    xdoc = XDocument.Load(stream);
                    this.LogDebug("File read");
                }

                this.LogDebug($"Parse results");
                string resultsNodeName = this.IsNUnit3 ? "test-run" : "test-results";

                var testResultsElement = xdoc.Element(resultsNodeName);

                var startTime = this.TryParseStartTime(testResultsElement);
                var failures = 0;

                using (var db = new DB.Context())
                {
                    foreach (var testCaseElement in xdoc.Descendants("test-case"))
                    {
                        var testName = (string)testCaseElement.Attribute("name");

                        // skip tests that weren't actually run
                        if (TestCaseWasSkipped(testCaseElement))
                        {
                            this.LogInformation($"NUnit test: {testName} (skipped)");
                            continue;
                        }

                        var result = GetTestCaseResult(testCaseElement);
                        if (result == Domains.TestStatusCodes.Failed)
                            failures++;

                        var testDuration = this.TryParseTestTime((string)testCaseElement.Attribute("time"));

                        this.LogInformation($"NUnit test: {testName}, Result: {Domains.TestStatusCodes.GetName(result)}, Test length: {testDuration}");

                        db.BuildTestResults_RecordTestResult(
                            Execution_Id: context.ExecutionId,
                            Group_Name: AH.NullIf(this.GroupName, string.Empty) ?? "NUnit",
                            Test_Name: testName,
                            TestStatus_Code: result,
                            TestResult_Text: result == Domains.TestStatusCodes.Passed ? result : testCaseElement.ToString(),
                            TestStarted_Date: startTime,
                            TestEnded_Date: startTime + testDuration
                        );

                        startTime += testDuration;
                    }
                }

                if (failures > 0)
                    this.LogError($"{0} test failures were reported.");
            }
            finally
            {
                if (string.IsNullOrEmpty(this.CustomXmlOutputPath))
                {
                    this.LogDebug($"Deleting temp output file ({testResultsXmlFile})...");
                    try
                    {
                        fileOps.DeleteFile(testResultsXmlFile);
                    }
                    catch
                    {
                        this.LogWarning($"Could not delete {testResultsXmlFile}.");
                    }
                }
            }
        }
Exemple #2
0
        public override async Task ExecuteAsync(IOperationExecutionContext context)
        {
            var fileOps      = context.Agent.GetService <IFileOperationsExecuter>();
            var testFilePath = context.ResolvePath(this.TestFile);

            this.LogDebug("Test file: " + testFilePath);

            var exePath = context.ResolvePath(this.ExePath);

            this.LogDebug("Exe path: " + exePath);

            if (!fileOps.FileExists(testFilePath))
            {
                this.LogError($"Test file {testFilePath} does not exist.");
                return;
            }

            if (!fileOps.FileExists(exePath))
            {
                this.LogError($"NUnit runner not found at {exePath}.");
                return;
            }

            string outputFilePath;

            if (string.IsNullOrEmpty(this.CustomXmlOutputPath))
            {
                outputFilePath = fileOps.CombinePath(context.WorkingDirectory, Guid.NewGuid().ToString("N") + ".xml");
            }
            else
            {
                outputFilePath = context.ResolvePath(this.CustomXmlOutputPath);
            }

            this.LogDebug("Output file: " + outputFilePath);

            var args = this.IsNUnit3
                ? $"\"{testFilePath}\" --result:\"{outputFilePath}\";format=nunit2"
                : $"\"{testFilePath}\" /xml:\"{outputFilePath}\"";

            if (!string.IsNullOrEmpty(this.AdditionalArguments))
            {
                this.LogDebug("Additional arguments: " + this.AdditionalArguments);
                args += " " + this.AdditionalArguments;
            }

            try
            {
                await this.ExecuteCommandLineAsync(
                    context,
                    new RemoteProcessStartInfo
                {
                    FileName         = exePath,
                    Arguments        = args,
                    WorkingDirectory = context.WorkingDirectory
                }
                    );

                XDocument xdoc;
                using (var stream = fileOps.OpenFile(outputFilePath, FileMode.Open, FileAccess.Read))
                {
                    xdoc = XDocument.Load(stream);
                }

                var testResultsElement = xdoc.Element("test-results");

                var startTime = this.TryParseStartTime((string)testResultsElement.Attribute("date"), (string)testResultsElement.Attribute("time")) ?? DateTime.UtcNow;
                var failures  = 0;

                using (var db = new DB.Context())
                {
                    foreach (var testCaseElement in xdoc.Descendants("test-case"))
                    {
                        var testName = (string)testCaseElement.Attribute("name");

                        // skip tests that weren't actually run
                        if (string.Equals((string)testCaseElement.Attribute("executed"), "False", StringComparison.OrdinalIgnoreCase))
                        {
                            this.LogInformation($"NUnit test: {testName} (skipped)");
                            continue;
                        }

                        var result = AH.Switch <string, string>((string)testCaseElement.Attribute("success"), StringComparer.OrdinalIgnoreCase)
                                     .Case("True", Domains.TestStatusCodes.Passed)
                                     .Case("Inconclusive", Domains.TestStatusCodes.Inconclusive)
                                     .Default(Domains.TestStatusCodes.Failed)
                                     .End();
                        if (result == Domains.TestStatusCodes.Failed)
                        {
                            failures++;
                        }

                        var testDuration = this.TryParseTestTime((string)testCaseElement.Attribute("time"));

                        this.LogInformation($"NUnit test: {testName}, Result: {Domains.TestStatusCodes.GetName(result)}, Test length: {testDuration}");

                        db.BuildTestResults_RecordTestResult(
                            Execution_Id: context.ExecutionId,
                            Group_Name: AH.NullIf(this.GroupName, string.Empty) ?? "NUnit",
                            Test_Name: testName,
                            TestStatus_Code: result,
                            TestResult_Text: testCaseElement.ToString(),
                            TestStarted_Date: startTime,
                            TestEnded_Date: startTime + testDuration
                            );

                        startTime += testDuration;
                    }
                }

                if (failures > 0)
                {
                    this.LogError($"{failures} test failures were reported.");
                }
            }
            finally
            {
                if (string.IsNullOrEmpty(this.CustomXmlOutputPath))
                {
                    this.LogDebug($"Deleting temp output file ({outputFilePath})...");
                    try
                    {
                        fileOps.DeleteFile(outputFilePath);
                    }
                    catch
                    {
                        this.LogWarning($"Could not delete {outputFilePath}.");
                    }
                }
            }
        }