使用CruiseControl.Net全面實現持續集成

持續集成想必你們不少人都據說過,甚至都實踐過,最近我又一次親歷了一次持續集成,現將個人經驗分享給你們。關於持續集成的理論在本文概不涉及,本文的主要目的是實戰CruiseControl.Net,用它來全面實現持續集成。web

在配置ccnet.config時會用到一些小工具,一併附上:小工具下載app

首先,咱們來看看用CC.Net能爲咱們作哪些事情:框架

自動獲取源代碼dom

自動Buildide

自動執行UnitTest,並生成單元測試報告svn

自動部署工具

觸發自動化(迴歸)測試單元測試

郵件提醒測試

使用CCTray進行監控ui

應用plugin顯示集成結果

設置集成策略

在開始以前,第一件事是配置咱們的持續集成環境

  獲取SVN或TFS工具,TFS可經過安裝VisualStudio得到,SVN可經過安裝TortoiseSVN來得到。

  安裝和配置IIS,由於咱們要使用Web頁面查看持續集成的結果,因此須要配置IIS,安裝CruiseControl.Net時會爲咱們建立一個名爲ccnet的web應用程序。

  從http://www.cruisecontrolnet.org/這個站點上如今咱們須要的工具CruiseControl.Net並將其安裝。

  安裝VisualStudio2013(固然也可選其它版本)。安裝它的目的有兩個,1. 使用了VSTest.Console.exe產生單元測試結果數據(UnitTest結果和測試覆蓋率),2. 當編譯不能經過時用它能夠發現問題。

到此爲止,集成環境已經OK,下面,咱們來逐一來經過配置ccnet.config實現上述功能。

1.自動獲取源代碼

首先須要瞭解,持續集成的單位是以項目爲單位,在ccnet.config文件裏體現爲Project,以下:

<project name="MyProject"
             description="demoproject showing a small config" queue="Q1">
  <!--內部配置-->
</project>
View Code

配置項目的源代地址,包括本地工做地址和源代碼管理服務地址,對於使用TFS的源碼管理器,向Project下添加以下配置:

<workingDirectory>E:\dailybuild</workingDirectory>
<artifactDirectory>E:\dailybuild</artifactDirectory>
<category>TestProject</category>
<sourcecontrol type="vsts" autoGetSource="true"  applyLabel="false">
  <server>http://tfs1.TestProject.com:8080</server>
  <domain>TestProject.com</domain>
  <project>$/TestProject projects/Analysis and Design\Concierge\Prototype</project>
  <workingDirectory>E:\dailybuild\TestProject</workingDirectory>
  <cleanCopy>true</cleanCopy>
</sourcecontrol>
View Code

對於使用svn源碼管理器,能夠使用如下配置:

<artifactDirectory>d:\svn\Log\MyProject</artifactDirectory>
<sourcecontrol type="svn">
  <executable>C:\Program Files\TortoiseSVN\bin\svn.exe</executable>
  <username>UserName</username>
  <password>******</password>
  <autoGetSource>true</autoGetSource>
  <trunkUrl>http://svnserver/trunk/MyProject</trunkUrl>
  <workingDirectory>d:\svn\trunk\MyProject</workingDirectory>
</sourcecontrol>
View Code 

2.實現自動Build,向Project節點下增長tasks節點,以下

<tasks>
  <msbuild>
    <executable>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable>
    <buildArgs>/p:OutputPath=D:\BuildOutput</buildArgs>
    <workingDirectory>D:\svn\branch\project\</workingDirectory>
    <projectFile>mysolution.sln</projectFile>
    <targets>Build</targets>
    <timeout>9000</timeout>
  </msbuild>
</tasks>
View Code

3.自動執行UnitTest,並生成單元測試報告

若是要生成單元測試報告和單元測試覆蓋率,這裏須要多下寫功夫去配置。首先在建立Runsettings文件,以下:

CodeCoverage.runsettings的配置內容以下:

<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
  <RunConfiguration>
    <!-- Path relative to solution directory -->
    <ResultsDirectory>d:\svn\log\TestResults</ResultsDirectory>

    <!-- [x86] | x64  
      - You can also change it from menu Test, Test Settings, Default Processor Architecture -->
    <TargetPlatform>x86</TargetPlatform>

    <!-- Framework35 | [Framework40] | Framework45 -->
    <TargetFrameworkVersion>Framework40</TargetFrameworkVersion>
  </RunConfiguration>
  <DataCollectionRunSettings>
    <DataCollectors>
      <DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0" assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
        <Configuration>
          <CodeCoverage>
            <!-- Match assembly file paths: -->
            <ModulePaths>
              <Include>
                <ModulePath>.*\.dll$</ModulePath>
                <ModulePath>.*\.exe$</ModulePath>
              </Include>
              <Exclude>
                <ModulePath>.*CPPUnitTestFramework.*</ModulePath>
              </Exclude>
            </ModulePaths>

            <!-- Match fully qualified names of functions: -->
            <!-- (Use "\." to delimit namespaces in C# or Visual Basic, "::" in C++.)  -->
            <Functions>
              <Exclude>
                <Function>^Fabrikam\.UnitTest\..*</Function>
                <Function>^std::.*</Function>
                <Function>^ATL::.*</Function>
                <Function>.*::__GetTestMethodInfo.*</Function>
                <Function>^Microsoft::VisualStudio::CppCodeCoverageFramework::.*</Function>
                <Function>^Microsoft::VisualStudio::CppUnitTestFramework::.*</Function>
              </Exclude>
            </Functions>

            <!-- Match attributes on any code element: -->
            <Attributes>
              <Exclude>
                <!-- Don’t forget "Attribute" at the end of the name -->
                <Attribute>^System.Diagnostics.DebuggerHiddenAttribute$</Attribute>
                <Attribute>^System.Diagnostics.DebuggerNonUserCodeAttribute$</Attribute>
                <Attribute>^System.Runtime.CompilerServices.CompilerGeneratedAttribute$</Attribute>
                <Attribute>^System.CodeDom.Compiler.GeneratedCodeAttribute$</Attribute>
                <Attribute>^System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute$</Attribute>
              </Exclude>
            </Attributes>

            <!-- Match the path of the source files in which each method is defined: -->
            <Sources>
              <Exclude>
                <Source>.*\\atlmfc\\.*</Source>
                <Source>.*\\vctools\\.*</Source>
                <Source>.*\\public\\sdk\\.*</Source>
                <Source>.*\\microsoft sdks\\.*</Source>
                <Source>.*\\vc\\include\\.*</Source>
              </Exclude>
            </Sources>

            <!-- Match the company name property in the assembly: -->
            <CompanyNames>
              <Exclude>
                <CompanyName>.*microsoft.*</CompanyName>
              </Exclude>
            </CompanyNames>

            <!-- Match the public key token of a signed assembly: -->
            <PublicKeyTokens>
              <!-- Exclude Visual Studio extensions: -->
              <Exclude>
                <PublicKeyToken>^B77A5C561934E089$</PublicKeyToken>
                <PublicKeyToken>^B03F5F7F11D50A3A$</PublicKeyToken>
                <PublicKeyToken>^31BF3856AD364E35$</PublicKeyToken>
                <PublicKeyToken>^89845DCD8080CC91$</PublicKeyToken>
                <PublicKeyToken>^71E9BCE111E9429C$</PublicKeyToken>
                <PublicKeyToken>^8F50407C4E9E73B6$</PublicKeyToken>
                <PublicKeyToken>^E361AF139669C375$</PublicKeyToken>
              </Exclude>
            </PublicKeyTokens>


            <!-- We recommend you do not change the following values: -->
            <UseVerifiableInstrumentation>True</UseVerifiableInstrumentation>
            <AllowLowIntegrityProcesses>True</AllowLowIntegrityProcesses>
            <CollectFromChildProcesses>True</CollectFromChildProcesses>
            <CollectAspDotNet>False</CollectAspDotNet>

          </CodeCoverage>
        </Configuration>
      </DataCollector>
    </DataCollectors>
  </DataCollectionRunSettings>
</RunSettings>
View Code

裏面最重要的信息室配置了單元測試結果存放路徑:<ResultsDirectory>d:\svn\log\TestResults</ResultsDirectory>,以便咱們後來生成測試結果。

接着來配置ccnet.config,以執行單元測試

<!--刪除上次單元測試結果-->
<exec>
  <executable>D:\svn\tool\delfile.bat</executable>
  <buildArgs>D:\svn\Log\TestResultsReal\mstest-results.trx</buildArgs>
  <buildTimeoutSeconds>300</buildTimeoutSeconds>
  <successExitCodes>-1,0</successExitCodes>
</exec>
<exec>
  <executable>D:\svn\tool\delfile.bat</executable>
  <buildArgs>D:\svn\Log\TestResultsReal\mstest-coverage.xml</buildArgs>
  <buildTimeoutSeconds>300</buildTimeoutSeconds>
  <successExitCodes>-1,0</successExitCodes>
</exec>
<!--執行單元測試-->
<exec>
  <executable>C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\VSTest.Console.exe</executable>
  <baseDirectory>D:\svn\UnitTest.dll所在的文件目錄</baseDirectory>
  <buildArgs>UnitTest.dll /Enablecodecoverage /Settings:D:\svn\tool\CodeCoverage.runsettings /logger:trx</buildArgs>
  <buildTimeoutSeconds>300</buildTimeoutSeconds>
</exec>
<!--生成測試覆蓋率-->
<exec>
  <executable>
    <!--刪除上次單元測試結果-->
    <exec>
      <executable>D:\svn\tool\delfile.bat</executable>
      <buildArgs>D:\svn\Log\TestResultsReal\mstest-results.trx</buildArgs>
      <buildTimeoutSeconds>300</buildTimeoutSeconds>
      <successExitCodes>-1,0</successExitCodes>
    </exec>
    <exec>
      <executable>D:\svn\tool\delfile.bat</executable>
      <buildArgs>D:\svn\Log\TestResultsReal\mstest-coverage.xml</buildArgs>
      <buildTimeoutSeconds>300</buildTimeoutSeconds>
      <successExitCodes>-1,0</successExitCodes>
    </exec>
    <!--執行單元測試-->
    <exec>
      <executable>C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\VSTest.Console.exe</executable>
      <baseDirectory>D:\svn\UnitTest.dll所在的文件目錄</baseDirectory>
      <buildArgs>UnitTest.dll /Enablecodecoverage /Settings:D:\svn\tool\CodeCoverage.runsettings /logger:trx</buildArgs>
      <buildTimeoutSeconds>300</buildTimeoutSeconds>
    </exec>
    <!--生成測試覆蓋率-->
    <exec>
      <executable>D:\svn\tool\coverage\Auto.Dealer.UnitTest.Tool.exe</executable>
      <buildArgs>D:\svn\log\TestResults\ D:\svn\log\TestResultsReal\mstest-results.trx D:\svn\log\TestResultsReal\mstest-coverage.xml</buildArgs>
      <buildTimeoutSeconds>300</buildTimeoutSeconds>
      <successExitCodes>-1,0</successExitCodes>
    </exec>

    <!--合併xml文件-->
    <merge>
      <files>
        <file>D:\svn\Log\TestResultsReal\mstest-results.trx</file>
        <!--這個文件是用於合併UnitTest result-->
      </files>
    </merge>
    <merge>
      <files>
        <file>D:\svn\Log\TestResultsReal\mstest-coverage.xml</file>
        <!--這個文件是用於合併UnitTest result-->
      </files>
    </merge>D:\svn\tool\coverage\Auto.Dealer.UnitTest.Tool.exe</executable>
  <buildArgs>D:\svn\log\TestResults\ D:\svn\log\TestResultsReal\mstest-results.trx D:\svn\log\TestResultsReal\mstest-coverage.xml</buildArgs>
  <buildTimeoutSeconds>300</buildTimeoutSeconds>
  <successExitCodes>-1,0</successExitCodes>
</exec>

<!--合併xml文件-->
<merge>
  <files>
    <file>D:\svn\Log\TestResultsReal\mstest-results.trx</file>
    <!--這個文件是用於合併UnitTest result-->
  </files>
</merge>
<merge>
  <files>
    <file>D:\svn\Log\TestResultsReal\mstest-coverage.xml</file>
    <!--這個文件是用於合併UnitTest result-->
  </files>
</merge>
View Code

這裏,想必你們已經注意到有兩處刪除操做,由於持續集成式一個不斷重複的過程,若是不刪除原來的測試結果就會發生錯誤。另外,用到的一個工具(這個工具裏的代碼很簡單,一併提供出來以下),用來將trx文件轉化爲xml文件,即單元測試覆蓋率結果。最後將它們一塊兒合併到CruiseControl的執行日誌裏。

生成單元測試覆蓋率代碼以下:

    class Program
    {
        static void Main(string[] args)
        {
            string dirName = args[0];
            string trxUutPutFileName = args[1];
            string coverageoutPutFileName = args[2];

            if (Directory.Exists(dirName))
            {
                DirectoryInfo dirc = new DirectoryInfo(dirName);
                foreach (FileInfo file in dirc.GetFiles("*.trx"))
                {
                    file.CopyTo(trxUutPutFileName, true);
                    break;
                }

                foreach (FileInfo file in dirc.GetFiles("*.coverage", SearchOption.AllDirectories))
                {
                    ConvertToXML(file.FullName, coverageoutPutFileName);
                    break;
                }

                dirc.Delete(true);
            }
            else
            {
                Console.WriteLine("沒找到目錄:"+dirName);
            }
        }

        public static void ConvertToXML(string coverageFile, string outputFile)
        {
            using( CoverageInfo coverageInfo = CoverageInfo.CreateFromFile(coverageFile))
            {
                using (CoverageDS ds = coverageInfo.BuildDataSet())
                {
                    ds.ExportXml(outputFile);
                }
            }
        }
    }
View Code

4.自動部署

<!--發佈到站點-->
<buildpublisher>
  <sourceDir>d:\svn\_PublishedWebsites\MyWeb</sourceDir>
  <publishDir>\\IP地址\website\</publishDir>
  <useLabelSubDirectory>false</useLabelSubDirectory>
</buildpublisher>
View Code

5. 觸發自動化(迴歸)測試

若是有自動化測試框架,則能夠考慮部署完畢後自動觸發執行自動化測試,因爲自動化測試框架可能會有很大差別,這裏就不在給出配置,總的來講,使用<exec></exec>能夠很靈活地實現咱們的需求。

6. 郵件提醒功能

不管持續集成執行成功,仍是失敗,均可以配置相應的郵件接收人員。郵件配置要放到<publishers></publishers>。這樣,郵件發送的失敗就不會阻塞持續集成。

<publishers>
  <email mailport="25" includeDetails="TRUE" mailhostUsername="my@sina.com" mailhostPassword="******" useSSL="FALSE">
    <from>my@sina.com</from>
    <mailhost>smtp.sina.net</mailhost>
    <users>
      <user name="張三" group="developers" address="123@sina.com" />
      <user name="李四" group="developers" address="456@sina.com" />
      <user name="王五" group="developers" address="789@sina.com" />
    </users>
    <groups>
      <group name="developers">
        <notifications>
          <notificationType>Failed</notificationType>
          <notificationType>Fixed</notificationType>
        </notifications>
      </group>
      <group name="buildmaster">
        <notifications>
          <notificationType>Always</notificationType>
        </notifications>
      </group>
    </groups>
    <converters>
      <regexConverter find="$" replace="@sina.com" />
    </converters>
    <modifierNotificationTypes>
      <NotificationType>Failed</NotificationType>
      <NotificationType>Fixed</NotificationType>
    </modifierNotificationTypes>
    <subjectSettings>
      <subject buildResult="StillBroken" value="Build is still broken for {CCNetProject}" />
    </subjectSettings>
  </email>
  <statistics />
  <xmllogger />
</publishers>
View Code

7. 使用CCTray監控持續集成

打開http://CruiseControl所在機的IP/ccnet/,能夠看到以下鏈接,下載並安裝。就能夠監控制定的項目了。

8.應用plugin顯示集成結果

最後,作了以上全部的事情之後,在http://CruiseControl所在機的IP/ccnet/這個站點上並不能看到咱們全部的持續集成結構,CruiseControl爲咱們提供了一些Plugins,即一些xsl文件,使用它們就能夠顯示咱們想要的結果了。這些xsl文件的地址爲:CruiseControl的安裝路徑\CruiseControl.NET\webdashboard\xsl。咱們須要修改一下dashboard.config這個文件,我向其中添加了以下內容:

<buildPlugins>
  <buildReportBuildPlugin>
    <xslFileNames>
      <xslFile>xsl\header.xsl</xslFile>
      <xslFile>xsl\modifications.xsl</xslFile>
      <xslFile>xsl\unittests.xsl</xslFile>
      <xslFile>xsl\MsTestSummary2008.xsl</xslFile>
      <xslFile>xsl\compile-msbuild.xsl</xslFile>
      <xslFile>xsl\SimianSummary.xsl</xslFile>
      <xslFile>xsl\MsTestSummary2010.xsl</xslFile>
      <xslFile>xsl\MsTestSummary.xsl</xslFile>
      <xslFile>xsl\MsTestReport2010.xsl</xslFile>
      <xslFile>xsl\MsTestCover2010.xsl</xslFile>
    </xslFileNames>
  </buildReportBuildPlugin>
</buildPlugins>
View Code

這樣,重啓ccnet站點後,咱們的測試結果也會被格式化地顯示出來。

9.設置集成策略

以每日構建爲例,須要在<triggers></triggers>裏配置以下結果:

<scheduleTrigger time="23:30" buildCondition="ForceBuild" name="Scheduled">
  <weekDays>
    <weekDay>Monday</weekDay>
    <weekDay>Tuesday</weekDay>
    <weekDay>Wednesday</weekDay>
    <weekDay>Thursday</weekDay>
    <weekDay>Friday</weekDay>
  </weekDays>
</scheduleTrigger>
View Code

 

至此,咱們的持續集成也基本上能夠告一段落了。能夠使用它來進行一些自動化的工做了。

相關文章
相關標籤/搜索