持续集成 在 Linux 上搭建 Jenkins,自动构建接口测试

耿晓 · 2022年12月25日 · 最后由 ChampionH 回复于 2023年11月24日 · 13115 次阅读

Hi,我是测试耿晓,前段时间我发布了一篇有关自己基于"pytest+requests+allure"测试框架的实践经验帖,佬儿哥佬儿姐们可以进去指点一下,接口测试 - 从 0 不到 1 的心路历程 (二),其实在完成测试脚本后,我并不满足于每次都手动运行脚本,所以我想到了 Jenkins,通过一系列实践之后,最终实现了 jenkins 定时使用 git 拉取代码,自动构建项目,并且把测试报告发送到我邮箱的效果。本篇就把从 0 开始搭建 Jenkins 的过程分享给大家,希望对小伙伴们有所帮助。

文章目录

  • 在 Linux 上安装 Jenkins
  • 在 Linux 上安装 Git
  • 在 Linux 上安装 Python
  • 在 Linux 上安装 Allure
  • 配置 Jenkins
  • jenkins 赋能 - 使用邮箱发送测试报告
  • jenkins 赋能 - 优化测试报告内容

Tips:在搭建过程中,我参考了网上很多资料,在众多虚虚实实的资料中不断地实践,最终搭建成功了。最想分享给各位的一个观点就是,尤其要注意版本依赖问题,Linux 版本、jdk 版本、Jenkins 版本等等,其次就是不同版本的配置文件内容也不一定相同,伙伴们一定要注意。在以下内容中,我也会尽可能的标明我使用的具体版本,希望可以助力有需要的小伙伴们。

在 Linux 上安装 Jenkins

我是在双十一的时候参加阿里云服务器购买活动时买的服务器,相信很多伙伴对这个活动都不陌生,因为微信公众号中很多博主都有做推广,刚好我用在这个地方。我服务器操作系统版本是CentOS 8.2 64 位,并且我使用了宝塔服务器运维面板,后续往服务器上上传安装包会经常用到它。

Jenkins 依赖 Java 环境,所以第一步是安装 jdk。
1.1.下载jdk11,因为最新版 Jenkins 已经不支持 jdk8。jdk 下载链接
我选择的是jdk-11.0.17

1.2.在 Linux 中创建 jdk 安装目录,我习惯把用到的东西安装在/usr/local 下面,方便管理。
# mkdir /usr/local/java

1.3.进入到创建好的 java 目录中,使用宝塔将下载好的 jdk11 上传上去。

1.4.解压压缩包。
# tar -zxvf jdk-11.0.17_linux-x64_bin.tar.gz

1.5.配置环境变量。
1.5.1 编辑 profile 文件。
# vim /etc/profile
追加如下内容:
export JAVA_HOME=/usr/local/java/jdk-11.0.17
export CLASSPATH=$JAVA_HOME/lib
export PATH=$PATH:$JAVA_HOME/bin

注意:这里的 CLASSPATH 如果是 jdk11,则写成"export CLASSPATH=$JAVA_HOME/lib",如果是 jdk8,则写成"CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar"。
记得保存后退出。:wq
1.5.2 重新加载配置文件 - 是配置立马生效。
# source /etc/profile
1.5.3 验证。
# java -version

第二步,安装 maven
我查找到的资料大部分表示 maven 也是 jenkins 的依赖项,具体原因我不太了解,以后有机会了解后再和大家分享,目前我们就只管安装就好了。
2.1 下载 maven 的 tar.gz 安装包,我选择的是 3.6.3 版本maven3.6.3 版本下载链接

2.2 创建 maven 目录
# mkdir /usr/local/maven

2.3 将下载后的安装包上传至 maven 目录

2.4 解压缩
# tar -zxvf apache-maven-3.6.3-bin.tar.gz

2.5 配置环境变量
# vim /etc/profile
在文件底部追加如下内容:
export M2_HOME=/usr/local/maven/apache-maven-3.6.3
export PATH=$PATH:$M2_HOME/bin

保存后退出。

2.6 使配置文件生效
# source /etc/profile

