zoukankan      html  css  js  c++  java
  • Using Hudson for C++/CMake/CppUnit

    As a follow-up to Using grails projects in Hudson, here is another not-so-standard usage of Hudson: C++ projects with CMake and CppUnit. Let’s see how that works out.

    As long as you have Java/Ant/JUnit based projects, a fine tool that it is, configuration of Hudson is pretty straight forward. But if you have a C++ project with CMake as build system and CppUnit for your unit testing, you have to dig a little deeper. Fortunately, Hudson provides the possibility to execute arbitrary shell commands. So in order to build the project and execute the tests, we can simply put a shell script to work:

       # define build and installation directories
       BUILD_DIR=$WORKSPACE/build_dir
       INSTALL_DIR=$WORKSPACE/install_dir
    
       # we want to have a clean build
       rm -Rf $BUILD_DIR
       mkdir $BUILD_DIR
       cd $BUILD_DIR
    
       # initializing the build system
       cmake  ..  -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR
    
       # fire-up the compiler
       make install

    Environment variable WORKSPACE is defined by Hudson. Other useful variables are e.g. BUILD_NUMBER, BUILD_TAG and CVS_BRANCH.

    But what about those unit tests? Hudson understands JUnit test result files out-of-the-box. So all we have to do is make CppUnit spit out an xml report and then translate it to JUnit form. To help us with that, we need a little xslt transformation. But first, let’s see how we can make CppUnit generate xml results (a little simplified):

    #include <cppunit/necessary/CppUnitIncludes/>
    ...
    
    using namespace std;
    using namespace CppUnit;
    
    int main(int argc, char** argv)
    {
       TestResult    controller;
       TestResultCollector result;
       controller.addListener(&result);
    
       CppUnit::TextUi::TestRunner runner;
       runner.addTest( TestFactoryRegistry::getRegistry().makeTest() );
       runner.run(controller);
    
       // important stuff happens next
       ofstream xmlFileOut("cpptestresults.xml");
       XmlOutputter xmlOut(&result, xmlFileOut);
       xmlOut.write();
    }

    The assumption here is that your unit tests are built into libraries that are linked with the main function above. To execute the unit tests we add the following to out shell script:

       export PATH=$INSTALL_DIR/bin:$PATH
       export LD_LIBRARY_PATH=$INSTALL_DIR/lib:$LD_LIBRARY_PATH
    
       # call the cppunit executable
       cd $WORKSPACE
       cppunittests

    This results in CppUnit generating file $WORKSPACE/cpptestresults.xml. Now, with the help of a little program called xsltproc and the following little piece of XSLT code, we can translate cpptestresults.xml to testresults.xml in JUnit format.

     <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" indent="yes"/>
        <xsl:template match="/">
            <testsuite>
                <xsl:attribute name="errors"><xsl:value-of select="TestRun/Statistics/Errors"/></xsl:attribute>
                <xsl:attribute name="failures">
                    <xsl:value-of select="TestRun/Statistics/Failures"/>
                </xsl:attribute>
                <xsl:attribute name="tests">
                    <xsl:value-of select="TestRun/Statistics/Tests"/>
                </xsl:attribute>
                <xsl:attribute name="name">from cppunit</xsl:attribute>
                <xsl:apply-templates/>
            </testsuite>
        </xsl:template>
        <xsl:template match="/TestRun/SuccessfulTests/Test">
            <testcase>
                <xsl:attribute name="classname" ><xsl:value-of select="substring-before(Name, '::')"/></xsl:attribute>
                <xsl:attribute name="name"><xsl:value-of select="substring-after(Name, '::')"/></xsl:attribute>
            </testcase>
        </xsl:template>
        <xsl:template match="/TestRun/FailedTests/FailedTest">
            <testcase>
                <xsl:attribute name="classname" ><xsl:value-of select="substring-before(Name, '::')"/></xsl:attribute>
                <xsl:attribute name="name"><xsl:value-of select="substring-after(Name, '::')"/></xsl:attribute>
                <error>
                    <xsl:attribute name="message">
                        <xsl:value-of select=" normalize-space(Message)"/>
                    </xsl:attribute>
                    <xsl:attribute name="type">
                        <xsl:value-of select="FailureType"/>
                    </xsl:attribute>
                    <xsl:value-of select="Message"/>
                    File:<xsl:value-of select="Location/File"/>
                    Line:<xsl:value-of select="Location/Line"/>
                </error>
            </testcase>
        </xsl:template>
        <xsl:template match="text()|@*"/>
    </xsl:stylesheet>

    The following call goes into our shell script:

    xsltproc cppunit2junit.xsl $WORKSPACE/cpptestresults.xml > $WORKSPACE/testresults.xml

    In the configuration page we can now check “Display JUnit test results” and give testresults.xml as result file. As a last step, we can package everything in $WORKSPACE/install_dir into a .tgz file and have Hudson to store it as build artifact. That’s it!

    As always, there is room for improvements. One would be to wrap the shell script code above in a separate bash script and have Hudson simply call that script. The only advantage of the approach above is that you can see what’s going on directly on the configuration page. If your project is bigger, you might have more than one CppUnit executable. In this case, you can for example generate all testresult.xml files into a separate directory and tell Hudson to take into account all .xml files there.

    Update: For the CMake related part of the above shell script I recently published the first version of a cmakebuilder plugin for Hudson. Check out my corresponding blog post.

  • 相关阅读:
    C++高级程序员(廊坊+高薪)欢迎各种漂回家!(该职位已截止)
    utf8_unicode_ci和utf8_general_ci区别
    Percentencoding
    libiconv GNU Project Free Software Foundation (FSF)
    2013年1月6日北京交流会:当当网如何打造个性化推荐&精准营销生态系统
    COM Vs .NET (Qt ActiveQt)
    新一篇: Unicode字符编码规范 实例详细介绍各种字符集编码转换问题
    甩开外包,雄踞榜首:揭开“宫爆老奶奶”成功的秘密
    awk使用命令
    API SOCKET基础(三)网络字节序与主机字节序的转换
  • 原文地址:https://www.cnblogs.com/kevinzhwl/p/1847838.html
Copyright © 2011-2022 走看看