如何与Java 8,NetBeans Platform 8,Jenkins,Jacoco和Sonar进行持续集成

介绍

Java 8出现了,人们所期待的革命终于发布了,我敢肯定,你们中的许多人都在想着同样的问题“我应该在项目中使用它吗?”。

好吧,几个月来我遇到了同样的问题,今天我有一个答案想与大家分享。 很多方面都在影响这一决定,但是在这篇文章中,我想特别关注一个方面:

我可以继续与Java 8和NetBeans Platform进行持续集成吗?


主要问题是进行CI所需的工具的成熟度,以及将其与NetBeans平台的ant构建脚本集成起来有多容易。

幸运的是,我们发现这是可行且容易的!

我还要感谢Alberto Requena Sanchez对本文的贡献。

技术环境

在以安全与质量为主要驱动力的项目中,CI至关重要。

因此,我从我的团队开始进行“概念验证”,以表明以下技术已准备好协同工作:

  • Java 8,NetBeans 8.0和Ant
  • JUnit 4和Jacoco 0.7.1
  • 詹金斯与声纳4.2

本文的范围是解释为使Java 8的CI服务器完全正常运行而安装和设置必要工具的所有步骤,请注意,该证明已在Windows 7的开发人员机器上完成,但很容易做到。在Linux服务器中也是如此。

下图高层次显示了将在帖子中描述的体系结构。

持续集成图

持续集成图

Java 8,NetBeans 8.0和Ant

Java 8已发布,可以在此处下载,安装,学习(最好)并开始使用它!

我们正在使用NetBeans Platform 8.0创建模块化应用程序。 该应用程序具有多层体系结构 ,其中每个层都是模块套件,而最终的可执行文件只是一组集成套件。

我们正在使用Ant来构建我们的项目,但是如果您正在使用Maven,那么甚至可以简化该过程,因为可以通过使用Maven的插件来完成Jenkins中的Sonar集成。

JUnit 4和Jacoco 0.7.1

自然,我们正在进行单元测试,因此,我们使用JUnit4。它在任何地方都可以很好地集成,尤其是在NetBeans中。

Jacoco是生成代码覆盖率的绝佳工具,并且自0.7.1版起,它完全支持Java 8。

詹金斯与声纳4.2

Jenkins是我们CI服务器的引擎,它将与上述所有技术集成在一起,没有任何问题。 测试的版本是1.554。

声纳正在对代码进行所有质量分析。 4.2版与Java 8完全兼容。

将Sonar与Ant一起使用需要一个小型库,其中包含要集成到Jenkins中的目标。 如果您使用的是Maven,则可以只安装Maven插件 。

开始困惑

步骤1 – NetBeans

  1. 安装Java 8和NetBeans 8.0
  2. 创建一个包含几个模块,几个类和几个jUnit测试的模块套件
  3. 将代码提交到您的源代码版本管理服务器中
  4. 深入了解NetBeans
  5. 在名为“ jacoco-0.7.1”的线束中创建一个文件夹,其中包含下载的jacoco jars
  6. 在名为“ sonar-ant-task”的线束中创建一个文件夹,并将其放入下载的声纳蚂蚁罐中
  7. 在名为sonar-jacoco-module.xml的工具中创建一个文件,并将以下代码粘贴到其中:
  8. <?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任务,并复制套件构建中每个模块的单元测试结果,以便sonar可以一起找到所有模块以进行分析。

  9. 在名为sonar-jacoco-suite.xml的线束中创建一个文件,并将以下代码粘贴到其中
  10. <?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中,以允许声纳进行分析。

  11. 用以下内容替换每个模块的build.xml的内容:
  12. <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"/>
  13. 用以下内容替换每个套件的build.xml的内容:
  14. <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"/>

    步骤2 –詹金斯

  15. 在“管理Jenkins->管理插件”中,进入可用列表并安装(如果尚未存在)以下插件:
  • JaCoCo
  • 水星或颠覆
  • 声纳

