何为持续集成?
持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试) 来验证,从而尽快地发现集成错误。许多团队发现这个过程可以大大减少集成的问题,让团队能够更快的开发内聚的软件。

持续集成的价值:

减少风险
一天中进行多次的集成,并做了相应的测试,这样有利于检查缺陷,了解软件的健康状况,减少假定。
减少重复过程
减少重复的过程可以节省时间、费用和工作量。说起来简单,做起来难。这些浪费时间的重复劳动可能在我们的项目活动的任何一个环节发生,包括代码编译、数据库集成、测试、审查、部署及反馈。通过自动化的持续集成可以将这些重复的动作都变成自动化的,无需太多人工干预,让人们的时间更多的投入到动脑筋的、更高价值的事情上。
任何时间、任何地点生成可部署的软件
持续集成可以让您在任何时间发布可以部署的软件。从外界来看,这是持续集成最明显的好处,我们可以对改进软件品质和减少风险说起来滔滔不绝,但对于客户来说,可以部署的软件产品是最实际的资产。利用持续集成,您可以经常对源代码进行一些小改动,并将这些改动和其他的代码进行集成。如果出现问题,项目成员马上就会被通知到,问题会第一时间被修复。不采用持续集成的情况下,这些问题有可能到交付前的集成测试的时候才发现,有可能会导致延迟发布产品,而在急于修复这些缺陷的时候又有可能引入新的缺陷,最终可能导致项目失败。
增强项目的可见性
持续集成让我们能够注意到趋势并进行有效的决策。如果没有真实或最新的数据提供支持,项目就会遇到麻烦,每个人都会提出他最好的猜测。通常,项目成员通过手工收集这些信息,增加了负担,也很耗时。持续集成可以带来两点积极效果:
(1) 有效决策:持续集成系统为项目构建状态和品质指标提供了及时的信息,有些持续集成系统可以报告功能完成度和缺陷率。
(2) 注意到趋势:由于经常集成,我们可以看到一些趋势,如构建成功或失败、总体品质以及其它的项目信息。
建立团队对开发产品的信心
持续集成可以建立开发团队对开发产品的信心,因为他们清楚的知道每一次构建的结果,他们知道他们对软件的改动造成了哪些影响,结果怎么样。

一:Jenkins 介绍和安装
Jenkins 是基于 Java 开发的一种持续集成工具,用于监控持续重复的工作,功能包括:
持续的软件版本发布/测试项目。
监控外部调用执行的工作。
跟其他持续集成相比,它的主要优点有:开源,即免费。支持多种平台(windows、linux、os x 都支持)。
安装、配置简单。Web 可视化管理界面,并且有丰富的 tips 帮助信息。
为什么要选择 Jenkins?
Jenins 是现在非常流行的持续集成 CI 服务器,这与它的前身 Hudson 也有着很大的关系,Jenkins 易于安装,不需要数据库的支持,直接通过 Web 界面进行配置,而且集成了 RSS/Email 的通知机制,支持分布式构建,具有丰富的插件,这些都是 Jenkins 相比其他持续集成服务器的优势所在。
对于版本控制软件的选择要看项目需要了,可能是 SVN 也可能是 Git,一般来说 Jenkins 都有提供插件支持。

1.1 CentOS 下配置 Jenkins
1.1.1 安装 jdk
新建目录 mkdir /usr/local/java
将 xvf jdk-8u77-linux-x64.gz 压缩包移动到/usr/local/java 目录下
解压 tar xvf jdk-8u77-linux-x64.gz

修改系统变量文件:
Vi /etc/profile
export JAVA_HOME=/usr/local/java/jdk1.8.0_77
export JRE_HOME=/usr/local/java/jdk1.8.0_77/jre
export CLASSPATH=.$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$PATH

重新编译文件 使系统变量即时生效
source /etc/profile
检查 jdk 是否安装成功
Java -version

1.1.2 安装 Jenkins
下载源码包
wget wget http://pkg.jenkins-ci.org/redhat/jenkins-1.656-1.1.noarch.rpm

安装 jenkins
rpm -ivh jenkins-1.656-1.1.noarch.rpm
启动 Jenkins: service jenkins start

可能会报错:Starting Jenkins bash: /usr/bin/java: 没有那个文件或目录
将/usr/local/java/jdk1.8.0_77/bin/java 添加到/etc/init.d/jenkins 文件中对应的位置

再次执行 service jenkins start 启动 jenkins 服务

1.2Windows 下配置 Jenkins
安装过程太过简单 这里不做更多的说明,方式两种:
1:将 jenkins.war 放到 tomcat 安装目录下的 webapp 下,启动 tomcat 即可。

