0

I have generated some coverage files using VS 2012 Dynamic Code Coverage tool. I want to merge them to produce a consolidated xml output. I was trying to do this using code. Here is the code,

    static CoverageInfo JoinCoverageFiles(IEnumerable<string> files)
    {
        if (files == null)
            throw new ArgumentNullException("files");

        // This will represent the joined coverage files
        CoverageInfo result = null;

        try
        {
            foreach (string file in files)
            {
                // Create from the current file
                CoverageInfo current = CoverageInfo.CreateFromFile(file);
                if (result == null)
                {
                    // First time through, assign to result
                    result = current;
                }
                else
                {                        
                    try
                    {
                        result= CoverageInfo.Join(result, current);
                    }
                }
            }
        }
        catch (Exception)
        {
            if (result != null)
            {
                result.Dispose();
            }
            throw;
        }
        return result;

Then after getting a CoverageInfo object i.e info, I was using these lines to generate the xml file.

        CoverageDS data = info.BuildDataSet(null);
        data.Lines.WriteXml("C:\\Users\Desktop\\coveragefiles\\finalCoverage.xml");

Through these lines I am able to generate finalCoverage.xml, but it is coming blank and it has got, <?xml version="1.0" standalone="yes"?> <CoverageDSPriv />

I am not getting what is the issue, no exception or nothing is being logged in Event Viewer.

Please help me in solving the issue.

Hitesh
  • 3,449
  • 8
  • 39
  • 57
ranarocks
  • 55
  • 9

3 Answers3

0

Try data.WriteXml(...) or data.ExportXml(...)

laaposto
  • 11,835
  • 15
  • 54
  • 71
0

I'd tried with the following code and its working and exporting the coverage data to XML

using (CoverageInfo info = CoverageInfo.CreateFromFile(@"C:\Data.coverage",
    new string[] { "<exe_path1>", "<exe_path2>" },                                                                   
    new string[] { "<sym_path1>", "<sym_path2>" })) //The second two parameters are optional.
{
    CoverageDS dataSet = info.BuildDataSet();
    dataSet.WriteXml(@"C:\Data.coveragexml");
}
C-Pound Guru
  • 15,967
  • 6
  • 46
  • 67
0

So I found the same snipplet you did.......here is my complete solution.....which is basically, 2 different internet st0len samples...merged into the below.

using System;

using Microsoft.VisualStudio.Coverage.Analysis;
using System.Collections.Generic;

/* References
\ThirdPartyReferences\Microsoft Visual Studio 11.0\Microsoft.VisualStudio.Coverage.Analysis.dll
\ThirdPartyReferences\Microsoft Visual Studio 11.0\Microsoft.VisualStudio.Coverage.Interop.dll
*/

namespace MyCompany.VisualStudioExtensions.CodeCoverage.CoverageCoverterConsoleApp
{
    class Program
    {
        static int Main(string[] args)
        {
            if (args.Length < 2)
            {
                Console.WriteLine("Coverage Convert - reads VStest binary code coverage data, and outputs it in XML format.");
                Console.WriteLine("Usage:  ConverageConvert <destinationfile> <sourcefile1> <sourcefile2> ... <sourcefileN>");
                return 1;
            }

            string destinationFile = args[0];
            //destinationFile = @"C:\TestResults\MySuperMergedCoverage.coverage.converted.to.xml";

            List<string> sourceFiles = new List<string>();

            //files.Add(@"C:\MyCoverage1.coverage");
            //files.Add(@"C:\MyCoverage2.coverage");
            //files.Add(@"C:\MyCoverage3.coverage");


            /* get all the file names EXCEPT the first one */
            for (int i = 1; i < args.Length; i++)
            {
                sourceFiles.Add(args[i]);
            }

            CoverageInfo mergedCoverage;
            try
            {
                mergedCoverage = JoinCoverageFiles(sourceFiles);
            }
            catch (Exception e)
            {
                Console.WriteLine("Error opening coverage data: {0}", e.Message);
                return 1;
            }

            CoverageDS data = mergedCoverage.BuildDataSet();

            try
            {
                data.WriteXml(destinationFile);
            }
            catch (Exception e)
            {

                Console.WriteLine("Error writing to output file: {0}", e.Message);
                return 1;
            }

            return 0;
        }

        private static CoverageInfo JoinCoverageFiles(IEnumerable<string> files)
        {
            if (files == null)
                throw new ArgumentNullException("files");

            // This will represent the joined coverage files
            CoverageInfo returnItem = null;
            string path;

            try
            {
                foreach (string sourceFile in files)
                {
                    // Create from the current file

                    path = System.IO.Path.GetDirectoryName(sourceFile);
                    CoverageInfo current = CoverageInfo.CreateFromFile(sourceFile, new string[] { path }, new string[] { path });

                    if (returnItem == null)
                    {
                        // First time through, assign to result
                        returnItem = current;
                        continue;
                    }

                    // Not the first time through, join the result with the current
                    CoverageInfo joined = null;
                    try
                    {
                        joined = CoverageInfo.Join(returnItem, current);
                    }
                    finally
                    {
                        // Dispose current and result
                        current.Dispose();
                        current = null;
                        returnItem.Dispose();
                        returnItem = null;
                    }

                    returnItem = joined;
                }
            }
            catch (Exception)
            {
                if (returnItem != null)
                {
                    returnItem.Dispose();
                }
                throw;
            }

            return returnItem;
        }
    }
}

I also found some xsl in the internet. (the 3 links below are pretty much the same xsl)

http://codetuner.blogspot.com/2011_09_01_archive.html

http://jp.axtstar.com/?page_id=258

http://codetuner.blogspot.com/2011/09/convert-mstest-code-covarage-results-in.html

I'm posting the xsl here "just in case" those URL's die in the future.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" indent="yes"/> 
    <xsl:template match="/" >
        <html>
            <head>

                <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"/>          

                <style type="text/css">
                    th {
                    background-color:#dcdcdc;
                    border:solid 1px #a9a9a9;
                    text-indent:2pt;
                    font-weight:bolder;
                    }
                    #data {
                    text-align: center;
                    }
                </style>

                <script language="JavaScript" type="text/javascript"  >

                    function CreateJavescript(){
                    var fileref=document.createElement('script');
                    fileref.setAttribute("type","text/javascript");
                    fileref.setAttribute("src", "script1.js");
                    document.getElementsByTagName("head")[0].appendChild(fileref);
                    }

                    function toggleDetail(control) {
                    var ctrlId = $(control).attr('Id');
                    $("tr[id='"+ctrlId +"']").toggle();
                    }                 

                </script>

                <title>Code Coverage Report</title>
            </head>
            <body onload='CreateJavescript()' >
                <h1>Code Coverage Report</h1>
                <table border="1">
                    <tr>
                        <th colspan="3"/>
                        <th>Name</th>
                        <th>Blocks Covered</th>
                        <th>Blocks Not Covered</th>
                        <th>Coverage</th>
                    </tr>
                    <xsl:apply-templates select="//CoverageDSPriv/Module" />
                </table>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="Module">
        <xsl:variable name="parentId" select="generate-id(./..)" />
        <xsl:variable name="currentId" select="generate-id(.)" />
        <tr id="{$parentId}">
            <td id="{$currentId}"      colspan="3"               onClick="toggleDetail(this)"        onMouseOver="this.style.cursor= 'pointer' ">[+]</td>
            <td>
                <xsl:value-of select="ModuleName" />
            </td>
            <td id="data">
                <xsl:value-of select="BlocksCovered" />
            </td>
            <td id="data">
                <xsl:value-of select="BlocksNotCovered" />
            </td>
            <xsl:call-template name="CoverageColumn">
                <xsl:with-param name="covered" select="BlocksCovered" />
                <xsl:with-param name="uncovered" select="BlocksNotCovered" />
            </xsl:call-template>
        </tr>
        <xsl:apply-templates select="NamespaceTable" />
        <tr id="{$currentId}-end" style="display: none;">
            <td colspan="5"/>
        </tr>
    </xsl:template>

    <xsl:template match="NamespaceTable">
        <xsl:variable name="parentId" select="generate-id(./..)" />
        <xsl:variable name="currentId" select="generate-id(.)" />
        <tr id="{$parentId}" style="display: none;">
            <td> - </td>
            <td id="{$currentId}"
                colspan="2"
                onClick="toggleDetail(this)"
                onMouseOver="this.style.cursor= 'pointer' ">[+]</td>
            <td>
                <xsl:value-of select="NamespaceName" />
            </td>
            <td id="data">
                <xsl:value-of select="BlocksCovered" />
            </td>
            <td id="data">
                <xsl:value-of select="BlocksNotCovered" />
            </td>
            <xsl:call-template name="CoverageColumn">
                <xsl:with-param name="covered" select="BlocksCovered" />
                <xsl:with-param name="uncovered" select="BlocksNotCovered" />
            </xsl:call-template>
        </tr>
        <xsl:apply-templates select="Class" />
        <tr id="{$currentId}-end" style="display: none;">
            <td colspan="5"/>
        </tr>
    </xsl:template>

    <xsl:template match="Class">
        <xsl:variable name="parentId" select="generate-id(./..)" />
        <xsl:variable name="currentId" select="generate-id(.)" />
        <tr id="{$parentId}" style="display: none;">
            <td> - </td>
            <td> - </td>
            <td id="{$currentId}"
                onClick="toggleDetail(this)"
                onMouseOver="this.style.cursor='pointer' ">[+]</td>
            <td>
                <xsl:value-of select="ClassName" />
            </td>
            <td id="data">
                <xsl:value-of select="BlocksCovered" />
            </td>
            <td id="data">
                <xsl:value-of select="BlocksNotCovered" />
            </td>
            <xsl:call-template name="CoverageColumn">
                <xsl:with-param name="covered" select="BlocksCovered" />
                <xsl:with-param name="uncovered" select="BlocksNotCovered" />
            </xsl:call-template>
        </tr>
        <xsl:apply-templates select="Method" />
        <tr id="{$currentId}-end" style="display: none;">
            <td colspan="5"/>
        </tr>
    </xsl:template>

    <xsl:template match="Method">
        <xsl:variable name="parentId" select="generate-id(./..)" />
        <tr id="{$parentId}" style="display: none;">
            <td> -</td>
            <td> - </td>
            <td> - </td>
            <td>
                <xsl:value-of select="MethodName" />
            </td>
            <td id="data">
                <xsl:value-of select="BlocksCovered" />
            </td>
            <td id="data">
                <xsl:value-of select="BlocksNotCovered" />
            </td>
            <xsl:call-template name="CoverageColumn">
                <xsl:with-param name="covered" select="BlocksCovered" />
                <xsl:with-param name="uncovered" select="BlocksNotCovered" />
            </xsl:call-template>
        </tr>
    </xsl:template>

    <xsl:template name="CoverageColumn">
        <xsl:param name="covered" select="0" />
        <xsl:param name="uncovered" select="0" />
        <td id="data">
            <xsl:variable name="percent"
                select="($covered div ($covered + $uncovered)) * 100" />
                            <xsl:attribute name="style">
                background-color:
                <xsl:choose>
                    <xsl:when test="number($percent >= 90)">#86ed60;</xsl:when>
                    <xsl:when test="number($percent >= 70)">#ffff99;</xsl:when>
                    <xsl:otherwise>#FF7979;</xsl:otherwise>
                </xsl:choose>
            </xsl:attribute>
            <xsl:if test="$percent > 0">
                <xsl:value-of select="format-number($percent, '###.##' )" />%
            </xsl:if>
            <xsl:if test="$percent = 0">
                <xsl:text>0.00%</xsl:text>
            </xsl:if>
        </td>
    </xsl:template>
</xsl:stylesheet>

Here is a small command line tool to help.

https://www.microsoft.com/en-us/download/details.aspx?id=21714

granadaCoder
  • 26,328
  • 10
  • 113
  • 146