예제 #1
0
        private async Task <ExitCode> RunVsTestAsync(
            ILogger logger,
            string vsTestReportDirectoryPath,
            string vsTestExePath,
            bool runTestsInReleaseConfiguration,
            string assemblyFilePrefix)
        {
            Type testClassAttribute  = typeof(TestClassAttribute);
            Type testMethodAttribute = typeof(TestMethodAttribute);

            var directory = new DirectoryInfo(_sourceRoot);

            var typesToFind = new List <Type> {
                testClassAttribute, testMethodAttribute
            };

            List <string> vsTestConsoleArguments =
                new UnitTestFinder(typesToFind).GetUnitTestFixtureDlls(directory, runTestsInReleaseConfiguration, assemblyFilePrefix, FrameworkConstants.NetFramework)
                .ToList();

            if (!vsTestConsoleArguments.Any())
            {
                logger.WriteWarning(
                    $"Could not find any VSTest tests in directory '{directory.FullName}' or any sub-directory");
                return(ExitCode.Success);
            }

            IEnumerable <string> options = GetVsTestConsoleOptions();

            vsTestConsoleArguments.AddRange(options);

            EnsureTestReportDirectoryExists(vsTestReportDirectoryPath);

            string oldCurrentDirectory = SaveCurrentDirectory();

            SetCurrentDirectory(vsTestReportDirectoryPath);

            LogExecution(logger, vsTestConsoleArguments, vsTestExePath);

            try
            {
                Task <ExitCode> execute = ProcessRunner.ExecuteAsync(
                    vsTestExePath,
                    arguments: vsTestConsoleArguments,
                    standardOutLog: logger.Write,
                    standardErrorAction: logger.WriteError,
                    toolAction: logger.Write);

                ExitCode result = await execute;

                return(result);
            }
            finally
            {
                RestoreCurrentDirectory(oldCurrentDirectory);
            }
        }
예제 #2
0
        private async Task <ExitCode> RunNUnitAsync(
            IVariable externalTools,
            ILogger logger,
            IVariable reportPath,
            bool runTestsInReleaseConfiguration,
            string assemblyFilePrefix)
        {
            Type fixtureAttribute    = typeof(TestFixtureAttribute);
            Type testMethodAttribute = typeof(TestAttribute);

            var directory = new DirectoryInfo(_sourceRoot);

            var typesToFind = new List <Type> {
                fixtureAttribute, testMethodAttribute
            };

            Stopwatch stopwatch = Stopwatch.StartNew();

            List <string> testDlls = new UnitTestFinder(typesToFind)
                                     .GetUnitTestFixtureDlls(directory, runTestsInReleaseConfiguration, assemblyFilePrefix, FrameworkConstants.NetFramework)
                                     .ToList();

            stopwatch.Stop();

            logger.Write($"NUnit test assembly lookup took {stopwatch.ElapsedMilliseconds:F2} milliseconds");

            if (!testDlls.Any())
            {
                logger.WriteWarning(
                    $"Could not find any NUnit tests in directory '{directory.FullName}' or any sub-directory");
                return(ExitCode.Success);
            }

            string nunitExePath = GetNunitExePath(externalTools);

            var results = new List <Tuple <string, ExitCode> >();

            foreach (string testDll in testDlls)
            {
                var nunitConsoleArguments = new List <string> {
                    testDll
                };

                string reportFilePath = GetNUnitXmlReportFilePath(reportPath, testDll);

                EnsureNUnitReportDirectoryExists(reportFilePath);

                IEnumerable <string> options = GetNUnitConsoleOptions(externalTools, reportFilePath);

                nunitConsoleArguments.AddRange(options);

                LogExecution(logger, nunitConsoleArguments, nunitExePath);

                Stopwatch executionStopwatch = Stopwatch.StartNew();

                ExitCode result = await ProcessRunner.ExecuteAsync(
                    nunitExePath,
                    arguments : nunitConsoleArguments,
                    standardOutLog : logger.Write,
                    standardErrorAction : logger.WriteError,
                    toolAction : logger.Write);

                executionStopwatch.Stop();

                logger.Write($"NUnit execution took {executionStopwatch.ElapsedMilliseconds:F2} milliseconds");

                results.Add(Tuple.Create(testDll, result));
            }

            if (results.All(result => result.Item2.IsSuccess))
            {
                return(ExitCode.Success);
            }

            var failedTestsBuilder = new StringBuilder();

            failedTestsBuilder.AppendLine("The following DLL files were not tested successfully:");
            foreach (Tuple <string, ExitCode> result in results.Where(r => !r.Item2.IsSuccess))
            {
                failedTestsBuilder.AppendLine(result.Item1);
            }

            logger.WriteError(failedTestsBuilder.ToString());

            return(ExitCode.Failure);
        }
