65.9K
CodeProject 正在变化。 阅读更多。
Home

从批处理脚本检查 NUnit 测试结果

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.14/5 (4投票s)

2009年7月4日

CPOL

1分钟阅读

viewsIcon

39382

downloadIcon

382

一个小程序,可以用来检查由 nunit-console 工具生成的测试结果。

问题概述

如果您使用 NUnit,可以使用 nunit-console 工具从构建脚本中运行测试。但是,这个测试运行器只是在控制台窗口中显示结果,并将报告保存到 XML 文件中。没有功能可以在 nunit-console 工具执行后检查测试结果,并根据这些结果执行某些操作。当然,有一些强大的构建工具可以做到这一点,例如 NAnt 或 FinalBuilder。但是,如果您仍然使用简单的 .bat 文件来构建您的产品,该怎么办?最重要的问题:如果某个单元测试失败,如何停止构建过程?

提出的解决方案

CheckTestResults 工具可以帮助解决这个问题。它可以分析 nunit-console 工具生成的 TestResult.xml 文件,显示所有找到的失败,为每个失败发出蜂鸣声,并且,如果在测试期间至少发生了一次失败,则最终停止执行并等待用户输入。

该工具是用 C# 编写的,需要 .NET 2.0(或更高版本)。这是源代码

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;

namespace CheckTestResults {
    class CheckTestResultsMain {

        class ErrorItem {
            public string Name;
            public string Message;
            public string StackTrace;
        }

        private static bool pauseOnError = true;
        private static string resultFileName = "";
        private static List<ErrorItem> errors;

        static void Main(string[] args) {

            Console.WriteLine("Check NUnit test results" + 
                    " utility version 1.0.0");
            Console.WriteLine("");

            errors = new List<ErrorItem>();


            if (args.Length > 0) {
                // Load program arguments
                for (int i = 0; i < args.Length; i++) {
                    if (args[i].StartsWith("-pause:")) {

                        string s = args[i].Substring("-pause:".Length);
                        pauseOnError = bool.Parse(s);
                    }
                    else
                        resultFileName = args[i];
                }
            }
            else {
                Console.WriteLine("Usage: CheckTestResults.exe" + 
                        " <path to TestResult.xml file>");
                return;
            }


            Console.WriteLine("Processing " + 
                    resultFileName + "...");
            Console.WriteLine("");
            try {
                //Analize test results file
                FileStream fstream = new FileStream(resultFileName, 
                           FileMode.Open, FileAccess.Read);
                try {
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load(fstream);
                    LoadTestResults(xmlDoc.DocumentElement);
                }
                finally {
                    fstream.Close();
                }
            }
            catch (Exception ex) {
                Console.ForegroundColor = ConsoleColor.Red;

                Console.WriteLine("Error occur: ");
                Console.ForegroundColor = ConsoleColor.Magenta;
                Console.WriteLine(ex.Message);
                Console.Beep();
                Console.ForegroundColor = ConsoleColor.Gray;
                Console.WriteLine("");
                Console.WriteLine("Press any key to continue...");
                Console.ReadKey(true);
                return;
            }


            if (errors.Count > 0) {
                Console.ForegroundColor = ConsoleColor.Red;

                //Print errors
                Console.WriteLine("Tests failed");
                Console.WriteLine("");

                for (int I = 0; I < errors.Count; I++) {
                    Console.ForegroundColor = ConsoleColor.Magenta;
                    Console.WriteLine("  " + (I + 1).ToString() + 
                            ": " + errors[I].Name);
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.Write(errors[I].Message);
                    Console.ForegroundColor = ConsoleColor.DarkYellow;
                    Console.Write(errors[I].StackTrace);

                    Console.Beep();
                    Console.WriteLine("");
                    Console.WriteLine("");
                }

                //Stop and wait for user input
                Console.ForegroundColor = ConsoleColor.Gray;
                Console.WriteLine("");
                Console.WriteLine("Press any key to continue...");
                Console.ReadKey(true);
            }
            else {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("Testing succeeded!");
                Console.ForegroundColor = ConsoleColor.Gray;
                Console.WriteLine("");
            }
        }

        private static void LoadTestResults(XmlElement rootNode) {
            foreach (XmlNode node in rootNode.ChildNodes) {
                if (node is XmlElement && 
                         node.LocalName == "test-suite")
                    LoadTestSuite((XmlElement)node);
            }
        }

        private static void LoadTestSuite(XmlElement suiteNode) {
            foreach (XmlNode node in suiteNode.ChildNodes) {
                if (node is XmlElement && 
                       node.LocalName == "results") {
                    foreach (XmlNode subNode in node.ChildNodes) {
                        if (subNode is XmlElement ) {
                            if (subNode.LocalName == "test-suite") {
                                LoadTestSuite((XmlElement)subNode);
                            }
                            else if (subNode.LocalName == "test-case") {
                                LoadTestCase((XmlElement)subNode);
                            }
                        }
                    }
                }
            }
        }

        private static void LoadTestCase(XmlElement caseNode) {
            foreach (XmlNode node in caseNode.ChildNodes) {
                if (node is XmlElement && 
                        node.LocalName == "failure") {
                    LoadTestFailure((XmlElement)node);
                }
            }
        }

        private static void LoadTestFailure(XmlElement failureNode) {
            ErrorItem error = new ErrorItem();

            error.Name = 
              failureNode.ParentNode.Attributes["name"].Value;

            foreach (XmlNode node in failureNode.ChildNodes) {
                if (node.LocalName == "message") {
                    error.Message = node.FirstChild.Value;
                }
                else if (node.LocalName == "stack-trace") {
                    error.StackTrace = node.FirstChild.Value;
                }
            }

            errors.Add(error);
        }
    }
}

使用代码

要使用 CheckTestResults,只需使用一个参数调用它:由 nunit-console 生成的 TestResult.xml 文件的路径。因此,您的构建脚本将如下所示:

nunit-console MyProject\Tests\bin\Debug\MyProjectTests.dll
CheckTestsResult.exe TestResult.xml
© . All rights reserved.