2:使用 java –jar 命令启动如下
//设置 jenkins 的工作目录
set JENKINS_HOME=E:\ToolsForTesting\Jenkins
cd /d %JENKINS_HOME%
//指定 jenkins 端口并启动 jenkins 服务
java -jar jenkins.war --httpPort=8080

二:Jenkins 插件介绍
2.1 Jenkins 集成 Svn
2.1.1 Svn 服务端部署
Step1:CentOS 上安装 Svn 服务端:
yum install svn
Step2:创建版本库目录
mkdir -p /home/svn/svnfile
创建版本库
svnadmin create /home/svn/svnfile
生成以下目录

Step3:配置权限
进入 conf 目录下,在 passwd 文件中配置用户名/密码;
在 authz 文件中设置用户权限;
在 svnserve.conf 文件中配置 svn 服务。

Step4:启动 SVN 服务
svnserve -d -r /home/svn/

2.1.2 Svn 常用命令
从服务器上签出:svn co url (ps: co 为 checkout 缩写)

向服务器提交更新两种情况:
1) 添加新文件并提交到服务器
Step1:svn add file Step2:svn commit –m “comments”
2) 更改已存在的文件后提交到服务器
一步到位:svn ci –m “comments” file_name (ps:ci 为 commit 的缩写)

对文件/目录加锁&解锁
svn lock file_name(or path)
svn unlocl file_name(or path)

更新工作区
svn up(ps:up 为 update 的简写)

回退到指定版本
1) 先 svn up,保证更新到最新的版本。
2) svn log,查看历史版本,找出要恢复的版本。
3) 回滚到指定版本号 svn merge –r 最新版本好:指定的回退版本号。

删除文件或分支
svn del/rm URL(or file) (ps:del 为 delete 缩写;rm 为 remove 缩写)

比较差异
Svn diff –r 版本号 1:版本号 B

将两个版本间的差异合并到当前文件
svn merge –r 版本号 A:版本号 2 path

切换到分支
svn switch (tag/分支) URL

建立 tags
svn copy trunk_URL tags_URL –m “comments”

删除 tags
svn rm tags_URL

创建分支
svn cp trunk_URL branch_URL –m “comments”

同步主干和分支
svn merge trunk_URL branch_URL

2.1.3 Jenkins 上设置 svn
Step 1:Jenkins 上设置 svn
Jenkins 上” 系统管理”” 系统设置” 中选择 svn 服务器端的版本

Step2:源代码管理设置

点击 Add 图标可在页面浮出层中设置 svn 的用户名密码。
Check-out Strategy 签出策略中设置为 Use ‘svn update’ as much as possible。

Step3:构建出发器

选中 Poll SCM,填写 H/10 * * * *
设置触发器为每 10 分钟比对 Svn 服务器,有新的提交则触发当前 job 的构建。

2.2 Jenkins 集成 git
2.2.1 git 的通信协议
Git 可以使用四种主要的协议来传输数据:本地传输,SSH 协议,Git 协议和 HTTP 协议。
(Ps:HTTP 协议外,其他所有协议都要求在服务器端安装并运行 Git)
本地协议
如果你使用一个共享的文件系统,就可以在一个本地文件系统中克隆仓库,推送和获取。克隆的时候只需要将远程仓库的路径作为 URL 使用,比如:
$ git clone /opt/git/project.git
$ git clone file:///opt/git/project.git
本地协议的缺点:
与基本的网络连接访问相比,难以控制从不同位置来的访问权限。如果你想从家里的笔记本电脑上推送,就要先挂载远程硬盘,这和基于网络连接的访问相比更加困难和缓慢。
另一个很重要的问题是该方法不一定就是最快的,尤其是对于共享挂载的文件系统。本地仓库只有在你对数据访问速度快的时候才快。在同一个服务器上,如果二者同时允许 Git 访问本地硬盘,通过 NFS 访问仓库通常会比 SSH 慢。

SSH 协议
SSH 也是唯一一个同时支持读写操作的网络协议;SSH 同时也是一个验证授权的网络协议。
通过 SSH 克隆一个 Git 仓库,你可以像下面这样给出 ssh:// 的 URL:
$ git clone ssh://user@server/project.git
不指明某个协议 Git 会默认使用 SSH :
$ git clone user@server:project.git
如果不指明用户,Git 会默认使用当前登录的用户名连接服务器。
SSH 协议的缺点:
SSH 的限制在于不能通过它实现仓库的匿名访问。也必须在能通过 SSH 访问主机的前提下才能访问仓库,这使得 SSH 不利于开源的项目。