2.7 验证是否安装成功
# mvn -v

第三步,安装 Jenkins
3.1 下载 Jenkins 的 rpm 包。jenkins rpm 包下载地址
我选择的是jenkins-2.346-1.1.noarch.rpm 2022-05-03 20:45 87M

3.2 在 Linux 中创建 jenkins 目录
# mkdir /usr/local/jenkins

3.3 进入到创建好的 jenkins 目录中,使用宝塔将下载好的 rpm 包上传上去。

3.4 解压。
# rpm -ivh jenkins-2.346-1.1.noarch.rpm

3.5 配置 jenkins 中的 java 路径。
3.5.1 先查看 java 的绝对路径
# which java

把路径复制一下。
3.5.2 修改/etc/init.d/jenkins 文件 ,配置 jdk 安装路径。
# vim /etc/init.d/jenkins
找到"candidates",将默认的/usr/bin/java 改成刚刚复制的 java 命令的绝对路径。

保存并退出。
3.5.3 修改/etc/sysconfig/jenkins 文件。
将 JENKINS_USER="jenkins"改成 JENKINS_USER="root";
将 JENKINS_PORT="8080"改成 JENKINS_PORT="8772";不必非改成 8772,只要是端口号不冲突就行。
保存并退出。
3.5.4 重新加载配置文件。
# systemctl daemon-reload

3.6 启动 jenkins 服务
# systemctl start jenkins

3.7 查看 jenkins 服务状态
# service jenkins status
如果一切顺利的话,你会看到:

奈何事事怎么都会这么顺利,我在安装 jenkins 时卸载重装了不下 10 次,如果你在启动服务是也遇到了异常,那么你一定需要卸载 jenkins 的命令,然后在仔细的重新安装配置一遍。我为你准备好了 jenkins 卸载命令:
# rpm -e jenkins -- rpm 卸载
# rpm -ql jenkins --检查是否卸载成功
# find / -iname jenkins | xargs -n 1000 rm -rf --彻底删除残留文件

如果一切顺利的话这个时候你用浏览器输入 Linux 的 ip 地址加上刚刚的端口号应该就能访问到 jenkins 的界面了。

如果你像我一样,Linux 服务启动成功了,但是使用浏览器访问不到 jenkins 界面,那你可以考虑下是不是防火墙的问题。

3.8 把端口号加入到防火墙。
根据自己设置的端口号,运行如下命令:
# firewall-cmd --zone=public --add-port=8772/tcp --permanent
# firewall-cmd --reload

如果你像我一样,配置完防火墙后仍然访问不到 jenkins 的界面,那你可以考虑是不是没有配置服务器的安全组。
3.9 配置服务器的安全组。
3.9.1 在阿里云服务器的控制台中,点击"网络与安全"下的"安全组"。

3.9.2 点击安全组列表下的名称。
3.9.3 把自己设置的端口添加在"入方向"下;

这个时候我就能成功访问 jenkins 了,不知道你成功了没,如果你还没成功,那就在留言板描述出你的问题,大家讨论一下吧。

在 Linux 上安装 Git

安装 git 有两种方式,可以使用"yum -y install git"命令在线安装,也可以选择下载安装包离线安装,经过实践后我推荐使用离线安装方式,因为我起初为了方便使用在线安装后,发现后续 jenkins 配置 git 时总是无法连接远程仓库,然后我卸载 git 后选择离线安装,就没有 jenkins 配置 git 出错的问题了。
1.下载 git 的 tar.gz 包。git 的 tar.gz 包的下载地址
我选择的是v2.39.0 版本

2.在服务器/usr/local 下创建 git 目录。
# mkdir /usr/local/git

3.将安装包上传到 git 文件夹。

4.解压缩。
# tar -zxvf git-2.39.0.tar.gz

5.安装依赖(中途出现提示就输入:y)。
# yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker

6.编译源码。
# make prefix=/usr/local/git all

7.安装 git 至/usr/local。
# make prefix=/usr/local/git install

8.配置环境变量。
# vim /etc/profile
在最后添加:export PATH=$PATH:/usr/local/git/bin

