RT-Thread上使用utest+jenkins实现持续集成和自动化测试
随着模块越来越多,测试维护成本越来越高,实现自动化便提上日程,网上关于嵌入式软件的持续集成和自动化测试的资料较少,utest是RTThread自带的测试框架,也没有接入jenkins,也没有测试报告,所以很多地方需要自己再做处理。本文记录了笔者搭建测试框架中详细的实现过程、踩过的坑和解决方法以及一些思考。环境:RT-Thread、SCons、qemu、jenkins、utest。
看到一篇文章,后续工作可能会用到,转载并记录如下,原文链接:RT-Thread上使用utest+jenkins实现持续集成和自动化测试 - 掘金 (juejin.cn)
前情提要: 随着模块越来越多,测试维护成本越来越高,实现自动化便提上日程,网上关于嵌入式软件的持续集成和自动化测试的资料较少,utest是RTThread自带的测试框架,也没有接入jenkins,也没有测试报告,所以很多地方需要自己再做处理。本文记录了笔者搭建测试框架中详细的实现过程、踩过的坑和解决方法以及一些思考。
环境:RT-Thread、SCons、qemu、jenkins、utest
1. 使用jenkins实现持续集成
持续集成( Continuous integration ,简称 CI)指的是,频繁地将代码集成到主干。
持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前必须通过自动化测试。只要有一个测试用例失败,就不能集成。
先新建一个jenkins的任务,再一个个解决问题
新建任务
构建一个自由风格的软件项目(或者可以拷贝一个scm的项目)
general和源码管理可以根据实际情况配置
构建触发器可选择定时构建或者gitlab/gerrit来触发,或者多选也可以
上图示意为周一到周五22:00定时构建
接下来build step和构建后操作就是重头戏了
build step
选择执行shell脚本
脚本内容分为几步:
- 获取开发代码
- 获取测试代码,以及mock服务
- 编译运行
- 生成html格式的测试结果报告
构建后操作
- 发布HTML reports
- 发送邮件通知
2. 问题解决
问题一:怎样执行用例
我们平时都是在整个系统编译运行之后,进入msh命令行界面进行交互,输入“utest_list","utest_run"分别查看测试用例和运行测试用例
第一个办法的灵感来源于rtthread的源码,里面找到一个utest自动化机器人,是通过python函数将命令传入
最终采用的解决方法:在/board/vexpress/arm-a9/applications/main.c中加上
#include <msh.h>
#include <finsh.h> //main函数中加入:
msh_exec("utest_run",11);
问题二:怎样结束进程
utest执行完,结束qemu是用的ctrl+A,然后再输入X,这里怎么结束进程呢
是这个问题想了我一个下午,一直没有搜到怎样退出,后来想明白了,自己怎么能结束自己呢,必须得要从外部来实现,然后碰巧看到一篇帖子求助怎么退出qemu的,发现不知道Ctrl+A+X的小伙伴一直是杀进程的,灵光一闪,那这不就是我自动化需要的方案吗!
接着就是代码实现过程:总体逻辑就是,1.启动三个进程,A进程运行,B进程等待,C进程判断log内容,2. A进程运行并将log重定向为log.txt,3.C进程判断log出现utest执行结束,便唤醒B线程来杀qemu进程
核心代码如下(仅展示方法,某些函数实现已隐去)
import threading
import time
import logging
import subprocess
import os
logging.basicConfig(format="%(asctime)s %(threadName)s %(thread)s %(message)s",level=logging.INFO)
event = threading.Event()
is_executing = False
def logrecorder():
logging.info("log: logrecorder start")
with open('utest_log.txt', 'r') as log_file:
while True:
flag = log_file.tell()
line = log_file.readline()
if not line:
time.sleep(1)
log_file.seek(flag)
else:
#print(line)
if line.find('[ utest ] finished') != -1:
logging.info("find finished")
event.set()
break
def test():
time.sleep(3)
event.set()
def run():
logging.info("log: run start")
os.system('')
logging.info("log: run finish")
def kill():
logging.info("log: kill thread start")
event.wait()
os.system('ps -aux | grep qemu | grep scmbuild | grep test-memblock-unit | awk \'{print $2}\' | xargs kill -9')
is_executing = False
if __name__=='__main__':
a = threading.Thread(name='run',target=run)
b = threading.Thread(name='kill',target=kill)
c = threading.Thread(name='logrecorder',target=logrecorder)
d = threading.Thread(name='test',target=test)
b.start()
a.start()
time.sleep(5)
c.start()
问题三:生成测试报告
怎样生成测试报告,一目了然
因为utest没有直接生成报告的功能,所以只能自己根据log来产生结果,而且utest有一个很大问题,就是其中某个测试套件中的某条case failed了,后面的case都会跳过,所以我们目前将统计的颗粒度就设为测试套件。通过python读取log,获取需要的数值,再传到html中显示,再把html文件作为jenkins的报告输出
部分代码:
from jinja2 import Environment, FileSystemLoader
import os
import time
def txt_read():
return totalcase, runcase, passcase, failcase, set(faillist)
def generate_html(body, current_time, result):
env = Environment(loader=FileSystemLoader('./'))
template = env.get_template('template.html')
with open("result.html", 'w+', encoding="UTF-8") as fout:
html_content = template.render(body=body, current_time = current_time, result=result)
fout.write(html_content)
def send_result():
totalcase, runcase, passcase, failcase,failname = txt_read()
if (runcase - passcase != failcase):
print("Maybe something is wrong")
body = []
if (failname):
result = {'ID': 1, 'total': totalcase, 'run': runcase, 'pass': passcase, 'fail':failcase, 'more' : failname}
else:
result = {'ID': 1, 'total': totalcase, 'run': runcase, 'pass': passcase, 'fail': failcase, 'more': "无"}
body.append(result)
current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
if(failcase == 0):
result = "pass"
else:
result = "fail"
generate_html(body, current_time, result)
if __name__ == '__main__':
txt_read()
send_result()
再自己写一个templete.html,每次调用python脚本即可根据templete.html生成对应的result.html,示例
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<html align = 'left'>
<h1>测试报告</h1>
<body>
<div id="table0" >
<table border= '0px ' width = "70%" cellspacing='1' cellpadding='3' align='left' bgcolor="black" >
<tr style="color:white; font-weight: bold;text-align:left; background-color:#777;">
<th>轮数</th>
<th>总用例数</th>
<th>执行</th>
<th>通过数</th>
<th>失败数</th>
</tr>
{% for item in body %}
<tr align='left' bgcolor="white">
<td>{{ item.ID }}</td>
<td>{{ item.total }}</td>
<td>{{ item.run }}</td>
<td>{{ item.pass }}</td>
<td>{{ item.fail }}</td>
</tr>
{% endfor %}
</table>
</div>
</body>
<body>
<div id="table1" class="hidden">
<table border="0" width = "70%" cellspacing='1' cellpadding='3' align='left' bgcolor="black" >
<tr style="color:white; font-weight: bold;text-align:left; background-color:#777;">
<th>测试用例</th>
<th>结果</th>
<th>备注</th>
</tr>
{% for name in failname %}
<tr align='left' bgcolor="white" >
<td>{{ name }}</td>
<td style = "color:FF0000"> Failed </td>
<td></td>
</tr>
{% endfor %}
</table>
</div>
</body>
问题四:邮件通知
在构建后的步骤中添加邮件报告,内容设置为html
在最下方点开
可以看到各种环境变量,能够直接用到我们这里的设置中
Project Recipient List:这里可以添加邮件地址,cc:地址可以抄送
因为我已经自己生成了测试报告,为了能把报告结合起来,采用了一下方式:
<!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">
<h3>以下是Jenkins自动发送的邮件,请勿回复!</h3>
<div>
<table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
<tr>
<th><br />
<h2>构建信息</h2>
</th>
</tr>
<tr>
<td>
<ul>
<li>项目名称 : ${PROJECT_NAME}</li><br />
<li>触发原因: ${CAUSE}</li><br />
<li>项目 Url : <a href="${PROJECT_URL}">${PROJECT_URL}</a></li><br />
<li>工作目录 : <a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li><br />
<li>测试报告 : <a href="${PROJECT_URL}HTML_20Report">${PROJECT_URL}HTML_20Report</a></li>
</ul>
</td>
</tr>
</table>
</div>
<div>
<table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
<tr>
<th><br />
<h2>测试报告</h2>
</th>
</tr>
<tr>
<td>
<div>${FILE ,path="/workspace/fw_autotest/resultBrief.html"}</div>
</td>
</tr>
</table>
</div>
</body>
</html>
问题五:报告优化
由于每个模块的开发和测试的需求不同,为了尽量能既一目了然又详细,所以在邮件里只是会展示结果,想要了解详细情况可以点击测试报告链接,在里面能够展示所有用例和log
点击测试报告的链接就会跳转到jenkins的html报告
其余问题:从安全性考虑,jenkins禁止了css和js的加载,所以格式会乱
解决方案:
更多推荐
所有评论(0)