Git 协议
是一个包含在 Git 软件包中的特殊守护进程;
它会监听一个提供类似于 SSH 服务的特定端口(9418),而无需任何授权。打算支持 Git 协议的仓库,需要先创建 git-daemon-export-ok 文件 —它是协议进程提供仓库服务的必要条件。
Git 协议的缺点:
Git 协议消极的一面是缺少授权机制。用 Git 协议作为访问项目的唯一方法通常是不可取的。一般的做法是,同时提供 SSH 接口,让几个开发者拥有推送(写)权限,其他人通过 git:// 拥有只读权限。 Git 协议可能也是最难架设的协议。它要求有单独的守护进程,需要定制 — 我们将在本章的 “Gitosis” 一节详细介绍它的架设 — 需要设定 xinetd 或类似的程序,而这些工作就没那么轻松了。该协议还要求防火墙开放 9418 端口,而企业级防火墙一般不允许对这个非标准端口的访问。大型企业级防火墙通常会封锁这个少见的端口。

HTTP/S 协议
HTTP 或 HTTPS 协议的优美之处在于架设的简便性。基本上,只需要把 Git 的裸仓库文件放在 HTTP 的根目录下,配置一个特定的 post-update 挂钩(hook)就可以搞定。
下面的操作可以允许通过 HTTP 对仓库进行读取:
$ cd /var/www/htdocs/
$ git clone --bare /path/to/git_project gitproject.git
$ cd gitproject.git
$ mv hooks/post-update.sample hooks/post-update
$ chmod a+x hooks/post-update
这样就可以了。Git 附带的 post-update 挂钩会默认运行合适的命令(git update-server-info)来确保通过 HTTP 的获取和克隆正常工作。
HTTP/S 协议的缺点:
克隆或者下载仓库内容可能会花费更多时间,而且 HTTP 传输的体积和网络开销比其他任何一个协议都大。因为它没有按需供应的能力 — 传输过程中没有服务端的动态计算 — 因而 HTTP 协议经常会被称为傻瓜(dumb)协议。

2.2.2 脑补 git 命令
以下示例选择 git oschina 为 git 服务器,在 git oschina 上新建一个 private 的项目。

下载 git for windows 并安装,完成安装后打开 Git Bash。
在 D 盘新建文件夹作为仓库

初始化仓库
git init(ps:git init –bare 也可)
二者区别是:
git init 使用普通库初始化
git init –bare 使用裸库初始化

//仓库初始化完成后 d/testgit 文件夹下会有一个.git 的文件夹,它是版本库。

配置邮件和用户名
git config –-global user.email “邮箱地址”
git config –-global user.anme “用户名可随意”

创建 SSH Key
ssh-keygen -t rsa -C "你的邮箱地址"
一路回车即可,在当前用户主目录里的.ssh 下会生成两个文件 id_rsa(私钥) 和 id_rsa.pub(公钥)

登录 git oschina,在个人资料----SSH 公钥栏中添加生成的公钥

克隆远程仓库
git clone 仓库 URL
如: git clone https://git.oschina.net/Share-Cherish/showgitcommand.git
git clone 和 git remote add 的区别是:
git clone 无需初始化仓库,它会拉取远程仓库到本地。
git remote add 操作必须在仓库中执行。
简要来说 git clone 等同于如下操作

mkdir "exampleProject"
cd "exampleProject"
git init
git remote add origin git@github.com:exampleUser/exampleProject.git
git pull origin master

创建分支
git branch 分支名 (ps:git branch 会列出所有分支)
如:git branch develop

切换分支
git checkout 分支名
如:git checkout master
git checkout –b 分支名 (创建并切换到分支) 它等同于 git branch 分支后再执行 git checkout 分支。

添加新文件
1) 新建文件 vi first_newfile.txt 在里面输入内容 add the first line
2) 将文件添加到缓冲区 git add first_newfile.txt
3) 将修改的内容提交到仓库 git commit –m “备注信息”

查看修改日志
git log
若想以精简方式显示 log 信息可以使用 git log–pretty=oneline

版本回退
git reset –hard HEAD回退到上一个版本; -head HEAD回退到上上一个版本;
回退到 4 个版本之前 git reset –hard HEAD~4

撤销修改
1) 修改了文件内容 没有执行 git add 和 git commit 操作
git checkout --需要撤销修改内容的文件名
2) 修改了文件内容 已执行 git add 操作 想撤销修改需要两步
先执行 git reset HEAD 文件名 再执行 git checkout –文件名