9.配置文件立即生效。
# source /etc/profile

10.验证是否安装成功。
# git --version

在 Linux 上安装 Python

1.下载 Python 的.tgz 安装包,Python 的.tgz 安装包链接
我选择的是Python-3.11.1.tgz

2.在 Linux 上创建 Python 文件夹
注意,这不是最终 Python 的安装目录,后续我们会在这个目录下再创建一个 Python 的安装目录,如果迷糊的伙伴请继续往下看。
为了更清楚的展示安装步骤,我将运行命令的所处位置也展示给大家,希望大家不会迷糊。
[root@XyServerHostName ~]# mkdir /usr/local/python

3.进入创建好的文件夹,上传下载好的 Python 安装包

4.解压
[root@XyServerHostName python]# tar -zxvf Python-3.11.1.tgz
解压之后,会在当前目录下 (/usr/local/python) 多出来一个安装包解压后的目录 (/usr/local/python/Python-3.11.1)。

5.创建 Python 的安装目录
[root@XyServerHostName python]# mkdir python3.11.1

6.进入到 Python 安装包解压后的目录,然后正式安装 Python
[root@XyServerHostName ~]# cd /usr/local/python/Python-3.11.1/
[root@XyServerHostName Python-3.11.1]# ./configure --prefix=/usr/local/python/python3.11.1/
注意:--prefix 是指定安装目录,指向刚刚创建的安装目录 python3.11.1

7.编译
[root@XyServerHostName Python-3.11.1]# make && make install
这个过程会等待一段时间,我大概等待了 3 分钟。

8.配置环境变量
[root@XyServerHostName Python-3.11.1]# vim /etc/profile
在最后追加如下内容:
export PYTHON_HOME=/usr/local/python/python3.11.1
export PATH=${PYTHON_HOME}/bin:$PATH

使配置文件生效:
[root@XyServerHostName Python-3.11.1]# source /etc/profile
验证是否安装成功:
[root@XyServerHostName Python-3.11.1]# python3 -V
注意:是大写字母 V

9.修改 Linux 默认的 Python 版本
9.1 查看 Linux 上 Python 的默认版本:
# cd /usr/bin
# ll

9.2 删除软连接
[root@XyServerHostName bin]# rm -rf python

9.3 重新创建软连接
[root@XyServerHostName bin]# ln -s /usr/local/python/python3.11.1/bin/python3.11 /usr/bin/python

9.4 验证

至此在 Linux 上安装 Python 的步骤就演示完了,因为我在安装的时候有点绕,所以这一部分写的就比较啰嗦,希望小伙伴们可以顺利安装。

在 Linux 上安装 Allure

1.下载 allure 的.tgz 安装包。我选择的是 v2.20.1 版本allure-2.20.1.tgz 下载链接

2.在 Linux 上创建 allure 目录
# mkdir /usr/local/allure

3.进入到 allure 文件夹,上传下载好的安装包

4.解压缩
[root@XyServerHostName allure]# tar -zxvf allure-2.20.1.tgz

5.配置环境变量
[root@XyServerHostName allure]# vim /etc/profile
在文件底部添加:export PATH=$PATH:/usr/local/allure/allure-2.20.1/bin

保存并退出。

6.使配置文件立刻生效
[root@XyServerHostName allure]# source /etc/profile

7.验证是否安装成功
[root@XyServerHostName ~]# allure --version

在 jenkins 上配置工程

到此为止,我们已经成功在 Linux 上安装并配置好了所有配置 jenkins 工程的所需项,接下来就让我们开始配置 jenkins 工程吧。(如下内容并不是一蹴而就的,需要经过几轮配置的调整,这也是我从 0 到 1 搭建的心路历程,相信看完后会对你有所帮助)
1.初次登录并配置 jenkins
使用浏览器拼接 jenkins 地址:ip 地址:jenkins 端口号
首次进入后会有一些基础配置,操作很简单,根据提示一步一步进行就好了,在此我就选三处加以说明:
1.1 首次进入后,根据提示获取密码,将文件内容复制到输入框中点击"继续"。

