Merge topic 'expand_cobertura_coverage'
50daf239
CTest: Generalize Cobertura coverage format handlinga2822d30
CTest: Rename coverage implementation for "Python" to "Cobertura"
This commit is contained in:
commit
994f4b71fc
|
@ -3,3 +3,58 @@ CTEST_COVERAGE_COMMAND
|
|||
|
||||
Specify the CTest ``CoverageCommand`` setting
|
||||
in a :manual:`ctest(1)` dashboard client script.
|
||||
|
||||
Cobertura
|
||||
'''''''''
|
||||
|
||||
Using `Cobertura`_ as the coverage generation within your multi-module
|
||||
Java project can generate a series of XML files.
|
||||
|
||||
The Cobertura Coverage parser expects to read the coverage data from a
|
||||
single XML file which contains the coverage data for all modules.
|
||||
Cobertura has a program with the ability to merge given cobertura.ser files
|
||||
and then another program to generate a combined XML file from the previous
|
||||
merged file. For command line testing, this can be done by hand prior to
|
||||
CTest looking for the coverage files. For script builds,
|
||||
set the ``CTEST_COVERAGE_COMMAND`` variable to point to a file which will
|
||||
perform these same steps, such as a .sh or .bat file.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
set(CTEST_COVERAGE_COMMAND .../run-coverage-and-consolidate.sh)
|
||||
|
||||
where the ``run-coverage-and-consolidate.sh`` script is perhaps created by
|
||||
the :command:`configure_file` command and might contain the following code:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
#!/usr/bin/env bash
|
||||
CoberturaFiles="$(find "/path/to/source" -name "cobertura.ser")"
|
||||
SourceDirs="$(find "/path/to/source" -name "java" -type d)"
|
||||
cobertura-merge --datafile coberturamerge.ser $CoberturaFiles
|
||||
cobertura-report --datafile coberturamerge.ser --destination . \
|
||||
--format xml $SourceDirs
|
||||
|
||||
The script uses ``find`` to capture the paths to all of the cobertura.ser files
|
||||
found below the project's source directory. It keeps the list of files and
|
||||
supplies it as an argument to the ``cobertura-merge`` program. The ``--datafile``
|
||||
argument signifies where the result of the merge will be kept.
|
||||
|
||||
The combined ``coberturamerge.ser`` file is then used to generate the XML report
|
||||
using the ``cobertura-report`` program. The call to the cobertura-report program
|
||||
requires some named arguments.
|
||||
|
||||
``--datafila``
|
||||
path to the merged .ser file
|
||||
|
||||
``--destination``
|
||||
path to put the output files(s)
|
||||
|
||||
``--format``
|
||||
file format to write output in: xml or html
|
||||
|
||||
The rest of the supplied arguments consist of the full paths to the
|
||||
/src/main/java directories of each module within the souce tree. These
|
||||
directories are needed and should not be forgotten.
|
||||
|
||||
.. _`Cobertura`: http://cobertura.github.io/cobertura/
|
||||
|
|
|
@ -519,7 +519,7 @@ set(CTEST_SRCS cmCTest.cxx
|
|||
CTest/cmParseCacheCoverage.cxx
|
||||
CTest/cmParseGTMCoverage.cxx
|
||||
CTest/cmParsePHPCoverage.cxx
|
||||
CTest/cmParsePythonCoverage.cxx
|
||||
CTest/cmParseCoberturaCoverage.cxx
|
||||
CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
|
||||
CTest/cmCTestGenericHandler.cxx
|
||||
CTest/cmCTestHandlerCommand.cxx
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
============================================================================*/
|
||||
#include "cmCTestCoverageHandler.h"
|
||||
#include "cmParsePHPCoverage.h"
|
||||
#include "cmParsePythonCoverage.h"
|
||||
#include "cmParseCoberturaCoverage.h"
|
||||
#include "cmParseGTMCoverage.h"
|
||||
#include "cmParseCacheCoverage.h"
|
||||
#include "cmCTest.h"
|
||||
|
@ -401,7 +401,7 @@ int cmCTestCoverageHandler::ProcessHandler()
|
|||
{
|
||||
return error;
|
||||
}
|
||||
file_count += this->HandlePythonCoverage(&cont);
|
||||
file_count += this->HandleCoberturaCoverage(&cont);
|
||||
error = cont.Error;
|
||||
if ( file_count < 0 )
|
||||
{
|
||||
|
@ -779,10 +779,10 @@ int cmCTestCoverageHandler::HandlePHPCoverage(
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int cmCTestCoverageHandler::HandlePythonCoverage(
|
||||
int cmCTestCoverageHandler::HandleCoberturaCoverage(
|
||||
cmCTestCoverageHandlerContainer* cont)
|
||||
{
|
||||
cmParsePythonCoverage cov(*cont, this->CTest);
|
||||
cmParseCoberturaCoverage cov(*cont, this->CTest);
|
||||
|
||||
// Assume the coverage.xml is in the source directory
|
||||
std::string coverageXMLFile = this->CTest->GetBinaryDir() + "/coverage.xml";
|
||||
|
@ -790,14 +790,14 @@ int cmCTestCoverageHandler::HandlePythonCoverage(
|
|||
if(cmSystemTools::FileExists(coverageXMLFile.c_str()))
|
||||
{
|
||||
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
|
||||
"Parsing coverage.py XML file: " << coverageXMLFile
|
||||
"Parsing Cobertura XML file: " << coverageXMLFile
|
||||
<< std::endl);
|
||||
cov.ReadCoverageXML(coverageXMLFile.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
|
||||
"Cannot find coverage.py XML file: " << coverageXMLFile
|
||||
"Cannot find Cobertura XML file: " << coverageXMLFile
|
||||
<< std::endl);
|
||||
}
|
||||
return static_cast<int>(cont->TotalCoverage.size());
|
||||
|
|
|
@ -76,7 +76,7 @@ private:
|
|||
int HandlePHPCoverage(cmCTestCoverageHandlerContainer* cont);
|
||||
|
||||
//! Handle coverage for Python with coverage.py
|
||||
int HandlePythonCoverage(cmCTestCoverageHandlerContainer* cont);
|
||||
int HandleCoberturaCoverage(cmCTestCoverageHandlerContainer* cont);
|
||||
|
||||
//! Handle coverage for mumps
|
||||
int HandleMumpsCoverage(cmCTestCoverageHandlerContainer* cont);
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
#include "cmStandardIncludes.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmXMLParser.h"
|
||||
#include "cmParsePythonCoverage.h"
|
||||
#include "cmParseCoberturaCoverage.h"
|
||||
#include <cmsys/Directory.hxx>
|
||||
#include <cmsys/FStream.hxx>
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class cmParsePythonCoverage::XMLParser: public cmXMLParser
|
||||
class cmParseCoberturaCoverage::XMLParser: public cmXMLParser
|
||||
{
|
||||
public:
|
||||
XMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont)
|
||||
: CTest(ctest), Coverage(cont)
|
||||
{
|
||||
this->InSources = false;
|
||||
this->InSource = false;
|
||||
this->FilePaths.push_back(this->Coverage.SourceDir);
|
||||
this->CurFileName = "";
|
||||
}
|
||||
|
||||
virtual ~XMLParser()
|
||||
|
@ -20,9 +24,44 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
|
||||
virtual void EndElement(const std::string& name)
|
||||
{
|
||||
if(name == "source")
|
||||
{
|
||||
this->InSource=false;
|
||||
}
|
||||
else if (name == "sources")
|
||||
{
|
||||
this->InSources=false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void CharacterDataHandler(const char* data, int length)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.insert(0,data,length);
|
||||
if (this->InSources && this->InSource)
|
||||
{
|
||||
this->FilePaths.push_back(tmp);
|
||||
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Adding Source: "
|
||||
<< tmp << std::endl);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void StartElement(const std::string& name, const char** atts)
|
||||
{
|
||||
if(name == "class")
|
||||
std::string FoundSource;
|
||||
std::string finalpath = "";
|
||||
if(name == "source")
|
||||
{
|
||||
this->InSource = true;
|
||||
}
|
||||
else if(name == "sources")
|
||||
{
|
||||
this->InSources = true;
|
||||
}
|
||||
else if(name == "class")
|
||||
{
|
||||
int tagCount = 0;
|
||||
while(true)
|
||||
|
@ -30,11 +69,19 @@ protected:
|
|||
if(strcmp(atts[tagCount], "filename") == 0)
|
||||
{
|
||||
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Reading file: "
|
||||
<< atts[tagCount+1] << std::endl);
|
||||
this->CurFileName = this->Coverage.SourceDir + "/" +
|
||||
atts[tagCount+1];
|
||||
<< atts[tagCount+1]<< std::endl);
|
||||
std::string filename = atts[tagCount+1];
|
||||
for(size_t i=0;i < FilePaths.size();i++)
|
||||
{
|
||||
finalpath = FilePaths[i] + "/" + filename;
|
||||
if(cmSystemTools::FileExists(finalpath.c_str()))
|
||||
{
|
||||
this->CurFileName = finalpath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cmsys::ifstream fin(this->CurFileName.c_str());
|
||||
if(!fin)
|
||||
if(this->CurFileName == "" || !fin )
|
||||
{
|
||||
this->CurFileName = this->Coverage.BinaryDir + "/" +
|
||||
atts[tagCount+1];
|
||||
|
@ -48,7 +95,6 @@ protected:
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string line;
|
||||
FileLinesType& curFileLines =
|
||||
this->Coverage.TotalCoverage[this->CurFileName];
|
||||
|
@ -83,7 +129,9 @@ protected:
|
|||
{
|
||||
FileLinesType& curFileLines =
|
||||
this->Coverage.TotalCoverage[this->CurFileName];
|
||||
curFileLines[curNumber-1] = curHits;
|
||||
{
|
||||
curFileLines[curNumber-1] = curHits;
|
||||
}
|
||||
break;
|
||||
}
|
||||
++tagCount;
|
||||
|
@ -91,10 +139,11 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void EndElement(const std::string&) {}
|
||||
|
||||
private:
|
||||
|
||||
bool InSources;
|
||||
bool InSource;
|
||||
std::vector<std::string> FilePaths;
|
||||
typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector
|
||||
FileLinesType;
|
||||
cmCTest* CTest;
|
||||
|
@ -104,16 +153,16 @@ private:
|
|||
};
|
||||
|
||||
|
||||
cmParsePythonCoverage::cmParsePythonCoverage(
|
||||
cmParseCoberturaCoverage::cmParseCoberturaCoverage(
|
||||
cmCTestCoverageHandlerContainer& cont,
|
||||
cmCTest* ctest)
|
||||
:Coverage(cont), CTest(ctest)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmParsePythonCoverage::ReadCoverageXML(const char* xmlFile)
|
||||
bool cmParseCoberturaCoverage::ReadCoverageXML(const char* xmlFile)
|
||||
{
|
||||
cmParsePythonCoverage::XMLParser parser(this->CTest, this->Coverage);
|
||||
cmParseCoberturaCoverage::XMLParser parser(this->CTest, this->Coverage);
|
||||
parser.ParseFile(xmlFile);
|
||||
return true;
|
||||
}
|
|
@ -10,8 +10,8 @@
|
|||
See the License for more information.
|
||||
============================================================================*/
|
||||
|
||||
#ifndef cmParsePythonCoverage_h
|
||||
#define cmParsePythonCoverage_h
|
||||
#ifndef cmParseCoberturaCoverage_h
|
||||
#define cmParseCoberturaCoverage_h
|
||||
|
||||
#include "cmStandardIncludes.h"
|
||||
#include "cmCTestCoverageHandler.h"
|
||||
|
@ -25,15 +25,18 @@
|
|||
* Java-based Cobertura coverage application. This helper class parses
|
||||
* that XML file to fill the coverage-handler container.
|
||||
*/
|
||||
class cmParsePythonCoverage
|
||||
class cmParseCoberturaCoverage
|
||||
{
|
||||
public:
|
||||
|
||||
//! Create the coverage parser by passing in the coverage handler
|
||||
//! container and the cmCTest object
|
||||
cmParsePythonCoverage(cmCTestCoverageHandlerContainer& cont,
|
||||
cmParseCoberturaCoverage(cmCTestCoverageHandlerContainer& cont,
|
||||
cmCTest* ctest);
|
||||
|
||||
bool inSources;
|
||||
bool inSource;
|
||||
std::vector<std::string> filepaths;
|
||||
//! Read the XML produced by running `coverage xml`
|
||||
bool ReadCoverageXML(const char* xmlFile);
|
||||
|
|
@ -2184,6 +2184,24 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
|
|||
"Process file.*foo.py.*Total LOC:.*13.*Percentage Coverage: 84.62.*"
|
||||
ENVIRONMENT COVFILE=)
|
||||
|
||||
# Adding a test case for non-python Cobertura Coverage
|
||||
configure_file(
|
||||
"${CMake_SOURCE_DIR}/Tests/CoberturaCoverage/DartConfiguration.tcl.in"
|
||||
"${CMake_BINARY_DIR}/Testing/CoberturaCoverage/DartConfiguration.tcl")
|
||||
configure_file(
|
||||
"${CMake_SOURCE_DIR}/Tests/CoberturaCoverage/coverage.xml.in"
|
||||
"${CMake_BINARY_DIR}/Testing/CoberturaCoverage/coverage.xml")
|
||||
file(COPY "${CMake_SOURCE_DIR}/Tests/CoberturaCoverage/src"
|
||||
DESTINATION "${CMake_BINARY_DIR}/Testing/CoberturaCoverage")
|
||||
add_test(NAME CTestCoberturaCoverage
|
||||
COMMAND cmake -E chdir
|
||||
${CMake_BINARY_DIR}/Testing/CoberturaCoverage
|
||||
$<TARGET_FILE:ctest> -T Coverage --debug)
|
||||
set_tests_properties(CTestCoberturaCoverage PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION
|
||||
"Process file.*CoverageTest.java.*Total LOC:.*18.*Percentage Coverage: 72.22.*"
|
||||
ENVIRONMENT COVFILE=)
|
||||
|
||||
function(add_config_tests cfg)
|
||||
set(base "${CMake_BINARY_DIR}/Tests/CTestConfig")
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# This file is configured by CMake automatically as DartConfiguration.tcl
|
||||
# If you choose not to use CMake, this file may be hand configured, by
|
||||
# filling in the required variables.
|
||||
|
||||
|
||||
# Configuration directories and files
|
||||
SourceDirectory: ${CMake_SOURCE_DIR}/Testing/CoberturaCoverage
|
||||
BuildDirectory: ${CMake_BINARY_DIR}/Testing/CoberturaCoverage
|
|
@ -0,0 +1,112 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE coverage SYSTEM "http://cobertura.sourceforge.net/xml/coverage-04.dtd">
|
||||
|
||||
<coverage line-rate="0.7222222222222222" branch-rate="0.875" lines-covered="13" lines-valid="18" branches-covered="7" branches-valid="8" complexity="0.0" version="1.9.4.1" timestamp="1401890139281">
|
||||
<sources>
|
||||
<source>${CMake_BINARY_DIR}/Testing/CoberturaCoverage/src/main/java/</source>
|
||||
</sources>
|
||||
<packages>
|
||||
<package name="org.cmake.Coverage" line-rate="0.7222222222222222" branch-rate="0.875" complexity="0.0">
|
||||
<classes>
|
||||
<class name="org.cmake.Coverage.CoverageTest" filename="org/cmake/CoverageTest.java" line-rate="0.7222222222222222" branch-rate="0.875" complexity="0.0">
|
||||
<methods>
|
||||
<method name="<clinit>" signature="()V" line-rate="1.0" branch-rate="1.0">
|
||||
<lines>
|
||||
<line number="10" hits="2" branch="false"/>
|
||||
<line number="11" hits="2" branch="false"/>
|
||||
</lines>
|
||||
</method>
|
||||
<method name="<init>" signature="()V" line-rate="0.0" branch-rate="1.0">
|
||||
<lines>
|
||||
<line number="8" hits="0" branch="false"/>
|
||||
<line number="12" hits="0" branch="false"/>
|
||||
</lines>
|
||||
</method>
|
||||
<method name="equalsVarOne" signature="(Ljava/lang/String;)Ljava/lang/Boolean;" line-rate="0.6666666666666666" branch-rate="0.5">
|
||||
<lines>
|
||||
<line number="16" hits="2" branch="true" condition-coverage="50% (1/2)">
|
||||
<conditions>
|
||||
<condition number="0" type="jump" coverage="50%"/>
|
||||
</conditions>
|
||||
</line>
|
||||
<line number="17" hits="2" branch="false"/>
|
||||
<line number="20" hits="0" branch="false"/>
|
||||
</lines>
|
||||
</method>
|
||||
<method name="equalsVarTwo" signature="(Ljava/lang/String;)Z" line-rate="1.0" branch-rate="1.0">
|
||||
<lines>
|
||||
<line number="26" hits="4" branch="true" condition-coverage="100% (2/2)">
|
||||
<conditions>
|
||||
<condition number="0" type="jump" coverage="100%"/>
|
||||
</conditions>
|
||||
</line>
|
||||
<line number="27" hits="2" branch="false"/>
|
||||
<line number="30" hits="2" branch="false"/>
|
||||
</lines>
|
||||
</method>
|
||||
<method name="timesIntOne" signature="(Ljava/lang/Integer;)Ljava/lang/Integer;" line-rate="0.0" branch-rate="1.0">
|
||||
<lines>
|
||||
<line number="35" hits="0" branch="false"/>
|
||||
<line number="36" hits="0" branch="false"/>
|
||||
</lines>
|
||||
</method>
|
||||
<method name="whileLoop" signature="(Ljava/lang/Integer;)Z" line-rate="1.0" branch-rate="1.0">
|
||||
<lines>
|
||||
<line number="41" hits="2" branch="false"/>
|
||||
<line number="42" hits="10" branch="true" condition-coverage="100% (2/2)">
|
||||
<conditions>
|
||||
<condition number="0" type="jump" coverage="100%"/>
|
||||
</conditions>
|
||||
</line>
|
||||
<line number="43" hits="8" branch="false"/>
|
||||
<line number="45" hits="2" branch="true" condition-coverage="100% (2/2)">
|
||||
<conditions>
|
||||
<condition number="0" type="jump" coverage="100%"/>
|
||||
</conditions>
|
||||
</line>
|
||||
<line number="46" hits="1" branch="false"/>
|
||||
<line number="49" hits="1" branch="false"/>
|
||||
</lines>
|
||||
</method>
|
||||
</methods>
|
||||
<lines>
|
||||
<line number="8" hits="0" branch="false"/>
|
||||
<line number="10" hits="2" branch="false"/>
|
||||
<line number="11" hits="2" branch="false"/>
|
||||
<line number="12" hits="0" branch="false"/>
|
||||
<line number="16" hits="2" branch="true" condition-coverage="50% (1/2)">
|
||||
<conditions>
|
||||
<condition number="0" type="jump" coverage="50%"/>
|
||||
</conditions>
|
||||
</line>
|
||||
<line number="17" hits="2" branch="false"/>
|
||||
<line number="20" hits="0" branch="false"/>
|
||||
<line number="26" hits="4" branch="true" condition-coverage="100% (2/2)">
|
||||
<conditions>
|
||||
<condition number="0" type="jump" coverage="100%"/>
|
||||
</conditions>
|
||||
</line>
|
||||
<line number="27" hits="2" branch="false"/>
|
||||
<line number="30" hits="2" branch="false"/>
|
||||
<line number="35" hits="0" branch="false"/>
|
||||
<line number="36" hits="0" branch="false"/>
|
||||
<line number="41" hits="2" branch="false"/>
|
||||
<line number="42" hits="10" branch="true" condition-coverage="100% (2/2)">
|
||||
<conditions>
|
||||
<condition number="0" type="jump" coverage="100%"/>
|
||||
</conditions>
|
||||
</line>
|
||||
<line number="43" hits="8" branch="false"/>
|
||||
<line number="45" hits="2" branch="true" condition-coverage="100% (2/2)">
|
||||
<conditions>
|
||||
<condition number="0" type="jump" coverage="100%"/>
|
||||
</conditions>
|
||||
</line>
|
||||
<line number="46" hits="1" branch="false"/>
|
||||
<line number="49" hits="1" branch="false"/>
|
||||
</lines>
|
||||
</class>
|
||||
</classes>
|
||||
</package>
|
||||
</packages>
|
||||
</coverage>
|
|
@ -0,0 +1,52 @@
|
|||
package org.cmake.Coverage;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.awt.*;
|
||||
|
||||
public class CoverageTest {
|
||||
|
||||
public static String VarOne = "test1";
|
||||
public static String VarTwo = "test2";
|
||||
private Integer IntOne = 4;
|
||||
|
||||
public static Boolean equalsVarOne(String inString) {
|
||||
|
||||
if(VarOne.equals(inString)){
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean equalsVarTwo(String inString){
|
||||
|
||||
if(VarTwo.equals(inString)){
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private Integer timesIntOne(Integer inVal){
|
||||
|
||||
return inVal * IntOne;
|
||||
}
|
||||
|
||||
public static boolean whileLoop(Integer StopInt){
|
||||
|
||||
Integer i = 0;
|
||||
while(i < StopInt){
|
||||
i=i+1;
|
||||
}
|
||||
if (i.equals(5)){
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue