I've been working on adding an ncover report to my
build system.  My QA manager likes the idea of seeing
the summary report of the modules, but does not need
all the detail produced by ncover.  

My solution has approximately 50 projects.  When I
submit all the dlls for nunit testing in one step,
i.e. ncover-console /c nunit.console "A.dll B.dll ..."
I get a good report, but...
(1) The output coverage file is roughly 6 MB of xml
(all on a single line)
(2) The coverage file takes a long time to load
(3) Manager only cares about the first of 150 some
pages.

On the other hand, I can run ncover 50 some times and
get summaries of the individual assemblies, but then I
don't get an overall summary for the whole solution.

I ended up writing a custom task that someone might
file useful, called ncoversummary.  It takes multiple
ncover reports, extracts out the coverage statistics,
and writes the stats to another xml file.  I'm an XML
dummy, so I am not providing an transform to make the
stats look pretty, but I (somehow) managed to write
the XPATH statements to get the stats.

You can use this as starting point for something
better, or make use of it as is.  I hope this survives
the trip through Yahoo without getting too distorted.

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Text;

using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Tasks;
using NAnt.Core.Util;
using NAnt.Core.Types;

namespace NCoverSummary
{
        /// <summary>
        /// Produces a summary of one or more Ncover output
files
        /// </summary>
        [TaskName("ncoversummary")]
        public class NCoverSummaryTask : Task
        {
                #region Private Instance Fields

                private FileSet _fileset = new FileSet();
                private FileInfo _tofile;

                #endregion Private Instance Fields
                #region Public Instance Properties

                /// <summary>
                /// All the files in the file set will be
summarized.
                /// </summary>
                [BuildElement("fileset")]
                public FileSet SummaryFileSet 
                {
                        get { return _fileset; }
                        set { _fileset = value; }
                }
                /// <summary>
                /// The name of the output file to write summary to
                /// </summary>
        [TaskAttribute("tofile")]
                public FileInfo ToFile
                {
                        get {return _tofile;}
                        set {_tofile = value;}
                }
                #endregion Public Instance Properties

                #region Override implementation of Task
                /// <summary>
                /// Checks whether all items are set 
                /// </summary>
                /// <param name="taskNode">The <see cref="XmlNode"
/> used to initialize the task.</param>
                protected override void InitializeTask(XmlNode
taskNode) 
                {
                        if (ToFile == null || SummaryFileSet == null)
                        {
                                throw new
BuildException(string.Format(CultureInfo.InvariantCulture,"Both
 'tofile' and 'fileset' must be specified"));
                        }
                }
                /// <summary>
                /// Overrides the task execute
                /// </summary>
                protected override void ExecuteTask() 
                {
                        if (SummaryFileSet.FileNames.Count > 0)
                        {
                                Log(Level.Info,"Summarizing {0} NCover
Files",SummaryFileSet.FileNames.Count);
                        }
                        // open the output file 
                        XmlTextWriter textWriter = new
XmlTextWriter(ToFile.FullName,null);
                        textWriter.Formatting = Formatting.Indented;
                        textWriter.WriteStartDocument();

                        try
                        {
                                // extract the information from the file
                                foreach (string path in 
SummaryFileSet.FileNames) 
                                {
                                        SummarizeNCoverFile(path, textWriter);
                                }
                        }
                        finally
                        {
                                textWriter.WriteEndDocument();
                                textWriter.Flush();
                                textWriter.Close();
                        }
                }
                #endregion
                #region private
                /// <summary>
                /// Extracts code coverage stats from a single
ncover xml file
                /// </summary>
                /// <param name="path">path to ncover file</param>
                /// <param name="writer">xml output file
object</param>
                private void SummarizeNCoverFile(String path,
XmlTextWriter writer)
                {
                        if (Verbose)
                        {
                                Log(Level.Verbose,"Checking ncover input file
{0}",path);
                        }
                        // load the xml document
                        XmlDocument document = new XmlDocument();
                        document.Load(path);

                        // find number of modules described in this file
                        XmlNodeList  modules =
document.SelectNodes("/coverage/module");
                        Log(Level.Verbose,"File {0} has {1} assembly
modules", path, modules.Count);
                        // loop over the number of modules
                        foreach (XmlNode module in modules)
                        {
                                string moduleName =
module.Attributes.GetNamedItem("name").Value;
                                string assemblyName =
module.Attributes.GetNamedItem("assembly").Value;

                                XmlNodeList nodesTotal =
module.SelectNodes("method/seqpnt");
                                XmlNodeList nodesWithZeroHits =
module.SelectNodes("method/[EMAIL PROTECTED]'0']");

                                double coverage =
ComputeCoverage(nodesTotal.Count,nodesWithZeroHits.Count);
                        
                                writer.WriteStartElement("module");
                                writer.WriteAttributeString("name",moduleName);
                        
writer.WriteAttributeString("assembly",assemblyName);
                        
writer.WriteAttributeString("totalines",nodesTotal.Count.ToString());
                        
writer.WriteAttributeString("coverage",coverage.ToString());
                                writer.WriteEndElement();
                        }
                }
                /// <summary>
                /// Computes the amount of code coverage from the
nodes
                /// </summary>
                /// <param name="totalNodes">total number of
executed lines in code</param>
                /// <param name="nodesNotCovered">number of lines
not executed during testing</param>
                private double ComputeCoverage (int totalNodes, int
nodesNotCovered)
                {
                        if (totalNodes > 0)
                                return
((double)(totalNodes-nodesNotCovered)/totalNodes);
                        else
                                return  0.0;
                }
                #endregion
        }
}



                
____________________________________________________
Start your day with Yahoo! - make it your home page 
http://www.yahoo.com/r/hs 
 


-------------------------------------------------------
SF.Net email is sponsored by: Discover Easy Linux Migration Strategies
from IBM. Find simple to follow Roadmaps, straightforward articles,
informative Webcasts and more! Get everything you need to get up to
speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click
_______________________________________________
NAntContrib-Developer mailing list
NAntContrib-Developer@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nantcontrib-developer

Reply via email to