1.2 可以根据需要创建登录用户,我选择使用 admin 登录。

1.3 在插件管理页面,我选择的是"安装推荐的插件"

2.创建工程
2.1 点击"新建 Item"按钮

2.2 填写工程名称、选择自由主题、点击确定

2.3 工程配置-General-填写描述

2.4 工程配置 - 源码管理 - 源码管理选择 git,填写 git 地址

2.5 工程配置 - 构建触发器

2.6 工程配置 - 构建

完成后点击保存。

3.安装插件
入口:

在"可选插件"tab 页中搜索插件-allure,然后选择插件后点击安装。

安装完所有需要用的插件后手动重启 jenkins 服务。
在端口号后面输入/restart,然后确定即可。

4.配置 jdk、git、allure
入口:

4.1 配置 jdk

4.2 配置 git

注意:如果"Path to Git executable"一栏写错,在工程配置的源码管理里会提示无法连接仓库错误。
(下面这张截图是如果"Path to Git executable"配置错误,在工程配置的源码管理里会提示无法连接仓库错误的错误示范)

4.3 配置 allure

注意:这里的安装目录就是 aller 的安装目录路径,不是 which allure 后显示的路径。

5.配置 allure 报告展示 (小心:这一步有坑)
5.1 回到工程配置,在"构建后操作"中选择"Allure Report"。
5.2 在 Path 一栏写入"./report"。
提示:坑就是这个 Path 的写法,别急,往后看。

6.立即构建,提示:"pytest:command not found"

解决办法:找到 pytest 安装目录所在位置,在 bin 目录下添加 pytest 软链接。

问题解决!

7.再次构建,pytest 执行成功,但提示:"allure-results does not exist"

查看 allure 测试报告,报告也是空的。

再次回到工程配置中的"构建后操作",(有道翻译了一下提示语,英语实在是硬伤呀,看来得背点单词了 。。)

根据提示,path 中需要写入的 allure 报告目录是相对于工作空间的相对路径。
可工作空间又是啥?工作空间在哪呢?后来我发现可以在构建历史的控制台输出中看到。

观察发现,如果工作空间是/var/lib/jenkins/workspace/pytest_requests_allure_v1,那么在工程配置中-"构建后操作"-"Allure Report"中的"Path"一栏直接填写"report"就行了。
注意,不是./report,也不是/var/lib/jenkins/workspace/pytest_requests_allure_v1/report。

将原先"Allure Report"中"Path"填写的"./report"改成"report"。

注意:"Allure Report"中"高级"里面的内容不需要修改。

至于工程配置中"构建"一栏中的命令中的测试报告路径写./report 或者直结写 report,都不影响成功构建。

具体原因不清楚,总之是我实践后得到的结论。

8.再次构建,哇,终于成功了!
(为了方便调试,所以我每次运行只选择了 4 条 case)

jenkins 赋能 - 使用邮箱发送测试报告

我并不满足,心想自动构建完要是能邮件通知我就好了。
1.1 获取邮箱授权码,这里我例举两种常用邮箱获取授权码的方式:
1.1.1 QQ 邮箱:

1.1.2 163 邮箱

1.2 安装插件:"Email Extension"

安装完插件后记得重启 jenkins 服务。

1.3 配置"Email Extension"插件
入口:系统管理 - 系统配置

设置内容详情见图片:

下滑到 Extended E-mail Notification

其中"Default Subject"内容为:【allure 测试报告】:$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!
其中"Default Content"内容为:

<!DOCTYPE html>    
<html>    
<head>    
<meta charset="UTF-8">    
<title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>    
</head>    