从版本库中删除文件
先执行 git rm 文件名 再执行 git commit

合并分支
git merge 分支名 (把指定分支合并到当前分支上)
如:git checkout master; git merge develop(把 develop 分支合并到 master 上)
git merge 默认会使用 Fast forward 模式,该模式下,删除分支后,会丢掉分支信息。
git merge –no-ff –m “comments” 分支名:
禁用 Fast forward 模式合并分支并添加一个新的备注。

删除分支
git branch –d 分支名
如:git branch –d develop

推送本地修改到远程仓库
git push 远程仓库名 本地分支名
如:git push origin develop

拉取远程分支到本地当前仓库
git pull
若 git pull 操作时提示 “no tracking information”,则说明本地分支和远程分支的链接关系未创建,用命令 git branch --set-upstream 本地分支名 origin/远程仓库分支名来创建本地分支和远程分支的链接。

2.2.3 Jekins 上的 git 设置
在系统管理 ---- 插件管理中选择 git 插件进行安装

在 job 的源码管理栏配置远程仓库 URL

配置触发器

点击立即构建 测试 Job 是否可以构建成功

2.3 Jenkins 集成 Ant
2.3.1 Ant 安装
1) CentOS 上安装 Ant
下载 Ant :wget http://apache.opencas.org//ant/binaries/apache-ant-1.9.7-bin.tar.gz
解压 Ant 包:tar -xvzf apache-ant-1.9.7-bin.tar.gz
编辑/etc/profile 文件 vi /etc/profile 添加内容 export ANT_HOME=Ant 包解压的目录
创建链接 cd /bin 执行 ln -s -f /root/Ant/apache-ant-1.9.7/bin/ant

2) windows 上安装 Ant
下载 Ant 包, 将解压后的目录作为环境变量 ANT_HOME 的值添加到系统变量即可。

2.3.2 Ant 常用配置项详解

1) name 属性:项目名称
2) deault 属性:必填项 表示默认的运行目标
3) basedir 属性:项目的基准目标
4) description 属性:项目的描述
示例如下:


ant firsttest!


1) name 属性:必填项 表示声明
2) depends 属性:依赖的目标
3) unless 属性:属性未设置时才知晓
4) description 属性:项目描述
示例如下:



创建目录


1) destfile 表示 jar 文件名
2) basedir 表示被归档的文件名
3) include 表示被归档的文件模式
4) exclueds 表示被排除的文件模式
示例如下:


1) srcdir 表示源文件的目录
2)destdir 表示 class 文件的输出目录
3)include 表示被编译的文件的模式
4)excludes 表示被排除的文件的模式
5)classpath 表示使用的类路径
6)debug 表示包含的调试信息
7)optimize 表示是否使用优化
8)verbose 表示提供详细的输出信息
9)fileonerror 表示当碰到错误就自动停止
示例如下:













1)file 表示要删除的文件
2)dir 表示要删除的目录
3)includEmptyDirs 表示是否要删除空目录,默认值是删除
4)failonerror 表示指定当碰到错误是否停止,默认值是自动停止

5)verbose 是否列出所删除的文件,默认是不列出
使用示例:





file 表示源文件
tofile 表示目标文件
todir 表示目标目录
overwrite 表示指定是否覆盖目标文件,默认值是不覆盖
includeEmptyDirs 表示指定是否拷贝空目录,默认是拷贝
failonerror 表示指定如目标没有发现是否自动台停止,默认是停止
使用示例:



Ant 实例详解:
<?xml version="1.0" encoding="UTF-8"?>

<!-- java 源文件目录 -->

<!-- 构建目录 -->

<!-- class 文件的存放目录 -->

<!--war 包的存放目录-->

<!-- tomcat_home 路径 -->

<!-- -->
<!-- web 应用名 -->

<!-- web 根目录-->



<!--Svn 远程目录-->

<!-- 编译时的 classpath -->








<!-- 直接调用 svn exec 要确保安装了 svn 客户端-->

<!-- 设置 svn 的命令行参数 -->






start init task














complate tar package of war





deploy to tomcat




2.3.3 Jenkins 上的 Ant 配置使用
配置 ANT_HOME

新建自由风格的 Job,源码管理配置为 svn 地址:

构建触发器 (每 10 分钟扫描 svn):

配置构建组件 (这里我用的是环境变量 Ant_Home,target 填写 build.xml 里的 deploy):

任务构建完成:

2.4 Jenkins 集成 Maven
2.4.1 Maven 安装和命令使用
Maven 是什么?
Maven 是一个项目管理和整合工具。Maven 为开发者提供了一套完整的构建生命周期框架。开发团队几乎不用花多少时间就能够自动完成工程的基础构建配置,因为 Maven 使用了一个标准的目录结构和一个默认的构建生命周期。
在有多个开发团队环境的情况下,Maven 能够在很短的时间内使得每项工作都按照标准进行。因为大部分的工程配置操作都非常简单并且可复用,在创建报告、检查、构建和测试自动配置时,Maven 可以让开发者的工作变得更简单。
Maven 能够帮助开发者完成以下工作:
• 构建
• 文档生成
• 报告
• 依赖
• SCMs
• 发布
• 分发
• 邮件列表
总的来说,Maven 简化了工程的构建过程,并对其标准化。它无缝衔接了编译、发布、文档生成、团队合作和其他任务。Maven 提高了重用性,负责了大部分构建相关的任务。

CentOS 上安装 Maven:
下载 maven 包:
wget http://mirrors.hust.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz
解压:
Tar –zxvf apache-maven-3.3.9-bin.tar.gz

建立软链接:
Ln –s apache-maven-3.3.9 maven
配置环境变量:
vi /etc/profile
export M2_HOME=/usr/local/apache-maven
export PATH=$PATH:$M2_HOME/bin
使环境变量生效:
source /etc/profile
验证安装结果:

2.4.2 Maven 常用命令介绍

mvn help:system 自动在本用户下创建 ~/.m2/repository
mvn clean compile 清理编译
mvn clean test 清理测试
mvn clean package 清理打包
mvn clean install 清理将打包好的 jar 存入 本地仓库 注意是本地仓库
mvn archetype:generate 使用 Archetype 生成项目骨架
mvn clean deploy 根据 pom 中的配置信息将项目发布到远程仓库中

Maven 项目的目录结构:
src/main/java :正式内容包路径
src/mian/resources :正式的配置文件路径
src/test/java :测试包路径
src/test/resources :测试的配置文件路径
src/main/webapp : war 资源目录

mvn dependency:list 显示所有已经解析的所有依赖
mvn dependency:tree 以目录树的形式展现依赖, 最高层为一层依赖 其次二层依赖 三层依赖....
mvn dependency:analyze 第一部分显示 已经使用但是未显示依赖的的 第二部分显示项目未使用的但是依赖的
构件: jar 插件 war 所有依赖的 jar
构建:编译 测试 打包 发布

构建生命周期:
生命周期就是接口:表明要干什么事情
插件就是具体的实现:表明怎么干这件事情
一个典型的 Maven 构建生命周期是由以下几个阶段的序列组成的:
阶段 处理 描述
prepare-resources 资源拷贝 本阶段可以自定义需要拷贝的资源
compile 编译 本阶段完成源代码编译
package 打包 本阶段根据 pom.xml 中描述的打包配置创建 JAR / WAR 包
install 安装 本阶段在本地 / 远程仓库中安装工程包
当需要在某个特定阶段之前或之后执行目标时,可以使用 pre 和 post 来定义这个目标。

Pom.xml 实例:
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4.0.0
com.temp
Demo
war
0.0.1-SNAPSHOT
Demo Maven Webapp
http://maven.apache.org


junit
junit
3.8.1
test


javax.servlet
javax.servlet-api
3.1.0
provided


org.htmlparser
htmlparser
1.6

<!-- spring 需要的 jar 包 -->

org.springframework
spring-context
3.2.4.RELEASE
jar


org.springframework
spring-core
3.2.4.RELEASE
jar


org.springframework
spring-beans
3.2.4.RELEASE
jar


org.springframework
spring-webmvc
3.2.4.RELEASE
jar


org.springframework
spring-orm
3.2.4.RELEASE
jar

<!-- 连接 MySQL 数据库需要的 jar 包 -->

mysql
mysql-connector-java
5.1.34

<!-- jstl 需要的 jar 包 -->

jstl
jstl
1.2

<!-- log4j 需要的 jar 包 -->

log4j
log4j
1.2.17

<!-- mybatis 需要的 jar -->

org.mybatis
mybatis
3.3.0


c3p0
c3p0
0.9.1.2


org.mybatis
mybatis-spring
1.2.2


com.fasterxml.jackson.core
jackson-databind
2.5.3

<!-- PDFBOX -->

org.apache.pdfbox
pdfbox
2.0.0


org.apache.pdfbox
pdfbox-tools
2.0.0


com.itextpdf
itextpdf
5.5.1



zfyz


2.4.3 Jenkins 上配置使用 Maven
系统管理中配置 Maven:

新建 Maven 构建项目:
设置源码管理的 svnurl

配置构建项:

立即构建验证效果:

2.5 Jenkin 集成 Java 静态检查工具
2.5.1 PMD 安装和使用
PMD 介绍:
PMD 是一种开源分析 Java 代码错误的工具。与其他分析工具不同的是,PMD 通过静态分析获知代码错误。也就是说,在不运行 Java 程序的情况下报告错误。PMD 附带了许多可以直接使用的规则,利用这些规则可以找出 Java 源程序的许多问题,例如:
® 潜在的 bug:空的 try/catch/finally/switch 语句
® 未使用的代码:未使用的局部变量、参数、私有方法等
® 可选的代码:String/StringBuffer 的滥用
® 复杂的表达式:不必须的 if 语句、可以使用 while 循环完成的 for 循环
® 重复的代码:拷贝/粘贴代码意味着拷贝/粘贴 bugs
® 循环体创建新对象:尽量不要再 for 或 while 循环体内实例化一个新对象
@ 资源关闭:Connect,Result,Statement 等使用之后确保关闭掉
此外,用户还可以自己定义规则,检查 Java 代码是否符合某些特定的编码规范。例如,你可以编写一个规则,要求 PMD 找出所有创建 Thread 和 Socket 对象的操作。
PMD 安装:
https://github.com/mrniko/redisson/wikipmd 的 wiki 信息可查看
https://pmd.github.io/ 下载 pmd。

使用 Ant 执行 PMD 的 task:
Java 项目的目录结构:

其中的 PMD 文件夹中存放的是 pmd 依赖的 jar 包和自定义的检查规则。

Pmd 的 task 如下编写:
<?xml version="1.0" encoding="UTF-8"?>



<!-- 定义 pmd 的 classpath,均为下载的 pmd 包解压后 lib 目录下的 jar 包-->









<!-- 定义 PMD 检测规则所在的文件,规则集在 pmdrule.xml 文件中定义-->

<!-- 输出 html 格式的报告-->

<!-- 静态代码检测工程下 src 目录下的所有 java 文件-->







我们执行 ant –f pmd-task.xml:

构建 pmd 的 task 成功后 在指定的目录下会生产报告 pmd-report.html

接下来我们将 pmd 集成到 Jenkins 中:
首先安装插件 PMD Plug-in,Maven Integration plugin,Static Analysis Collector Plug-in,Static Analysis Utilities。

新建 Job 命名为 jenkins+pmd;配置远程源码仓库 url 地址:

构建出发器:每 10 分钟检查源码仓库是否有更新:

配置构建任务:

配置构建后的操作:

立即构建后我们即可查收邮件并查看 pmd 的检查结果:

邮件内容:

查看 PMD Warnings:

2.5.2 CheckStyle 的安装和使用
Checkstyle 介绍:
CheckStyle 是什么?
  CheckStyle 是 SourceForge 下的一个项目,提供了一个帮助 JAVA 开发人员遵守某些编码规范的工具。它能够自动化代码规范检查过程,从而使得开发人员从这项重要,但是枯燥的任务中解脱出来 [1]。
  2.2. CheckStyle 检验的主要内容
  CheckStyle 默认提供一下主要检查内容:
  •Javadoc 注释
  •命名约定
  •标题
  •Import 语句
  •体积大小
  •空白
  •修饰符
  •块
  •代码问题
  •类设计
  •混合检查(包活一些有用的比如非必须的 System.out 和 printstackTrace)
  从上面可以看出,CheckStyle 提供了大部分功能都是对于代码规范的检查,而没有提供象 PMD 和 Jalopy 那么多的增强代码质量和修改代码的功能。但是,对于团队开发,尤其是强调代码规范的公司来说,它的功能已经足够强大。

安装 checkstyle:
首先请务必到 github 上去读官方文档: https://github.com/checkstyle/checkstyle
将 checkstyle 的 jar 包放置在 ant 安装目录下的 lib 下即可。

创建 ant 任务 (ps:大百度搜索结果都是特么扯淡 请直接去官网看怎么写的):
<?xml version="1.0" encoding="UTF-8"?>









Jenkins 上集成 checkstyle 插件:
我这里直接上截图哦
最重要的两步之一:构建 (配置 ant_home,targets 和 build file)

构建后将 checkstyle 的结果发布出来:
因为在 ant 的任务配置中我是直接把 checkstyle 的结果生成在项目的根目录下,所以我下面的 checkstyle results 直接写了文件名。

任务配置完成后 我们直接点立即构建可查看效果 (我这里试了几次,所以前几次构建是失败的):