예제 #3
0
        public async Task <ExitCode> ExecuteAsync([NotNull] ILogger logger, [NotNull] IReadOnlyCollection <IVariable> buildVariables, CancellationToken cancellationToken)
        {
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }

            if (buildVariables == null)
            {
                throw new ArgumentNullException(nameof(buildVariables));
            }

            bool enabled = buildVariables.GetBooleanByKey(WellKnownVariables.XUnitNetCoreAppEnabled, false);

            if (!enabled)
            {
                logger.WriteDebug("Xunit .NET Core App test runner is not enabled");
                return(ExitCode.Success);
            }

            _sourceRoot = buildVariables.Require(WellKnownVariables.SourceRoot).ThrowIfEmptyValue().Value;
            IVariable reportPath   = buildVariables.Require(WellKnownVariables.ReportPath).ThrowIfEmptyValue();
            string    xunitDllPath = buildVariables.GetVariableValueOrDefault(WellKnownVariables.XUnitNetCoreAppDllPath, null) ?? Path.Combine(buildVariables.Require(WellKnownVariables.ExternalTools).Value, "xunit", "netcoreapp2.0", "xunit.console.dll");

            logger.WriteDebug($"Using XUnit dll path '{xunitDllPath}'");

            Type theoryType    = typeof(TheoryAttribute);
            Type factAttribute = typeof(FactAttribute);

            var directory = new DirectoryInfo(_sourceRoot);

            var typesToFind = new List <Type> {
                theoryType, factAttribute
            };

            bool runTestsInReleaseConfiguration =
                buildVariables.GetBooleanByKey(
                    WellKnownVariables.RunTestsInReleaseConfigurationEnabled,
                    true);

            string configuration = runTestsInReleaseConfiguration ? "release" : "debug";

            string assemblyFilePrefix = buildVariables.GetVariableValueOrDefault(WellKnownVariables.TestsAssemblyStartsWith, string.Empty);

            logger.Write($"Finding Xunit test DLL files built with {configuration} in directory '{_sourceRoot}'");
            logger.Write($"Looking for types {string.Join(", ", typesToFind.Select(t => t.FullName))} in directory '{_sourceRoot}'");

            List <string> testDlls = new UnitTestFinder(typesToFind, logger: logger, debugLogEnabled: true)
                                     .GetUnitTestFixtureDlls(directory, runTestsInReleaseConfiguration, assemblyFilePrefix: assemblyFilePrefix, targetFrameworkPrefix: FrameworkConstants.NetCoreApp)
                                     .ToList();

            if (!testDlls.Any())
            {
                logger.Write("Found no .NETCoreApp Assemblies with Xunit tests");
                return(ExitCode.Success);
            }

            string dotNetExePath =
                buildVariables.GetVariableValueOrDefault(WellKnownVariables.DotNetExePath, string.Empty);

            if (string.IsNullOrWhiteSpace(dotNetExePath))
            {
                logger.Write(
                    $"Path to 'dotnet.exe' has not been specified, set variable '{WellKnownVariables.DotNetExePath}' or ensure the dotnet.exe is installed in its standard location");
                return(ExitCode.Failure);
            }

            logger.WriteDebug($"Using dotnet.exe in path '{dotNetExePath}'");

            string xmlReportName = $"{Guid.NewGuid()}.xml";

            var arguments = new List <string>();

            string reportFile = Path.Combine(reportPath.Value, "xunit", xmlReportName);

            var reportFileInfo = new FileInfo(reportFile);

            reportFileInfo.Directory.EnsureExists();

            arguments.Add(xunitDllPath);
            arguments.AddRange(testDlls);
            arguments.Add("-nunit");
            arguments.Add(reportFileInfo.FullName);

            ExitCode result = await ProcessRunner.ExecuteAsync(
                dotNetExePath,
                arguments : arguments,
                standardOutLog : logger.Write,
                standardErrorAction : logger.WriteError,
                toolAction : logger.Write,
                cancellationToken : cancellationToken);

            return(result);
        }
