Ошибки Sonar Runner при обработке файла.coveragexml, созданного из Visual Studio MSTest
Я пытаюсь обработать мой файл.coveragexml (после преобразования файла.coverage), который я получаю после использования MSTest из командной строки, но Sonar Runner продолжает давать сбой, когда пытается проанализировать файл. Ошибки состоят из ошибок синтаксического анализа, таких как неожиданное '?' а также не в состоянии найти тег в файле.
Я попробовал несколько способов получить файл.coveragexml: с помощью команд "vsinstr -coverage ..." и "start vsperfmon -coverage ..." (затем запустив MSTest) из командной строки, изменив файл.testrunconfig и указав, какие библиотеки я хочу получить покрытие, и попытался с помощью "CodeCoverage.exe собирать...". Первые два дали мне успех при получении данных о покрытии кода, но у меня были проблемы с получением "CodeCoverage.exe collect ..." для сбора результатов. Несмотря на то, что я могу получить результаты покрытия кода кода из первых двух, созданный файл.coveragexml, похоже, не в том формате, который принимает SonarQube, даже несмотря на то, что они указывают на своей веб-странице плагина VB.NET, что они поддерживают MSTest и VSTest XML-файлы покрытия кода. Я попытался использовать VSTest и могу получить мои файлы.coveragexml, которые будут приняты Sonarqube без каких-либо ошибок просто отлично. Проблема в том, что компания, для которой я стажируюсь, использует MSTest для запуска всех своих модульных тестов, поэтому мне нужно получить данные.coveragexml от использования MSTest.
Еще я заметил, что когда я пытаюсь экспортировать файл.coverage в виде.coveragexml в Visual Studio (как для MSTest, так и для VSTest), он создает формат.coveragexml, который Sonarqube не принимает (он просто выдает ошибку из-за ошибки я упоминал выше). Когда я использую команду "CodeCoverage.exe analysis..." для преобразования файла.coverage из VSTest, он создает формат.coveragexml, который Sonarqube принимает, так как я не получаю ошибок и вижу результаты покрытия моего кода на панели инструментов. Теперь, когда я пытаюсь использовать команду "CodeCoverage.exe analysis..." для преобразования файла.coverage из MSTest, ничего не происходит. Файл.coveragexml не создается, а также нет ошибок или каких-либо отзывов. Я также попытался написать метод C# для преобразования файла.coverage в файл.coveragexml с помощью Microsoft.VisualStudio.Coverage.Analysis. Но он создает тот же формат файла.coveragexml, как если бы я экспортировал его из Visual Studio.
Другие вещи, которые может быть полезно знать:
- Я выполняю анализ кода VB.NET.
- Я использую версию 2.2 плагина VB.NET от Sonarqube.
- Я использую версию 4.3.2 Sonarqube и версию 2.4 Runar SonarQube.
- Я использую Visual Studio 2013 Premium.
(Ошибка SonarQube) Формат файла.coveragexml после его экспорта из Visual Studio выглядит следующим образом:
<CoverageDSPriv>
<xs:schema ...>
...
</xs:schema>
<Module>
<ModuleName>...</ModuleName>
<ImageSize>...</ImageSize>
...
<NameSpaceTable>
<BlocksCovered>...</BlocksCovered>
...
(SonarQube принимает) Формат файла.coveragexml после использования "CodeCoverage.exe анализ..." (работает только с файлом VSTest.coverage)
<?xml version="1.0" encoding="UTF-8" ?>
<results>
<modules>
<module name="..." path="..." id="..." block_coverage="..." line_coverage="..." blocks_covered="..." ... >
<functions>
<function id="..." token="..." name="..." type_name="..." block_coverage="..." >
...
Похоже, что есть две совершенно разные схемы для этих данных, и SonarQube принимает только одну из них, так ли это? Есть ли другой способ преобразовать данные.coverage в тот, который принимает SonarQube?
2 ответа
Я думаю, что вы отлично описали ситуацию: действительно есть два совершенно разных отчета о покрытии кода, в обоих из которых используется расширение *.coveragexml.
Плагин C# и VB.NET на данный момент поддерживает только один из этих форматов, и существует билет для добавления поддержки другого: https://jira.codehaus.org/browse/SONARNTEST-3
Я создал этот XSLT, чтобы преобразовать файл coverxml в хороший формат.
<xsl:output method="xml" indent="yes"/>
<xsl:template match="CoverageDSPriv">
<results>
<modules>
<xsl:for-each select="Module">
<xsl:element name="module">
<xsl:attribute name="name">
<xsl:value-of select="ModuleName"/>
</xsl:attribute>
<xsl:attribute name="path">
<xsl:value-of select="ModuleName"/>
</xsl:attribute>
<xsl:attribute name="block_coverage">
<xsl:value-of select="BlocksCovered div (BlocksCovered + BlocksNotCovered) * 100"/>
</xsl:attribute>
<xsl:attribute name="line_coverage">
<xsl:value-of select="LinesCovered div (LinesCovered + LinesPartiallyCovered + LinesNotCovered) * 100"/>
</xsl:attribute>
<xsl:attribute name="blocks_covered">
<xsl:value-of select="BlocksCovered"/>
</xsl:attribute>
<xsl:attribute name="blocks_not_covered">
<xsl:value-of select="BlocksNotCovered"/>
</xsl:attribute>
<xsl:attribute name="lines_covered">
<xsl:value-of select="LinesCovered"/>
</xsl:attribute>
<xsl:attribute name="lines_partially_covered">
<xsl:value-of select="LinesPartiallyCovered"/>
</xsl:attribute>
<xsl:attribute name="lines_not_covered">
<xsl:value-of select="LinesNotCovered"/>
</xsl:attribute>
<xsl:for-each select="NamespaceTable">
<xsl:for-each select="Class">
<functions>
<xsl:for-each select="Method">
<xsl:element name="function">
<xsl:attribute name="name">
<xsl:value-of select="substring-before(MethodName, '()')"/>
</xsl:attribute>
<xsl:attribute name="type_name">
<xsl:value-of select="../ClassName"/>
</xsl:attribute>
<xsl:attribute name="block_coverage">
<xsl:value-of select="BlocksCovered div (BlocksCovered + BlocksNotCovered) * 100"/>
</xsl:attribute>
<xsl:attribute name="line_coverage">
<xsl:value-of select="LinesCovered div (LinesCovered + LinesPartiallyCovered + LinesNotCovered) * 100"/>
</xsl:attribute>
<xsl:attribute name="blocks_covered">
<xsl:value-of select="BlocksCovered"/>
</xsl:attribute>
<xsl:attribute name="blocks_not_covered">
<xsl:value-of select="BlocksNotCovered"/>
</xsl:attribute>
<xsl:attribute name="lines_covered">
<xsl:value-of select="LinesCovered"/>
</xsl:attribute>
<xsl:attribute name="lines_partially_covered">
<xsl:value-of select="LinesPartiallyCovered"/>
</xsl:attribute>
<xsl:attribute name="lines_not_covered">
<xsl:value-of select="LinesNotCovered"/>
</xsl:attribute>
<ranges>
<xsl:for-each select="Lines">
<xsl:element name="range">
<xsl:attribute name="source_id">
<xsl:value-of select="SourceFileID"/>
</xsl:attribute>
<xsl:attribute name="covered">
<xsl:choose>
<xsl:when test="Coverage=0">yes</xsl:when>
<xsl:when test="Coverage=1">partial</xsl:when>
<xsl:when test="Coverage=2">no</xsl:when>
</xsl:choose>
</xsl:attribute>
<xsl:attribute name="start_line">
<xsl:value-of select="LnStart"/>
</xsl:attribute>
<xsl:attribute name="start_column">
<xsl:value-of select="ColStart"/>
</xsl:attribute>
<xsl:attribute name="end_line">
<xsl:value-of select="LnEnd"/>
</xsl:attribute>
<xsl:attribute name="end_column">
<xsl:value-of select="ColEnd"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</ranges>
</xsl:element>
</xsl:for-each>
</functions>
<source_files>
<xsl:for-each select="../../../SourceFileNames">
<xsl:element name="source_file">
<xsl:attribute name="id">
<xsl:value-of select="SourceFileID"/>
</xsl:attribute>
<xsl:attribute name="path">
<xsl:value-of select="SourceFileName"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</source_files>
</xsl:for-each>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</modules>
</results>
</xsl:template>