我们可点击 checkstyle warnings 查看 checkstyle 的检查结果:

2.5.3 Findbugs 安装和使用
FindBugs 是什么?
FindBugs 是一个静态分析工具,它检查类或者 JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题。有了静态分析工具,就可以在不实际运行程序的情况对软件进行分析。不是通过分析类文件的形式或结构来确定程序的意图,而是通常使用 Visitor 模式(请参阅 参考资料)。图 1 显示了分析一个匿名项目的结果(为防止可怕的犯罪,这里不给出它的名字):
在 FindBugs 的 GUI 中,需要先选择待扫描的.class 文件 (FindBugs 其实就是对编译后的 class 进行扫描,藉以发现一些隐藏的 bug。)。如果你拥有这些.class 档对应的源文件,可把这些.java 文件再选上,这样便可以从稍后得出的报告中快捷的定位到出问题的代码上面。此外,还可以选上工程所使用的 library,这样似乎可以帮助 FindBugs 做一些高阶的检查,藉以发现一些更深层的 bug。
选定了以上各项后,便可以开始检测了。检测的过程可能会花好几分钟,具体视工程的规模而定。检测完毕可生成一份详细的报告,藉由这份报告,可以发现许多代码中间潜在的 bug。比较典型的,如引用了空指针 (null pointer dereference), 特定的资源 (db connection) 未关闭,等等。如果用人工检查的方式,这些 bug 可能很难才会被发现,或许永远也无法发现,直到运行时发作…当除掉了这些典型的 (classic) bug 后,可以确信的是,我们的系统稳定度将会上一个新的台阶。
以目前遇到的状况来看,FindBugs 可以有两种使用时机。
开发阶段
当 Developer 完成了某一部分功能模块开发的时候 (这通常是指代码撰写完成,并已 debug 通过之后),可藉由 FindBugs 对该模块涉及的 java 文件进行一次扫描,以发现一些不易察觉的 bug 或是效能问题。交付新版的时候,开发团队可以跑一下 FindBugs,除掉一些隐藏的 Bug。FindBugs 得出的报告可以作为该版本的一个参考文档一并交付给测试团队留档待查。
在开发阶段使用 FindBugs,一方面开发人员可以对新版的品质更有信心,另一方面,测试人员藉此可以把更多的精力放在业务逻辑的确认上面,而不是花大量精力去进一些要在特殊状况下才可能出现的 BUG(典型的如 Null Pointer Dereference)。从而可以提高测试的效率。
维护阶段
这里指的是系统已经上线,却发现因为代码中的某一个 bug 导致系统崩溃。在除掉这个已暴露的 bug 之后,为了快速的找出类似的但还未暴露的 bug,可以使用 FindBugs 对该版的代码进行扫描。当然,在维护阶段使用 FindBugs 往往是无奈之举,且时间紧迫。此外,如果本来在新版交付的时候就使用过 FindBugs 的话,往往意味着这种 bug 是 FindBugs 还无法检测出的。这也是 FindBugs 局限的地方。
FindBugs 出到目前的版本,功能已经相当强大,不过也有待完善的地方。从实际使用来看,有一些隐藏的 bug 并不能靠 FindBugs 直接发现。那么,可不可以撰写一个新的 Detector,来发现这种将一个未初始化的 reference 传来传去而形成的潜在的 bug 呢?理论上来讲,应该是可以的。这个 Detector 目前还未实现。哪位如果有兴趣的话,可以参考 FindBugs, Part 2: Writing custom detectors(扩展阅读)这篇文章,帮忙实现这个 Detector。实现一个新的 Detector,便可以检测出一种新型的 bug,这样不知又可以帮开发人员省去多少人工检查的时间,功德无量啊。
FindBugs 也不能发现非 java 的 Bug。对于非 java 撰写的代码,如 javascript,SQL 等等,要找出其中可能的 bug,FindBugs 是无能为力的。当然,javascript 中的 bug 似乎还不至于使系统崩溃,而 SQL 中的 bug 往往又跟业务逻辑相关,只要测试仔细一些应该是可以发现的。
FindBugs 不过是一个工具。作为开发人员,当然首先要在编程的时候努力避免引入 bug,而不要依赖于某个工具来为自己把关。不过由于代码的复杂性,一些隐藏的 bug 确实很难靠咱们的肉眼发现。这时,应用一些好的工具或许就可以帮你发现这样的 bug。这便是 FingBug 存在的价值。
为什么应该将 FindBugs 集成到编译过程中?
经常问到的第一个问题是为什么要将 FindBugs 加入到编译过程中?虽然有大量理由,最明显的回答是要保证尽可能早地在进行编译时发现问题。当团队扩大,并且不可避免地在项目中加入更多新开发人员时,FindBugs 可以作为一个安全网,检测出已经识别的缺陷模式。我想重申在一篇 FindBugs 论文中表述的一些观点。如果让一定数量的开发人员共同工作,那么在代码中就会出现缺陷。像 FindBugs 这样的工具当然不会找出所有的缺陷,但是它们会帮助找出其中的部分。现在找出部分比客户在以后找到它们要好——特别是当将 FindBugs 结合到编译过程中的成本是如此低时。
一旦确定了加入哪些过滤器和类,运行 FindBugs 就没什么成本了,而带来的好处就是它会检测出新缺陷。如果编写特定于应用程序的检测器,则这个好处可能更大。
生成有意义的结果
重要的是要认识到这种成本/效益分析只有在不生成大量误检时才有效。换句话说,如果在每次编译时,不能简单地确定是否引入了新的缺陷,那么这个工具的价值就会被抵消。分析越自动化越好。如果修复缺陷意味着必须吃力地分析检测出的大量不相干的缺陷,那么您就不会经常使用它,或者至少不会很好地使用它。
确定不关心哪些问题并从编译中排除它们。也可以挑出 确实关注的一小部分检测器并只运行它们。另一种选择是从个别的类中排除一组检测器,但是其他的类不排除。FindBugs 提供了使用过滤器的极大灵活性,这可帮助生成对团队有意义的结果。
确定用 FindBugs 的结果做什么
可能看来很显然,但是团队中有多少加入了类似 FindBugs 这样的工具而没有真正利用它。深入探讨这个问题——用结果做什么?明确回答这个问题是困难的,因为这与团队的组织方式、如何处理代码所有权问题等有很大关系。不过,下面是一些指导:
可以考虑将 FindBugs 结果加入到源代码管理(SCM)系统中。一般的经验做法是不将编译工件(artifact)放到 SCM 系统中。不过,在这种特定情况下,打破这个规则可能是正确的,因为它使您可以监视代码质量随时间的变化。
可以选择将 XML 结果转换为可以发送到团队的网站上的 HTML 报告。转换可以用 XSL 样式表或者脚本实现。有关例子请查看 FindBugs 网站或者邮件列表(请参阅 参考资料)。
像 FindBugs 这样的工具通常会成为用于敲打团队或者个人的政治武器。尽量抵制这种做法或者不让它发生——记住,它只是一个工具,它可以帮助改进团队成员代码的质量。