<body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4"    
    offset="0">    
    <table width="95%" cellpadding="0" cellspacing="0"  style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">    
        <tr>    
            本邮件由系统自动发出,无需回复!<br/>            
            各位同事,大家好,以下为${PROJECT_NAME }项目构建信息</br> 
            <td><font color="#CC0000">构建结果 - ${BUILD_STATUS}</font></td>   
        </tr>    
        <tr>    
            <td><br />    
            <b><font color="#0B610B">构建信息</font></b>    
            <hr size="2" width="100%" align="center" /></td>    
        </tr>    
        <tr>    
            <td>    
                <ul>    
                    <li>项目名称 : ${PROJECT_NAME}</li>    
                    <li>构建编号 : 第${BUILD_NUMBER}次构建</li>    
                    <li>触发原因: ${CAUSE}</li>    
                    <li>构建状态: ${BUILD_STATUS}</li>    
                    <li>构建日志: <a href="${BUILD_URL}console">${BUILD_URL}console</a></li>    
                    <li>构建  Url : <a href="${BUILD_URL}">${BUILD_URL}</a></li>    
                    <li>工作目录 : <a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
                    <li>项目  Url : <a href="${PROJECT_URL}">${PROJECT_URL}</a></li>    
                    <li>allure报告Url :<a href="${PROJECT_URL}${BUILD_NUMBER}/allure">${PROJECT_URL}allure</a></li> 
                </ul>    

<h4><font color="#0B610B">失败用例</font></h4>
<hr size="2" width="100%" />
$FAILED_TESTS<br/>