예제 #4
0
        public async Task <ExitCode> ExecuteAsync(
            ILogger logger,
            IReadOnlyCollection <IVariable> buildVariables,
            CancellationToken cancellationToken)
        {
            bool enabled = buildVariables.GetBooleanByKey(WellKnownVariables.MSpecEnabled, true);

            if (!enabled)
            {
                logger.WriteWarning($"{MachineSpecificationsConstants.MachineSpecificationsName} not enabled");
                return(ExitCode.Success);
            }

            string externalToolsPath =
                buildVariables.Require(WellKnownVariables.ExternalTools).ThrowIfEmptyValue().Value;

            string sourceRoot =
                buildVariables.Require(WellKnownVariables.SourceRoot).ThrowIfEmptyValue().Value;

            string testReportDirectoryPath =
                buildVariables.Require(WellKnownVariables.ExternalTools_MSpec_ReportPath).ThrowIfEmptyValue().Value;

            string sourceRootOverride =
                buildVariables.GetVariableValueOrDefault(WellKnownVariables.SourceRootOverride, string.Empty);

            string sourceDirectoryPath;

            if (string.IsNullOrWhiteSpace(sourceRootOverride) || !Directory.Exists(sourceRootOverride))
            {
                if (sourceRoot == null)
                {
                    throw new InvalidOperationException("Source root cannot be null");
                }

                sourceDirectoryPath = sourceRoot;
            }
            else
            {
                sourceDirectoryPath = sourceRootOverride;
            }

            var    directory    = new DirectoryInfo(sourceDirectoryPath);
            string mspecExePath = Path.Combine(
                externalToolsPath,
                MachineSpecificationsConstants.MachineSpecificationsName,
                "mspec-clr4.exe");

            bool runTestsInReleaseConfiguration =
                buildVariables.GetBooleanByKey(
                    WellKnownVariables.RunTestsInReleaseConfigurationEnabled,
                    true);

            IEnumerable <Type> typesToFind = new List <Type>
            {
                typeof(It),
                typeof(BehaviorsAttribute),
                typeof(SubjectAttribute),
                typeof(Behaves_like <>)
            };

            logger.WriteVerbose(
                $"Scanning directory '{directory.FullName}' for assemblies containing Machine.Specifications tests");

            string assemblyFilePrefix = buildVariables.GetVariableValueOrDefault(WellKnownVariables.TestsAssemblyStartsWith, string.Empty);

            List <string> testDlls =
                new UnitTestFinder(typesToFind, logger: logger)
                .GetUnitTestFixtureDlls(directory, runTestsInReleaseConfiguration, assemblyFilePrefix, FrameworkConstants.NetFramework)
                .ToList();

            if (!testDlls.Any())
            {
                logger.WriteWarning(
                    $"No DLL files with {MachineSpecificationsConstants.MachineSpecificationsName} specifications was found");
                return(ExitCode.Success);
            }

            var arguments = new List <string>();

            arguments.AddRange(testDlls);

            arguments.Add("--xml");
            string timestamp     = DateTime.UtcNow.ToString("O").Replace(":", ".");
            string fileName      = "MSpec_" + timestamp + ".xml";
            string xmlReportPath = Path.Combine(testReportDirectoryPath, "Xml", fileName);

            new FileInfo(xmlReportPath).Directory.EnsureExists();

            arguments.Add(xmlReportPath);
            string htmlPath = Path.Combine(testReportDirectoryPath, "Html", "MSpec_" + timestamp);

            new DirectoryInfo(htmlPath).EnsureExists();

            IReadOnlyCollection <string> excludedTags = buildVariables
                                                        .GetVariableValueOrDefault(
                WellKnownVariables.IgnoredTestCategories,
                string.Empty)
                                                        .Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
                                                        .Select(item => item.Trim())
                                                        .Where(item => !string.IsNullOrWhiteSpace(item))
                                                        .ToReadOnlyCollection();

            arguments.Add("--html");
            arguments.Add(htmlPath);

            bool hasArborTestDll =
                testDlls.Any(dll => dll.IndexOf("arbor", StringComparison.InvariantCultureIgnoreCase) >= 0);

            if (hasArborTestDll || excludedTags.Any())
            {
                var allExcludedTags = new List <string>();

                arguments.Add("--exclude");

                if (hasArborTestDll)
                {
                    allExcludedTags.Add(MSpecInternalConstants.RecursiveArborXTest);
                }

                if (excludedTags.Any())
                {
                    allExcludedTags.AddRange(excludedTags);
                }

                string excludedTagsParameter = string.Join(",", allExcludedTags);

                logger.Write($"Running MSpec with excluded tags: {excludedTagsParameter}");

                arguments.Add(excludedTagsParameter);
            }

            // ReSharper disable once CollectionNeverUpdated.Local
            var environmentVariables = new Dictionary <string, string>();

            ExitCode exitCode = await
                                ProcessRunner.ExecuteAsync(
                mspecExePath,
                arguments : arguments,
                cancellationToken : cancellationToken,
                standardOutLog : logger.Write,
                standardErrorAction : logger.WriteError,
                toolAction : logger.Write,
                verboseAction : logger.WriteVerbose,
                environmentVariables : environmentVariables,
                debugAction : logger.WriteDebug);

            if (buildVariables.GetBooleanByKey(
                    WellKnownVariables.MSpecJUnitXslTransformationEnabled,
                    false))
            {
                logger.WriteVerbose(
                    $"Transforming {MachineSpecificationsConstants.MachineSpecificationsName} test reports to JUnit format");

                const string junitSuffix = "_junit.xml";

                DirectoryInfo xmlReportDirectory = new FileInfo(xmlReportPath).Directory;

// ReSharper disable once PossibleNullReferenceException
                IReadOnlyCollection <FileInfo> xmlReports = xmlReportDirectory
                                                            .GetFiles("*.xml")
                                                            .Where(report => !report.Name.EndsWith(junitSuffix, StringComparison.Ordinal))
                                                            .ToReadOnlyCollection();

                if (xmlReports.Any())
                {
                    Encoding encoding = Encoding.UTF8;
                    using (Stream stream = new MemoryStream(encoding.GetBytes(MSpecJUnitXsl.Xml)))
                    {
                        using (XmlReader xmlReader = new XmlTextReader(stream))
                        {
                            var myXslTransform = new XslCompiledTransform();
                            myXslTransform.Load(xmlReader);

                            foreach (FileInfo xmlReport in xmlReports)
                            {
                                logger.WriteDebug($"Transforming '{xmlReport.FullName}' to JUnit XML format");
                                try
                                {
                                    TransformReport(xmlReport, junitSuffix, encoding, myXslTransform, logger);
                                }
                                catch (Exception ex)
                                {
                                    logger.WriteError($"Could not transform '{xmlReport.FullName}', {ex}");
                                    return(ExitCode.Failure);
                                }

                                logger.WriteDebug(
                                    $"Successfully transformed '{xmlReport.FullName}' to JUnit XML format");
                            }
                        }
                    }
                }
            }

            return(exitCode);
        }