如果您在防火墙或代理后面,并且在配置网络设置时遇到问题,可以随时从此处手动下载并安装它们。 在这种情况下,请记住还要先下载每个插件的依赖项。

  • 在“管理Jenkins->配置系统”中,检查是否正确安装了所有插件,请参见以下屏幕截图以获取示例(将文件夹替换为适合您的文件夹):
  • 詹金斯-jdk1

    詹金斯·杰克

    詹金斯-声纳-1

    詹金斯-声纳2

  • 创建一个新的自由样式项目,配置您的首选项的版本控制,然后在“构建”面板中添加以下三个“ Invoce Ant”任务:
  • 詹金斯配置

  • 最后,在“构建后操作”面板中添加新的“记录Jacoco覆盖率报告”,其配置如下:
  • 詹金斯·雅科科

    步骤3 –声纳

  • 按照此脚本创建数据库,并选择运行此查询以使连接正常工作:
  • GRANT ALL PRIVILEGES ON 'sonar'.* TO 'sonar'@'localhost';
  • 进入声纳的配置文件(sonar.properties)并启用MySQL,该文件位于安装的conf文件夹中
  • # Permissions to create tables, indices and triggers 
    # must be granted to JDBC user.
    # The schema must be created first.
    sonar.jdbc.username=sonar
    sonar.jdbc.password=sonar#----- MySQL 5.x
    # Comment the embedded database and uncomment the following 
    # line to use MySQL
    sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true
  • 在声纳的配置中,如果需要与Java 8兼容,请更新Java插件
  • 如有必要,请始终在sonar.properties文件中配置代理
  • 做完了!

    现在一切都已设置好,您可以进入NetBeans,进行构建,提交代码,然后在Jenkins中启动构建,然后在确定构建之后检查Sonar中的项目。

    就这样! 希望我不会忘记任何事情,但是如果您在此过程中发现一些错误,可以随时提出评论,我将尝试找到解决方案。

    翻译自: https://www.javacodegeeks.com/2014/04/how-to-do-continuous-integration-with-java-8-netbeans-platform-8-jenkins-jacoco-and-sonar.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/364245.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WSS学习(一)---简单部署图

研究了一段时间的WSS&#xff0c;终于找到点头绪了今天把这段时间的思路整理了一下&#xff0c;结果发现就是这么一张图也不知道研究的对不对&#xff0c;有高手发现不对的给点指点有也在研究的大家一起讨论一下简单说明&#xff1a;数据库用SQL2005&#xff0c;报表用SQL2005的…

Wildfly 8.0通过其JAXRS 2.0实现提供了无缝的JSON支持。

很高兴看到Wildfly 8.0使得使用同一组JAXB类中的XML和JSON表示 两者变得更加容易&#xff0c;而无需任何额外的检查或配置不同的JAXB运行时实现。 您需要做的就是 只需从JAXRS资源类中的业务方法中返回JAXB对象 将HTTP Accept标头设置为application / json 返回JAXB类的简单…

vue.config.js配置别名alias、配置生产环境清除console

项目中使用引入文件有时候路径比较深&#xff0c;需要使用"../../../xx.js"这种类似的路劲引入&#xff0c;这种方式比较笨&#xff0c;可以使用webpack的别名alias配置来解决。 首先&#xff0c;先确定项目中是否有path模块&#xff1a; 如果没有path模块需要先安装…

借助Java 8和lambdas,可以一起使用AssertJ和Awaitility

AssertJ和Awaitility是在自动代码测试中使用的两个我最喜欢的工具。 不幸的是直到最近&#xff0c;还不能一起使用它。 但是随后Java 8进入了游戏&#xff0c;几十行代码足以使其在Awaility 1.6.0中实现。 AssertJ提供了一组丰富的断言&#xff0c;其中包含非常有用的错误消息…

小程序-冒泡事件

小程序冒泡事件与非冒泡事件 会随之触发父元素的称为冒泡事件&#xff0c;反之&#xff0c;则是非冒泡事件 wxml&#xff1a; <view class"view1" bindtap"view1click"> <!-- 用 bind 绑定事件 -->view1<view class"view2" bin…

mysql导出表结构 创建_mysql如何导出表结构为文本文件

Log Goup ID&#xff0c;可能会配置多个redo组&#xff0c;每个组对应一个id&#xff0c;当前都是0&#xff0c;占用4字节Start LSN&#xff0c;这个redo log文件开始日志的lsn&#xff0c;占用8字节Log File Number&#xff0c;总是为0&#xff0c;占用4字节Created By&#x…

CSS基础学习-15-1.CSS 浏览器内核

转载于:https://www.cnblogs.com/songsongblue/p/11047935.html

gitlab提交代码push,触发jenkins构建

一、安装插件 Build Authorization TokenRoot Gitlab Hook Plugin二、配置 在linux上执行命令 openssl rand -hex 12获得token&#xff1a; 632f873225efdb5b7e5da411 去掉jenkins的 CSRF Protection设置 找到触发构建的项目&#xff0c;修改触发器 在gitlab的项目中&#xff0…

5分钟搞定jQuery zepto.js 面向对象插件

