Jenkins + TestNG 实现自助式自动化测试平台
摘要:
本文介绍了如何使用 Jenkins 和 TestNG 实现满足复杂测试需求的”自助式”自动化测试平台。该方案以 Jenkins 作为平台的基础,结合功能强大的插件及系统配置,部署基于 TestNG 的自动化测试包,并提供了友好的 Web 访问界面。项目成员可以在任何时间和地点,通过浏览器访问该平台,而且可以按照不同需求选择测试环境、测试集、测试用例,并提交自动化测试请求,达到真正的“自助式”自动化测试。该平台它可以极大地提高开发和测试团队自动化脚本的使用效率和便捷性。
目录:
- 提出需求
- 方案设计
- 编码
- 测试
正文:
一. 提出需求
测试部开发一套自己的质量中心,主要用于缺陷统计、接口自动化测试、APP自动化测试、在线监控等,在接口自动化测试和APP自动化测试过程中,我们需要实现,用户选择不同的测试集合,集合中包含哪些测试用例,TestNG会自己去执行不同的测试用例,做到根据用户不同的输入做出不同的响应。
二. 方案设计
- 质量中心(WEB)提供测试用例管理和测试集合管理,创建测试任务,关联测试集合,测试集合又关联测试用例
- 质量中心(WEB)将创建的测试任务相应的调用Jenkins任务,并把相应的需要传递的参数传递过去
- Jenkins任务启动,先根据传进来的测试任务编号,找到相应的测试集合和测试用例,并用Python脚本生成相应的TestNG XML文件,其中XML文件定义了需要执行的测试用例,这样子就做到了,根据用户不同的输入做出不同的相应
- Jenkins执行Python生成的TestNG XML文档
- TestNG在Jenkins上执行后会在surefine-reports文件夹下面生成emailable-report.html测试报告
- Jenkins任务执行完再次调用Python脚本,将生成的emailable-report.html报告写入MySQL存储起来,提供给质量中心(WEB)查看
三. 编码
3.1 质量中心->APP自动化测试 数据库设计
app_elements:存储app页面控件,如Android的resource id,iOS的xpath
app_execute: 存储支持执行结果,测试报告、测试结果等
app_mobile: 存储测试机型的相关信息
app_modules: 存储测试APP中包含的模块,分层的思想,方便管理
app_platform: 存储测试APP,支持多个APP
app_suitecase: 存储测试集合与测试用例的关系,一个测试用例对应多个测试集合
app_testcase:存储测试用例
app_testjob:存储测试任务,关联相应的Jenkins路径,直接多地执行
app_testsuite:存储测试集合
3.2 Jenkins参数配置
TestPlatform: 测试平台,是Android还是iOS
TestDevice: 测试设备,Android需要传入udid,iOS不需要
TestEnv: 测试环境,qa还是live
TestJobId: 测试任务编号,通过这个任务编号可以MySQL查询到关联的测试集合以及测试集合中的测试用例
TestExecuteId: 执行任务编号,传入Python脚本,讲生成的测试报告emailable-report.html存放相应的位置
3.3 Python文件生成TestNG XML
# -*- coding:utf-8 -*-
import os
import MySQLdb
import sys
import xml.dom.minidom
# 外部传入的测试任务编号
test_job_id = sys.argv[1]
# 连接db
def connect_db(db):
db = MySQLdb.connect(host="10.9.8.20",
port=3306,
user="***",
passwd="***",
db=db,
charset="utf8")
return db
# 请求mysql获取数据
def get_data(db, sql):
conn = connect_db(db)
cur = conn.cursor()
cur.execute(sql)
data = cur.fetchall()
cur.close()
conn.commit()
conn.close()
return data
# 判断文件是否存在,如果不存在立即创建,如果存在,则立即删除,重新覆盖
def xml_exist():
file_name = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "/resources/YouYu_Stock.xml"
if os.path.exists(file_name):
os.remove(file_name)
f = open(file_name, "w")
f.close()
return file_name
# 获取测试用例英文名
def get_case_name():
suite_id = get_data("app", "select suite_id from app_testjob where id=" + test_job_id)[0][0]
case_id = get_data("app", "select case_id from app_suitecase where suite_id=" + str(suite_id))
list_case_name = []
for i in xrange(0, len(case_id)):
case_name = get_data("app", "select ename from app_testcase where id=" + str(case_id[i][0]))[0][0]
list_case_name.append(case_name)
return list_case_name
def main():
file_name = xml_exist()
case_names = get_case_name()
doc = xml.dom.minidom.Document()
root = doc.createElement("suite")
root.setAttribute("name", "TestSuite")
root.setAttribute("parallel", "false")
doc.appendChild(root)
# 添加parameter
nodeManager = doc.createElement("parameter")
nodeManager.setAttribute("name", "url")
nodeManager.setAttribute("value", "127.0.0.1")
root.appendChild(nodeManager)
nodeManager = doc.createElement("parameter")
nodeManager.setAttribute("name", "port")
nodeManager.setAttribute("value", "4727")
root.appendChild(nodeManager)
nodeManager = doc.createElement("parameter")
nodeManager.setAttribute("name", "device")
nodeManager.setAttribute("value", "${TestPlatform}")
root.appendChild(nodeManager)
nodeManager = doc.createElement("parameter")
nodeManager.setAttribute("name", "udid")
nodeManager.setAttribute("value", "${TestDevice}")
root.appendChild(nodeManager)
nodeManager = doc.createElement("parameter")
nodeManager.setAttribute("name", "env")
nodeManager.setAttribute("value", "${TestEnv}")
root.appendChild(nodeManager)
# 添加test case
for i in xrange(0, len(case_names)):
print case_names[i]
node_test = doc.createElement("test")
node_test.setAttribute("name", case_names[i])
node_classes = doc.createElement("classes")
node_test.appendChild(node_classes)
node_class = doc.createElement("class")
node_class.setAttribute("name", "com.youyu.stock.automation.mobile.testcase.registerAndLogin.RegisterAndLoginTestCase")
node_classes.appendChild(node_class)
node_methods = doc.createElement("methods")
node_class.appendChild(node_methods)
node_include = doc.createElement("include")
node_include.setAttribute("name", case_names[i])
node_methods.appendChild(node_include)
root.appendChild(node_test)
f = file(file_name, "w")
doc.writexml(f, " ", " ", " ", "utf-8")
f.close()
if __name__ == '__main__':
main()
3.4 Jenkins配置与执行Maven TestNG
Maven pom.xml定义:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<systemPropertyVariables>
<testEnvironment>${TestDevice}</testEnvironment>
<testEnvironment>${TestEnv}</testEnvironment>
<testEnvironment>${TestJobId}</testEnvironment>
</systemPropertyVariables>
<suiteXmlFiles>
<suiteXmlFile>${automationFile}</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
3.5 生成的TestNG XML文件,例如:
3.6 生成的emailable-report.html存储在MySQL中
# -*- coding:utf-8 -*-
import os
import sys
import MySQLdb
from bs4 import BeautifulSoup
# 外部传入执行任务时参数的编号
execute_id = sys.argv[1]
# 连接db
def connect_db(db):
db = MySQLdb.connect(host="10.9.8.20",
port=3306,
user="***",
passwd="***",
db=db,
charset="utf8")
return db
# 请求mysql获取数据
def get_data(db, sql):
conn = connect_db(db)
cur = conn.cursor()
cur.execute(sql)
data = cur.fetchall()
cur.close()
conn.commit()
conn.close()
return data
def write_result():
file_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "/target/surefire-reports/emailable-report.html"
f = open(file_path, "r")
html = f.read()
# 测试结果写入MySQL
soup = BeautifulSoup(html)
PassCase = int(soup.find_all("th", class_="num")[0].get_text())
FailCase = int(soup.find_all("th", class_="num")[2].get_text())
# 测试报告写入MySQL
html = MySQLdb.escape_string(html)
get_data("app", "update app_execute set test_result="%s", test_report="%s" where id=%s" % (str(PassCase) + "/" + str(PassCase+FailCase), html, str(execute_id)))
if __name__ == '__main__':
write_result()
四. 测试
4.1 质量平台
总结:
为了实习根据用户不同的输入做出不同的相应,期间尝试方案如下:
- TestNG @Test enabled=false或者true 失败,失败原因:enabled传入值必须是定值
- TestNG 自动-testname可以根据传入不同的test name选择执行不同的测试用例,失败,依赖包太多,Maven项目下载的包不能通过classpath方式安装到本地classpath,maven进行了一层封装,maven的dependences
- Maven 执行命令行mvn clean test将TestNG参数传递进去,失败,失败原因:Maven -Dtest仅仅选择需要执行的,并不能知道TestNG中的参数
Jenkins + TestNG 实现自助式自动化测试平台相关推荐
- 集成 Jenkins 和 TestNG 实现自助式自动化测试平台
背景介绍 在软件业十分成熟的今天,敏捷(Agile)开发在业界日益流行,而面临的挑战也日益增多,不断变化的用户需求.缩短的开发周期.频繁的部署上线.复杂的产品架构和团队组织,如何继续保证软件的质量是一 ...
- ios jenkins配置_Jenkins + TestNG 实现自助式自动化测试平台
摘要: 本文介绍了如何使用 Jenkins 和 TestNG 实现满足复杂测试需求的"自助式"自动化测试平台.该方案以 Jenkins 作为平台的基础,结合功能强大的插件及系统配置 ...
- jenkins+calabash搭建Android自动化测试平台
关于环境搭建过程参考 jenkins+appium+calabash测试框架搭建 1.假设环境都已经搭好,现在进入jenkins新建一个job. 配置SVN: 如果SVN需要授权,添加账号和密码. 2 ...
- 搭建自动化测试平台(selenium+testng+maven+svn+Jenkins)【转自galen2016】
http://blog.csdn.net/galen2016/article/details/76790591 首先创建一个Maven项目 1.打开eclipse,选择File-new-Other ...
- Cucumber+Rest Assured快速搭建api自动化测试平台
转载:http://www.jianshu.com/p/6249f9a9e9c4 什么是Cucumber?什么是BDD?这里不细讲,不懂的直接查看官方:https://cucumber.io/ 什么是 ...
- 接口自动化测试平台Lego ------ 美团接口自动化测试超全实践【3000字长文】
一.概述 1.1 接口自动化概述 众所周知,接口自动化测试有着如下特点: 低投入,高产出. 比较容易实现自动化. 和UI自动化测试相比更加稳定. 如何做好一个接口自动化测试项目呢? 我认为,一个&qu ...
- python自动化测试平台github_GitHub - DangKaio/FXTest: 接口自动化测试平台——python+flask版,支持http协议...
FXTest测试平台 flask + Python3 实现的API自动化测试平台. 下面有介绍python flask部署相关的文章链接.为自己部署的记录文章 前后端开始进行分离,通过接口进行交互 敬 ...
- 自动化测试平台搭建从零开始
从上家公司离职后,有段空窗期,计划系统提升下自己的技术能力,想着做一个基于python的自动化测试平台(B/S架构的WEB测试平台),在这过程中逐渐学习python的使用,希望能够坚持下去吧. 之前虽 ...
- 自动化测试平台及可视化界面
从Web UI 测试.API 测试.数据库测试.接口测试.单元测试.性能测试等方面,为大家整理了 Gitee 上优秀的自动化测试开源项目,希望能给大家带来一点帮助. 一.Web UI 自动化测试 1. ...
最新文章
- python 编程入门-实验一 Python程序设计入门
- JavaScript(循环)
- JZOJ 3742. 【TJOI2014】上升子序列
- Easyui 异步树直接所有展开
- 在nodejs中创建cluster
- mysql 视图 教程_MySQL视图简介及基本操作教程
- where 泛型类型约束 default 关键字
- [高光谱] GitHub开源项目Hyperspectral-Classification的解析
- Srping事务的传播行为和隔离级别
- 数据库系统load飙高问题解决思路(转)
- 39个SEO经典案例
- android个人日记本论文,个人心情日记本的设计与实现论文.doc
- 【8】同步vscode配置和插件【导入导出】、再也不用担心换电脑重新安装插件了
- cisco链路聚合 不均衡_Cisco PT 案例七:配置链路聚合 / 负载均衡
- c语言中 结构体对象,C语言中结构体详解
- 注射php,手工注射php学习
- PDC10与最后的恐慌者
- laravel-admin Base table or view not found: 1146 Table ‘hyzt.brands‘ doesn‘t exist (SQL: select coun
- 智慧公厕系统为管理方提供更丰富的管理手段
- Spring中使用Map、Set、List、数组、属性集合的注入方法配置文件