技術環境
在以安全與質量為主要驅動力的項目中,CI至關重要。
因此,我從我的團隊開始進行“概念驗證”,以表明以下技術已准備好協同工作:
- Java 8, NetBeans 8.0 & Ant
- JUnit 4 & Jacoco 0.7.1
- Jenkins & Sonar 4.2
本文的范圍是解釋安裝和設置必要工具的所有步驟,以使Java 8的CI服務器完全正常運行。請注意,該證明已在Windows 7的開發人員機器上完成,但很容易做到。在Linux服務器中也是如此。
下圖高層次顯示了將在帖子中描述的體系結構。
Java 8 & NetBeans 8.0 & Ant
我們正在創建模塊化應用程序。該應用程序具有多層體系結構,其中每個層都是模塊套件,而最終的可執行文件只是一組集成套件。
我們正在使用Ant 來構建我們的項目,但是如果您使用的是Maven,則甚至可以簡化該過程,因為Jenkins中的Sonar集成可以通過使用Maven的插件來完成。
JUnit 4 & Jacoco 0.7.1
自然,我們正在進行單元測試,因此,我們使用JUnit4。它在任何地方都可以很好地集成,尤其是在NetBeans中。
Jacoco 是生成代碼覆蓋率的絕佳工具,並且自0.7.1版起,它完全支持Java 8。
Jenkins & Sonar 4.2
Jenkins是我們CI服務器的引擎,它將與上述所有技術集成在一起,沒有任何問題。測試的版本是1.554。
聲納正在對代碼進行所有質量分析。4.2版與Java 8完全兼容。
將Sonar與Ant一起使用需要一個小型庫,其中包含要集成到Jenkins中的目標。如果您使用的是Maven,則可以只安裝Maven插件。
項目配置
1、安裝Java 8
2、創建一個包含幾個模塊,幾個類和幾個jUnit測試的模塊套件
3、將代碼提交到您的源代碼版本管理服務器中
4、在名為“ jacoco-0.7.1”的線束中創建一個文件夾,其中包含下載的jacoco jars
5、在名為“ sonar-ant-task”的線束中創建一個文件夾,並將其放入下載的sonar文件夾
6、在名為sonar-jacoco-module.xml的工具中創建一個文件,並將以下代碼粘貼到其中:
<?xml version="1.0" encoding="UTF-8"?>
<!--
-->
<project name="sonar-jacoco-module" basedir="." xmlns:jacoco="antlib:org.jacoco.ant" xmlns:sonar="antlib:org.sonar.ant">
<description>Builds the module suite otherSuite.</description>
<property name="jacoco.dir" location="${nbplatform.default.harness.dir}/jacoco-0.7.1"/>
<property name="result.exec.file" location="${jacoco.dir}/jacoco.exec"/>
<property name="build.test.results.dir" location="build/test/unit/results"/>
<property file="nbproject/project.properties"/>
<!-- Step 1: Import JaCoCo Ant tasks -->
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
<classpath path="${jacoco.dir}/jacocoant.jar"/>
</taskdef>
<!-- Target at the level of modules -->
<target name="-do-junit" depends="test-init">
<echo message="Doing testing for jacoco"/>
<macrodef name="junit-impl">
<attribute name="test.type"/>
<attribute name="disable.apple.ui" default="false"/>
<sequential>
<jacoco:coverage destfile="${build.test.results.dir}/${code.name.base}_jacoco.exec">
<junit showoutput="true" fork="true" failureproperty="tests.failed" errorproperty="tests.failed"
filtertrace="${test.filter.trace}" tempdir="${build.test.@{test.type}.results.dir}"
timeout="${test.timeout}">
<batchtest todir="${build.test.@{test.type}.results.dir}">
<fileset dir="${build.test.@{test.type}.classes.dir}" includes="${test.includes}"
excludes="${test.excludes}"/>
</batchtest>
<classpath refid="test.@{test.type}.run.cp"/>
<syspropertyset refid="test.@{test.type}.properties"/>
<jvmarg value="${test.bootclasspath.prepend.args}"/>
<jvmarg line="${test.run.args}"/>
<!--needed to have tests NOT to steal focus when running, works in latest apple jdk update only.-->
<sysproperty key="apple.awt.UIElement" value="@{disable.apple.ui}"/>
<formatter type="brief" usefile="false"/>
<formatter type="xml"/>
</junit>
</jacoco:coverage>
<copy file="${build.test.results.dir}/${code.name.base}_jacoco.exec"
todir="${suite.dir}/build/coverage"/>
<!--
Copy the result of all the unit tests of all the modules into one common
folder at the level of the suite, so that sonar could find those files to
generate associated reports
-->
<copy todir="${suite.dir}/build/test-results">
<fileset dir="${build.test.results.dir}">
<include name="**/TEST*.xml"/>
</fileset>
</copy>
<fail if="tests.failed" unless="continue.after.failing.tests">Some tests failed; see details above.
</fail>
</sequential>
</macrodef>
<junit-impl test.type="${run.test.type}" disable.apple.ui="${disable.apple.ui}"/>
</target>
</project>
該文件的范圍是覆蓋添加jacoco覆蓋范圍的do-junit任務,並復制套件構建中每個模塊的單元測試結果,以便聲納將找到所有這些元素一起進行分析。
7、在名為sonar-jacoco-suite.xml的線束中創建一個文件,並將以下代碼粘貼到其中
<?xml version="1.0" encoding="UTF-8"?>
<project name="sonar-jacoco-suite" basedir="." xmlns:jacoco="antlib:org.jacoco.ant" xmlns:sonar="antlib:org.sonar.ant">
<description>Builds the module suite otherSuite.</description>
<property name="jacoco.dir" location="${nbplatform.default.harness.dir}/jacoco-0.7.1"/>
<property name="result.exec.file" location="build/coverage"/>
<!-- Define the SonarQube global properties (the most usual way is to pass these properties via the command line) -->
<property name="sonar.jdbc.url" value="jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8" />
<property name="sonar.jdbc.username" value="sonar" />
<property name="sonar.jdbc.password" value="sonar" />
<!-- Define the SonarQube project properties -->
<property name="sonar.projectKey" value="org.codehaus.sonar:example-java-ant" />
<property name="sonar.projectName" value="Simple Java Project analyzed with the SonarQube Ant Task" />
<property name="sonar.projectVersion" value="1.0" />
<property name="sonar.language" value="java" />
<!-- Load the project properties file for retrieving the modules of the suite -->
<property file="nbproject/project.properties"/>
<!-- Using Javascript functions to build the paths of the data source for sonar configuration -->
<script language="javascript">
<![CDATA[
// getting the value
modulesName = project.getProperty("modules");
modulesName = modulesName.replace(":",",");
res = modulesName.split(",");
srcModules = "";
binariesModules = "";
testModules = "";
//Build the paths
for (var i=0; i<res.length; i++)
{
srcModules += res[i]+"/src,";
binariesModules += res[i]+"/build/classes,";
testModules += res[i]+"/test,";
}
//Remove the last comma
srcModules = srcModules.substring(0, srcModules.length - 1);
binariesModules = binariesModules.substring(0, binariesModules.length - 1);
testModules = testModules.substring(0, testModules.length - 1);
// store the result in a new properties
project.setProperty("srcModulesPath",srcModules);
project.setProperty("binariesModulesPath",binariesModules);
project.setProperty("testModulesPath",testModules);
]]>
</script>
<!-- Display the values -->
<property name="sonar.sources" value="${srcModulesPath}"/>
<property name="sonar.binaries" value="${binariesModulesPath}" />
<property name="sonar.tests" value="${testModulesPath}" />
<!-- Define where the coverage reports are located -->
<!-- Tells SonarQube to reuse existing reports for unit tests execution and coverage reports -->
<property name="sonar.dynamicAnalysis" value="reuseReports" />
<!-- Tells SonarQube where the unit tests execution reports are -->
<property name="sonar.junit.reportsPath" value="build/test-results" />
<!-- Tells SonarQube that the code coverage tool by unit tests is JaCoCo -->
<property name="sonar.java.coveragePlugin" value="jacoco" />
<!-- Tells SonarQube where the unit tests code coverage report is -->
<property name="sonar.jacoco.reportPath" value="${result.exec.file}/merged.exec" />
<!-- Step 1: Import JaCoCo Ant tasks -->
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
<classpath path="${jacoco.dir}/jacocoant.jar"/>
</taskdef>
<target name="merge-coverage">
<jacoco:merge destfile="${result.exec.file}/merged.exec">
<fileset dir="${result.exec.file}" includes="*.exec"/>
</jacoco:merge>
</target>
<target name="sonar">
<taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml">
<!-- Update the following line, or put the "sonar-ant-task-*.jar" file in your "$HOME/.ant/lib" folder -->
<classpath path="${harness.dir}/sonar-ant-task-2.1/sonar-ant-task-2.1.jar" />
</taskdef>
<!-- Execute the SonarQube analysis -->
<sonar:sonar />
</target>
</project>
該文件的范圍是在套件級別定義聲納配置和聲納任務。如果您使用聲納,則某些特殊的數據庫或特殊的用戶必須在此處更改配置。
定義的另一項任務是jacoco合並,該合並實際上將獲取每個模塊的所有生成的exec,並將它們合並到套件構建中的單個exec中,以允許聲納進行分析。
8、用以下內容替換每個模塊的build.xml的內容:
<description>Builds, tests, and runs the project com.infrabel.jacoco.</description>
<property file="nbproject/suite.properties"/>
<property file="${suite.dir}/nbproject/private/platform-private.properties"/>
<property file="${user.properties.file}"/>
<import file="${nbplatform.default.harness.dir}/sonar-jacoco-module.xml"/>
<import file="nbproject/build-impl.xml"/>
9、用以下內容替換每個套件的build.xml的內容:
<description>Builds the module suite otherSuite.</description>
<property file="nbproject/private/platform-private.properties"/>
<property file="${user.properties.file}"/>
<import file="${nbplatform.default.harness.dir}/sonar-jacoco-suite.xml"/>
<import file="nbproject/build-impl.xml"/>
Jenkins
在“管理Jenkins->管理插件”中,進入可用列表並安裝(如果尚未存在)以下插件:
- JaCoCo
- Mercurial or Subversion
- Sonar
如果您在防火牆或代理后面,並且在配置網絡設置時遇到問題,可以隨時從此處手動下載並安裝它們。在這種情況下,請記住還要先下載每個插件的依賴項。
在“管理Jenkins->配置系統”中,檢查是否正確安裝了所有插件,請參見以下屏幕截圖以獲取示例(將文件夾替換為適合您的文件夾):
創建一個新的自由樣式項目,配置您的首選項的版本控制,然后在“構建”面板中添加以下三個“ Invoce Ant”任務:
在“構建后操作”面板中添加新的“記錄Jacoco覆蓋率報告”,其配置如下:
Sonar
按照此腳本創建數據庫,並選擇運行此查詢以使連接正常工作:
GRANT ALL PRIVILEGES ON 'sonar'.* TO 'sonar'@'localhost';
進入聲納的配置文件(sonar.properties)並啟用MySQL,該文件位於安裝的conf文件夾中:
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true
在聲納的配置中,如果需要與Java 8兼容,請更新Java插件
技術類文章精選
- java一行代碼打印心形
- Linux性能監控軟件netdata中文漢化版
- 接口測試代碼覆蓋率(jacoco)方案分享
- 性能測試框架
- 如何在Linux命令行界面愉快進行性能測試
- 圖解HTTP腦圖
- 將swagger文檔自動變成測試代碼
- 五行代碼構建靜態博客
- 基於java的直線型接口測試框架初探
- JUnit中用於Selenium測試的中實踐