Findbugs 安装:
下载 findbugs https://sourceforge.net/projects/findbugs/

配置 findbugs 的 ant-task:
<?xml version="1.0" encoding="UTF-8"?>

<!--set findbugs's home-->

<!--set findbugs check rule file-->






<!--set reference of task findbugs-->

<!--define task findbugs-->







自定义检查规则:
<?xml version="1.0" encoding="UTF-8"?>































在 Jenkins 上集成 findbugs:
和 pmd 以及 checkstyle 一样创建一个自由风格的 job
源代码使用 svn 管理
我这里直接上图:

构建成功后点击 FindBugs Warnings 查看结果:

2.7 Jenkins 上的邮件扩展
安装邮件扩展插件

在” 系统设置” ---- “Extended E-mail Notification” 中配置扩展邮件项

(ps:注意这里的邮箱地址要和 Jenkins Location—系统管理员邮件地址一致)

我这里是使用 163 邮箱作示例,需要登录到 163 邮箱进行一些设置
在” 设置” --- “POP3/SMTP/IMAP” 中开启 POP3/SMTP 服务和 IMAP/SMTP 服务

在” 客户端授权密码” 中设置客户端的授权密码 (此处的授权密码即为 Jenkins 中的邮箱密码)

在 Job 中设置构建后的发送邮件步骤:

立即构建查看邮件内容:

OK 大功告成!(PS:各位同学可根据自己需要来设计邮件内容模板)

2.8 Jenkins 集成 RobotFrameWork test results
首先在” 系统管理” --- “管理插件” 中搜索 Robot 然后选择 Robot Framework plugin 插件进行安装

在 Job 总配置 RobotFramework 插件

立即构建该 job 来验证我们的设置

我也可以看到测试的完成情况,也可以点击 Robot Results 来查看详情

三:后记:
历时数周终成此稿,不忍窃为己有,遂飨众亲; 不负晚上加餐后长的那二两肥膘~~~~~~~~~


↙↙↙阅读原文可查看相关链接,并与作者交流