Click here to Skip to main content
Click here to Skip to main content
Go to top

Check NUnit test results from a batch script

, 6 Jul 2009
Rate this:
Please Sign up or sign in to vote.
A small program which allows to check results generated by the nunit-console utility.

Problem overview

If you use NUnit, you can run tests using the nunit-console utility from your build script. But, this test runner just shows the results in a console window and saves a report in an XML file. There is no functionality which allows to check the results of testing after the nunit-console utility execution and perform some actions depending on these results. Of course, there are some powerful build tools which allow to do it, for example, NAnt or FinalBuilder. But, what should you do if you still use simple .bat files to build your product? The most significant problem: how could you stop the build process if some Unit Test failed?

Proposed solution

The CheckTestResults utility helps to solve this issue. It can analyze the TestResult.xml file produced by the nunit-console utility, show all the found failures, sound a beep for each failure, and finally, stop execution and wait for user input if there was at least one failure during the testing.

The utility is written in C#, and requires .NET 2.0 (or higher). Here is the source code:

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);
        }
    }
}

Using the code

To use CheckTestResults, just call it with one parameter: the path to the TestResult.xml file produced by nunit-console. So, your build script will look like:

nunit-console MyProject\Tests\bin\Debug\MyProjectTests.dll
CheckTestsResult.exe TestResult.xml

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Sergiy Korzh
Founder Korzh.com
Ukraine Ukraine
Software developer and entrepreneur.
 
Main projects:
* EasyQuery - ad-hoc data filtering UI for .NET applications;
* Localizer - localization tool kit for Delphi projects;
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralMy vote of 4 PinmvpKanasz Robert28-Sep-12 5:55 
QuestionHave you tried just checking the return code of nunit-console? Pinmembererik.f14-Feb-10 4:42 
GeneralMain should return the status Pinmemberbzchai8-Jul-09 2:55 
GeneralRe: Main should return the status PinmemberSergiy Korzh9-Jul-09 14:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140921.1 | Last Updated 6 Jul 2009
Article Copyright 2009 by Sergiy Korzh
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid