持续集成的回归测试框架
来源:互联网 发布:股城模拟炒股软件 编辑:程序博客网 时间:2024/06/13 21:45
- 系统框图
- 目录结构
- 代码
- 第一步: 多线程运行测试用例,保存测试结果到数据库/result/regression.db:
脚本执行命令:python readXml.py -t 4 config.txt参数-t 4:4个线程运行
; 配置文件[config]; 记录测试向量的xml文件run_xml=E:/python/regression/testcases/test1.xml; 运行目录run_dir=E:/python/regression/resultreadXml.py:解析xml文件,获取测试用例的列表
#-*- coding:utf-8 -*-import os,sysimport timeimport getoptimport xml.etree.ElementTree as ETfrom sqlAPI import SQLTestimport configparserfrom readCase import runCaseByXmlfrom multiprocessing import Lockfrom multiprocessing.pool import ThreadPooldef runTestByXml(xml_file,run_dir):'''read the xml file and check each testcases'''# 读取xml文件xml_root = ET.parse(xml_file)xml = xml_root.getroot()# 创建数据库db_file_path = os.path.join(run_dir,'regression.db')with open(db_file_path,'w'):db = SQLTest(path = db_file_path)# 创建信息表infocreate_info_sql = '''create table if not exists 'info' (\'id' integer(16) NOT NULL,\'version' nvarchar(64) NOT NULL,\'begin_time' float NOT NULL,\'end_time' float NOT NULL,\'tables' nvarchar(128) DEFAULT NULL,\'test_group' nvarchar(64) NOT NULL,\PRIMARY KEY('id')\)'''db.createTable(create_info_sql)insert_sql = '''INSERT INTO info values (?,?,?,?,?,?)'''info_id = db.rowCount('info') + 1date = time.strftime('%y%m%d',time.localtime(time.time()))data = [(info_id,'v_01',time.time(),'','','regression1')]
db.insert(insert_sql,data)# 信息统计num_fail = 0 #失败的测试用例total_cases = 0 #测试用例的总数# 迭代groupgroup_list = xml.find('common').find('groups').text.split(',')group_list = [item.strip() for item in group_list if item.strip()]tables = []tables_name = ''lock = Lock()for group in group_list:# 在SqlDB中创建表group_name = xml.find(group).find('name').text# 创建表单group_nameif group_name == 'info':print('group name cannot be "info"')continuecreate_table_sql = '''create table if not exists '%s' ('id' integer(16) NOT NULL,'case_name' nvarchar(64) NOT NULL,'begin_time' float NOT NULL,'end_time' float NOT NULL,'loss_packet' float(128) DEFAULT 0,'note' nvarchar(64) DEFAULT NULL,PRIMARY KEY('id'))''' % group_namedb.createTable(create_table_sql)# 取得本组所有的测试向量test_lists = []group_node = xml.find(group)if (group_node is None):print('Info : group {} not found'.fromat(group))for test_list in group_node.findall('file'):test_lists.append(test_list.text)# group的测试向量统计num_cases = len(test_lists)total_cases += num_cases# close db, because db object must be in same threaddb.closedb()# 放入线程池,多线程运行每一个测试向量print('Using multiprocess ...')pool = ThreadPool(num_thread)raw_results = [pool.apply_async(runCaseByXml,(i+1,num_cases,test_lists[i],\db_file_path,group_name,run_dir,lock)) for i in range(num_cases)]results = [r.get() for r in raw_results]pool.close()pool.join()
db = SQLTest(path = db_file_path)
#记录表明到数据库tables
if tables == []:
tables_name = group_name
elif group_name not in tables:
tables_name += ',{}'.format(group_name)
#运行结束时间
update_sql = 'UPDATE info SET end_time=? WHERE ID=?'
data = [(time.time(),info_id)]
db.updata(update_sql,data)
#数据表
update_sql = 'UPDATE info SET tables=? WHERE ID=?'
data = [(tables_name,info_id)]
db.updata(update_sql,data)
#测试Fail统计print('{} total, {} failed'.format(total_cases,num_fail))#main函数if __name__ == '__main__':# 线程数量num_thread = 1try:opts,argv = getopt.getopt(sys.argv[1:],'t:')except getopt.GetoptError as err:print(err)sys.exit(1)for o,a in opts:if o == '-t':num_thread = int(a)# 解析配置文件config_file = argv[0]if os.path.isfile(config_file):# configparser解析配置文件config = configparser.ConfigParser()config.read(config_file)# 如果参数多,建议封装成类xml_file = config['config']['run_xml']run_dir = config['config']['run_dir']runTestByXml(xml_file,run_dir)else:print('file {} not found'.format(config_file))
readCase.py:多线程调用软件可执行程序,执行测试用例,保存测试结果到数据库。
impr_loss_packet = re.match('.*?丢失\s=\s(\d+)\s.*',line).group(1)#-*- coding:utf-8 -*-import os,sysimport timeimport os,sysimport reimport shutilimport xml.etree.ElementTree as ETfrom subprocess import Popen,PIPE,STDOUT,TimeoutExpiredfrom sqlAPI import SQLTestdef runCaseByXml(i,num_cases,xml_file,db_file_path,table_name,run_dir,lock):'''read the xml file and excute testcase@parameter i:本组测试向量的第i个@parameter num_cases:本组测试向量的总数@parameter test_list:测试向量@parameter db_file_path:数据库的文件路径@parameter table_name:数据库的表名称@parameter run_dir:测试向量的执行路径@parameter lock:多线程的lock'''print('{} of {} ***************'.format(i,num_cases))#xml file是否存在if not os.path.isfile(xml_file):print('File {} not found'.format(xml_file))return 1#读取xml文件内容xml_root = ET.parse(xml_file)xml = xml_root.getroot()#测试用例的idcase_id = int(xml.find('id').text)case_name = xml.find('name').textip = xml.find('ip').textping_nums = xml.find('nums').textloss_packet = xml.find('loss').text#清空工作目录work_dir = ''.join([run_dir,'/reg',str(i)])if os.path.isdir(work_dir):shutil.rmtree(work_dir)os.mkdir(work_dir)#创建数据库dbdb = SQLTest(path = db_file_path)#创建运行测试用例的tclrun_tcl = ''.join([work_dir,'/MyScript.bat'])with open(run_tcl,'w') as fp:fp.write('ping {} -n {}'.format(ip,ping_nums))TIMEOUT_EXPIRED = 180 #单位:秒flag_timeout = False #超时标识begin_time = time.time()#执行tcltry:p = Popen([run_tcl],stdout=PIPE,stderr=PIPE,cwd=work_dir)#等待子进程结束stdout_data,stderr_data = p.communicate(timeout=TIMEOUT_EXPIRED) #超时退出except TimeoutExpired:p.kill()flag_timeout = Trueprint('Info: run {} TimeoutExpired'.format(xml_file))end_time = time.time()#系统输出流stdout的编码方式stdout_encode = sys.stdout.encoding#写stdout_data到logfilestdout_log = os.path.join(work_dir,'run.log')with open(stdout_log,'w',encoding='utf-8') as fp:fp.write(stdout_data.decode(stdout_encode))#解析log文件with open(stdout_log,'r',encoding='utf-8') as fp:for line in fp:if '丢失' in line:
insert_sql = 'INSERT INTO {} values(?,?,?,?,?,?)'.format(table_name)data = [(case_id,case_name,begin_time,end_time,impr_loss_packet,'')]with lock:db.insert(insert_sql,data)return 0 if (int(impr_loss_packet) <= int(loss_packet)) else 1#自测if __name__ == '__main__':passsqlAPI.py:数据库接口
代码参考以前的博客《python脚本sqlite3模块的应用》
http://blog.csdn.net/zhanghs11/article/details/51338112
- 第二步:生成测试报告/result/regression.html
脚本执行命令:python dbHtml.py db_file
dbHtml.py:生成Html报告
#-*- coding: utf-8 -*-
from pyh import *
from sqlAPI import SQLTest
import os,sys
import time
class ToHTML:
def __init__(self,project = 'TEST', version = 'v1.0'):
self.page = PyH('%s 测试报告' % project)
self.project = project
self.path = ''
self.version = version
self.start_time = time.time()
self.end_time = ''
self.group = ''
#设置版本信息
def setVersion(self,version=None):
self.version = version
def setPath(self,path=None):
self.path = path
def setGroup(self,group=None):
self.group = group
def setStartTime(self,start_time=None):
if start_time is None:
self.start_time = time.time()
else:
self.start_time = start_time
def setEndTime(self,end_time):
if end_time is None:
self.end_time = time.time()
else:
self.end_time = end_time
#设置表格的格式
def tablecss(self, table = None, width = '600'):
table.attributes['cellSpacing'] = 1
table.attributes['cellPadding'] = 1
table.attributes['border'] = 1
table.attributes['borderColor'] = 'green'
table.attributes['width'] = 'width'
def tr_title_css(self, tr = None, color = '#B0C4DE'):
tr.attributes['bgcolor'] = color
#版本信息
def genVersionInfo(self):
self.page << div(b('版本信息'), id = 'mydiv')
table_info = self.page << table()
#表格宽度
self.tablecss(table_info,'50%')
version_tr_info = table_info << tr()
self.tr_title_css(version_tr_info,'#5566CC')
version_td_info = version_tr_info<<td('测试代码')
value_tr_info = table_info << tr()
td_dev = value_tr_info << td('版本:')
td_dev << self.version
td_dev << br()
td_dev << '组别:'
td_dev << self.group
td_dev << br()
td_dev << '开始:'
td_dev << time.strftime('%y.%m.%d %X',time.localtime(self.start_time))
td_dev << br()
self.page << br()
def genReport(self,filename='reg.html'):
self.page << '结束'
try:
self.page << time.strftime('%y.%m.%d %X',time.localtime(self.end_time))
except:
self.page << 'unfinished'
self.page << br()
self.page.printOut(file_name)
def setcontent(self,unit):
value_tr_unit = self.tableGroup << tr()
for unitOne in unit:
value_tr_unit << td('%s' % unitOne)
def genReport(self, filename = 'report.html'):
print(filename)
self.page << '结束:'
try:
self.page << 'finished'
except:
self.page << 'unfinished'
self.page << br()
self.page.printOut(filename)
def dbToHtml(pri_obj,db,file_path):
#div 版本信息
sql = 'SELECT * FROM info'
table_rows = db.fetchAll(sql)
for e in range(len(table_rows)):
pri_obj.setVersion(table_rows[e][1])
pri_obj.setStartTime(table_rows[e][2])
pri_obj.setEndTime(table_rows[e][3])
tables = table_rows[e][4]
pri_obj.setGroup(table_rows[e][5])
pri_obj.genVersionInfo()
prj_obj.genReport(os.path.join(file_path,'regression.html'))
# self test
if __name__ == '__main__':
prj_obj = ToHTML('TEST')
# 命令提示
if len(sys.argv) < 2:
print('Info: command python dbHtml.py dbfile ...')
sys.exit(0)
db_file = sys.argv[1]
file_dir,file_name = os.path.split(db_file)
#打开数据库
db = SQLTest(path = db_file)
if os.path.isfile(db_file):
dbToHtml(prj_obj,db,file_dir)
pass
else:
print('file {} not found'.format(db_file))
生成的报告如下图所示:(报告不完整,后续完善)
- 持续集成的回归测试框架
- jenkins+ant+jmeter接口自动化的持续集成测试框架
- jenkins+ant+jmeter接口自动化的持续集成测试框架
- 第4代白盒测试方法实践之“VcTester持续集成框架的应用价值”
- 基于jenkins的持续集成测试
- Agitar的持续集成和测试
- 基于jenkins持续集成测试的意义
- 基于Jmeter+Maven+Jenkins持续集成接口测试框架
- 持续集成框架pipeline
- Selenium 实现WEB测试持续回归测试
- 单体测试、集成测试、回归测试、系统测试、验收测试等的比较
- 单体测试、集成测试、回归测试、系统测试、验收测试等的比较
- 图书摘录:持续集成意味着持续测试
- 内部分享---接口测试和py接口测试持续集成框架instaAPI
- 持续集成与测试自动化
- 持续集成与测试自动化
- 持续集成与测试自动化
- 持续集成与测试自动化
- MySql+PHP实现分页
- 如何选择文件系统:EXT4、Btrfs 和 XFS
- 在一个无序数组中找到第K个最小或者最大的元素
- 我不要的彷徨
- 数据结构课程设计
- 持续集成的回归测试框架
- javascript中 n--与 --n的区别
- 关于百度地图API定位问题
- 阿里云云服务器Centos7部署JDK8+Nginx+Tomcat8+Mysql5.7
- Unreal Engine 4 —— Ghost Mesh Plugin的开发日志
- c++测试题
- 【ESP8266】基于ESP8266的MicroPython入门笔记
- JavaScript 计算字符串所占的像素个数
- 第47篇白板修复之铅笔选择三种粗细(一)