<h4><font color="#0B610B">最近提交(#$GIT_REVISION)</font></h4>
<hr size="2" width="100%" />
<ul>
${CHANGES_SINCE_LAST_SUCCESS, reverse=true, format="%c", changesFormat="<li>%d [%a] %m</li>"}
</ul>
详细提交: <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a><br/>

            </td>    
        </tr>    
    </table>    
</body>    
</html>

1.4 工程配置,增加"构建后操作"

其中只需要将"Content Type"一栏切换成"HTML(text/html)"即可,其他内容默认就好。

随后再次构建工程,绑定收件人的邮箱就会收到构建报告了!

jenkins 赋能 - 优化测试报告内容

我并不满足,心想报告要是能更加明显的告诉我执行结果就好了。
根据以上配置,收件人收到的邮件大致是这样的:

想必各位小伙伴们也会想我一样更青睐 pytest 运行完成后给出的测试总结吧。如果遇到问题,才会想点击查看对应的报告或日志吧。

让我们行动起来。(这部分内容是借鉴 CSDN 上名为"上海 - 悠悠"发布的一篇相关文章,我实践后效果很不错,故而分享给各位)

1 第一步先拿到 pytest 运行的测试结果,通过 pytest_terminal_summary 这个 hook 函数。
在项目根目录 conftest.py 文件下写如下代码。

def pytest_terminal_summary(terminalreporter, exitstatus, config):
    '''收集测试结果'''
    # print(terminalreporter.stats)
    total = terminalreporter._numcollected
    passed = len([i for i in terminalreporter.stats.get('passed', []) if i.when != 'teardown'])
    failed = len([i for i in terminalreporter.stats.get('failed', []) if i.when != 'teardown'])
    error = len([i for i in terminalreporter.stats.get('error', []) if i.when != 'teardown'])
    skipped = len([i for i in terminalreporter.stats.get('skipped', []) if i.when != 'teardown'])
    successful = len(terminalreporter.stats.get('passed', [])) / terminalreporter._numcollected * 100
    # terminalreporter._sessionstarttime 会话开始时间
    duration = time.time() - terminalreporter._sessionstarttime
    print('total times: %.2f' % duration, 'seconds')

    with open("result.txt", "w") as fp:
        fp.write("TOTAL=%s" % total + "\n")
        fp.write("PASSED=%s" % passed + "\n")
        fp.write("FAILED=%s" % failed + "\n")
        fp.write("ERROR=%s" % error + "\n")
        fp.write("SKIPPED=%s" % skipped + "\n")
        fp.write("SUCCESSFUL=%.2f%%" % successful + "\n")
        fp.write("TOTAL_TIMES=%.2fs" % duration)

2 在 jenkins 中安装插件:"Environment Injector"
说明:
jenkins 在构建 job 的时候,可以自己添加一些环境变量,在后续的构建步骤中引用环境变量,比如在测试报告中引用。
Environment Injector 插件可以在在构建步骤中添加环境变量。

Properties Content 自定义环境变量。
Properties File Path 引用本地文件作为环境变量。

安装成功后重启 jenkins 服务。

3 工程配置
在"构建"中点击"增加构建步骤",在下拉框中选择"注入环境变量"。

在"注入环境变量"的"属性文件路径"中写入"result.txt"。

到这一步前面执行完 pytest 生成的 result.txt 会把相关键值对添加到环境变量。

4 系统配置
修改系统管理 - 系统配置-"Extended E-mail Notification"中"Default Content"的内容,在原有的 html 中加入插入如下代码:

<tr>      
               <p>总数:${TOTAL} </br> 
                      成功:${PASSED}  </br> 
                      失败:${FAILED} </br> 
                      跳过:${SKIPPED}</p>
                      异常:${ERROR}  </br> 
               <p>运行成功率:${SUCCESSFUL}  运行时长:${TOTAL_TIMES}</p>
</tr>  

注意,有一个潜在的问题:
如果在构建执行 shell 的时候,退出代码为 0,也就是构建成功,那是没有问题的;
如果在构建执行 shell 的时候,退出代码为 1,也就是构建失败,那么后面的 Inject environment variables 这一步就不会执行了,导致后面的环境变量拿不到;
解决办法:
在执行 shell 的时候,脚本执行后会有个 exit code ,状态为 0 和 1 ,0 是表示代码执行成功,1 表示执行失败。
jenkins 在构建脚本可以认为 1 是不稳定的构建,于是设置为构建不稳定时的退出码:1
再次配置工程配置:

5 再次构建,效果如下:

这回就清晰多了,如果发现有异常再打开邮件查看相应报告。

总结

以上就是我在服务器的 Linux 操作系统中搭建 jenkins 的一系列过程。文章中你觉着啰嗦的地方就是我当时头最大的地方,写的详细点只希望小伙伴们在实践过程中顺利一些。整篇文章并不是从 0 开始一步到位直接写到自定义邮件内容的,而是描述了我搭建时走的每一步,写了一些踩坑和爬坑的过程,只是希望小伙伴在实践过程中遇到类似的问题后可以从这篇文章中感同身受一下,毕竟事事不会一帆风顺,也许你会在 Linux 上安装很多次 jenkins,也许你会搭建很多次 jenkins 工程,但只要坚持下去,终会成功的。
通过整整 52 次构建终于把 jenkins 调通了,感谢自己没有放弃,感谢在百度上被我搜到的众多资料,在这些虚虚实实的资料中辗转腾挪是真不容易呀,嘿嘿。

共收到 14 条回复 时间 点赞
耿晓 接口测试 - 从 0 不到 1 的心路历程 (二) 中提及了此贴 12月25日 19:24

2.4 工程配置 - 源码管理 - 源码管理选择 git,填写 git 地址 ----------请问大佬,这一步的 git 地址是在哪里获取的啊

回复

我把测试脚本上传到了 git 上,git 上就能看到地址,比如我的:

在线求大佬解答:我在部署完毕后一直服务启动失败,Jenkins 里面的 Java 环境也配置了,防火墙也关了,还没启动成功

查看 Jenkins 状态:

耿晓 #11 · 2023年02月03日 Author

不好意思,最近有点忙,回复不及时,方便的话加个 V 讨论下:GXY1162031010,不一定能解决,但我尽力帮你搞搞明白。

改为 docker 搭建 jenkins 会省事很多

作者真的很棒,难得在 testhome 看到接地气的作者😂 ,跟我们普通测试很贴近,看着你一步步成长,感觉身临其境,你做过的我也做过

我想请教一下 对于发送测试报告到邮箱 我是一步步按照你的做的 但是构建了好几次还是不行😩 我想问对于 smtp 端口号必须写成 587 吗 我不知道什么原理 我的默认是 25 但是它能够随意修改 还有就是不知道作者了不了解将测试结果利用群机器人发送到群里的 对于发送到邮箱和用机器人发送到群里我都尝试了好久 一直失败 先谢过

在实践中一步步学习成长,点赞

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册