예제 #5
0
        public async Task <ExitCode> ExecuteAsync([NotNull] ILogger logger, [NotNull] IReadOnlyCollection <IVariable> buildVariables, CancellationToken cancellationToken)
        {
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }

            if (buildVariables == null)
            {
                throw new ArgumentNullException(nameof(buildVariables));
            }

            bool enabled = buildVariables.GetBooleanByKey(WellKnownVariables.XUnitNetFrameworkEnabled, false);

            if (!enabled)
            {
                logger.WriteDebug("Xunit .NET Framework test runner is not enabled");
                return(ExitCode.Success);
            }

            _sourceRoot = buildVariables.Require(WellKnownVariables.SourceRoot).ThrowIfEmptyValue().Value;
            IVariable reportPath   = buildVariables.Require(WellKnownVariables.ReportPath).ThrowIfEmptyValue();
            string    xunitExePath = buildVariables.GetVariableValueOrDefault(WellKnownVariables.XUnitNetFrameworkExePath, Path.Combine(buildVariables.Require(WellKnownVariables.ExternalTools).Value, "xunit", "net452", "xunit.console.exe"));

            Type theoryType    = typeof(TheoryAttribute);
            Type factAttribute = typeof(FactAttribute);

            var directory = new DirectoryInfo(_sourceRoot);

            var typesToFind = new List <Type> {
                theoryType, factAttribute
            };

            bool runTestsInReleaseConfiguration =
                buildVariables.GetBooleanByKey(
                    WellKnownVariables.RunTestsInReleaseConfigurationEnabled,
                    true);

            string assemblyFilePrefix = buildVariables.GetVariableValueOrDefault(WellKnownVariables.TestsAssemblyStartsWith, string.Empty);

            List <string> testDlls = new UnitTestFinder(typesToFind)
                                     .GetUnitTestFixtureDlls(directory, runTestsInReleaseConfiguration, assemblyFilePrefix, FrameworkConstants.NetFramework)
                                     .ToList();

            if (!testDlls.Any())
            {
                logger.Write("Could not find any DLL files with Xunit test and target framework .NETFramework, skipping Xunit Net Framework tests");
                return(ExitCode.Success);
            }

            string xmlReportName = $"{Guid.NewGuid()}.xml";

            var arguments = new List <string>();

            string reportFile = Path.Combine(reportPath.Value, "xunit", xmlReportName);

            var fileInfo = new FileInfo(reportFile);

            fileInfo.Directory.EnsureExists();

            arguments.AddRange(testDlls);
            arguments.Add("-nunit");
            arguments.Add(fileInfo.FullName);

            ExitCode result = await ProcessRunner.ExecuteAsync(
                xunitExePath,
                arguments : arguments,
                standardOutLog : logger.Write,
                standardErrorAction : logger.WriteError,
                toolAction : logger.Write,
                cancellationToken : cancellationToken);

            return(result);
        }