今天分享一下快速使用jQuery zepto.js的技巧&#xff0c;需要的记得收藏 1.jQuery的引入&#xff1a;本地下载jQuery(后面简称jq)的源文件&#xff0c;开发版本使用非min版&#xff0c;线上使用min版&#xff0c;zepto.js类似&#xff0c;同样的一些基于jq的插件也是如此用法&…

在JDK 8中可通过反射获得构造函数/方法参数元数据

JDK 8较不为人所知的一项新 功能是在编译的Java类中包含参数元数据的可选功能[JDK增强建议&#xff08; JEP &#xff09; 118 ]。 此功能允许Java应用程序在运行时通过反射访问此参数元数据信息。 Java Tutorial的Reflection API路径包括一个名为“ 获取方法参数的名称”的课…

基于面向对象的图片轮播(js原生代码)

无论你想走多远&#xff0c;你都需要不断地走下去。前端最精华的便是原生的js,这也是我们前端工程师的技术分层的重要指标&#xff0c;也提现这你的代码能力&#xff0c;开发的水平。废话不多说&#xff0c;进入今天的主要分享————基于面向对象思想的图片轮播。其效果如下所…

C#定义只能处理枚举类型的泛型类型

1 internal sealed class GenericTypeThatRequireAnEnum<T>2 {3 public static int age 12; //该 static 字段在不同的封闭类型之间是独立不共享的4 5 //静态构造器针对每个封闭类型都会执行一次&#xff0c;泛型类型定义静态构造器的目的就是为了保证传递的类…

Spring应用程序与JNDI连接池的集成测试

我们都知道&#xff0c;无论何时连接到数据库&#xff0c;都需要使用连接池。 所有使用JDBC 4类的现代驱动程序都支持它。 在本文中&#xff0c;我们将概述Spring应用程序中的连接池&#xff0c;以及如何在非JEE环境&#xff08;例如测试&#xff09;中处理相同的上下文。 在S…

在java web工程中jsp页面中使用kindeditor

在这之前我们用Notepad写过kindeditor 在Java web工程里也差不多 首先我们复制之前的thml代码粘贴到工程里 然后把样式也复制进去 然后就可以运行了 转载于:https://www.cnblogs.com/q2546/p/11066539.html

数据分析方法论

把零散的报表整成数据监控体系 把每次拍脑袋的评估整成数据考核体系 在推荐、广告等算法上有所突破&#xff0c;而不是自己瞎捣鼓个没人看的聚类分析 在推送响应等有业绩的地方产出产品&#xff0c;而不是每次用时间序列法预测个销量走势再被业务喷回来。 分析自己的现状&am…

Markdown的使用笔记

Markdown的使用笔记 Markdown在我看是一种使用几种标记符号就可以完成清晰排版的一种标记语言&#xff0c;是写笔记文章的一大利器&#xff0c;使用简单、方便&#xff0c;上手快&#xff0c;而且可以很好的兼容html&#xff0c;即html中的标签在markdown中也同样试用。这边文章…

多项式孤儿桶

巨佬制作人们大家好&#xff0c;我是练习多项式两周半的个人练习生lgl。这里总结一下多项式基本操作。 1.多项式加、减、输出 不说了。 时间复杂度$O(n)$。 2.多项式取模 已知多项式$F(x)$&#xff0c;求它对$x^n$取模。 人话&#xff1a;把$n$次及以上的系数清零。 时间复杂度…

python亲密度_Python OpenCV 图像2D直方图,取经之旅第 25 天

Python OpenCV 365 天学习计划&#xff0c;与橡皮擦一起进入图像领域吧。基础知识铺垫在之前的博客中&#xff0c;我们获取图像直方图的方式都是获取一维直方图&#xff0c;简单说就是只获取一个通道的特征&#xff0c;例如灰度&#xff0c;B 通道&#xff0c;R 通道。今天要学…

清除浮动的方式

1、父级div定义伪类&#xff1a;after和zoom <style type"text/css"> .div1{background:#000080;border:1px solid red;}.div2{background:#800080;border:1px solid red;height:100px;margin-top:10px}.left{float:left;width:20%;height:200px;background:#D…

py函数两个返回值_Python 函数为什么会默认返回 None?

Python 有一项默认的做法&#xff0c;很多编程语言都没有——它的所有函数都会有一个返回值&#xff0c;不管你有没有写 return 语句。本文出自“Python为什么”系列&#xff0c;在正式开始之前&#xff0c;我们就用之前讨论过的 pass语句和 …对象 作为例子&#xff0c;看看 P…