Commit a225177f authored by xiao-hesheng's avatar xiao-hesheng
Browse files

修改case目录 添加data文件

parent 0c277885
项目结构:
自动化用例的工程目录
----common 存放公共方法
----air_case 存放用例case
----templates 存在模板报告
----report 存放case执行总报告及各用例报告
----log 存放case执行日志
----data 存放数据
runner.py case执行调度入口
autotest-airtest-web:
---common 存放公共方法
---air_case 存放用例case
---templates 存在模板报告
---report 存放case执行总报告及各用例报告
---log 存放case执行日志
---data 存放数据
---runner.py case执行调度入口
---distribute.py 任务分发及上传数据到云平台
不方便准备环境的童鞋可以直接登录云编辑器,在云编辑器上直接开发用例,操作手册链接:http://space.babytree-inc.com/pages/viewpage.action?pageId=27535942
如果有权限问题,请联系caiyubing解决
一、环境准备:
1、python包安装:
要求: python要python3以上,pip版本要在20以上。使用python -V和pip -V查看各自版本
将python安装环境配置到环境变量中
详细安装文档参考http://space.babytree-inc.com/pages/viewpage.action?pageId=24940086,编写用例手册查看http://space.babytree-inc.com/pages/viewpage.action?pageId=24940840
总工程执行方式:
python3 runner.py 参数1 参数2 参数3 参数4 参数5
参数1: 设备id(多个用逗号分隔)
参数2:选择运行模式,s, m, d
s-> single 单设备运行,m-> multi 多设备运行(测兼容性相关,每个设备上都执行要执行的case)、d-> distribute多设备分布式运行(将case分布到不同的设备上跑,节省耗时)
参数3: case执行类型,all表示执行所有,choose表示选择性执行, tag表示按case级别执行任务
参数4: 与第二个参数对应,如果参数2是all,参数3可传all(非空值都行),参数2是choose, 参数3传要执行的case名称,多个case逗号分隔,
参数2是tag,参数3传tag名,多个tag用逗号分割,如:P0,P1
参数5: 设置日志级别,可选参数 WARN、DEBUG、INFO
2、安装chromedriver,后面跑web测试需要用到。
直接下载chromedriver并添加路径
http://chromedriver.storage.googleapis.com/index.html
下载和chrome及电脑系统对应版本的chromedriver
--mac添加到路径的方式是:
进入下载文件所在位置
unzip chromedriver_mac64.zip
mv chromedriver /usr/local/bin
--windows添加到路径的方式是
Windows 进入系统->高级设置->环境变量进行设置->选中path,点编辑,把chrome浏览器的路径(比如:C:\Users\Administrator\AppData\Local\Google\Chrome\Application)和chromedriver的路径加到path里。
二、case编写
可根据不同的情况选择拷贝不同的demo脚本。
本地执行dubbo拷贝【dubbo-local-demo.air】文件
openapi拷贝【openapi-demo.air】文件
mapi get请求拷贝【httpget-demo.air】文件
mapi post请求拷贝【httppost-demo.air】文件
注意:
1. 拷贝后修改文件名.air的文件名和.py的文件名保持一致
2. 请注意下方case_tag中新增pool名、taskCode、执行环境(sit/on/pre)等其他需要增加的tag
实例1: 单设备跑所有的case及埋点,同时设置日志级别为DEBUG:
python3 runner.py 60fbe8cc s all all DEBUG
实例2:多设备跑部分case,同时设置日志级别为WARN
python3 runner.py 60fbe8cc,b5384901 m choose demo WARN
实例3:
单设备跑P0的case
python3 runner.py 60fbe8cc s tag P0 DEBUG
三、case 执行:
执行某个tag的case并设置日志等级为DEBUG, tag在每个用例上的case_tag的后面取:
python runner.py tag 100086 DEBUG sit
执行case中的某个场景命令:
python runner.py sc 月嫂 babyCareSearch 传参sortType=1 DEBUG sit
说明: 月嫂 模块名 babyCareSearch(.air文件夹的名字) 传参sortType=1(场景的名字,支持模糊匹配,但是不能有空格)
多个casetag用英文逗号分割。 如果需要同时满足多种tag用#分割
如python runner.py tag api#user-web DEBUG sit 表示执行同时满足api 且 user-web两个条件的case
python runner.py tag api#user-web,health-web 表示执行满足api 且 (user-web或者health-web)条件的case
DEBUG表示设置日志等级,可选参数有
DEBUG,INFO,WARN
sit表示选择执行环境。可输入参数sit,on,pre
sit表示测试环境,on 表示线上环境, pre预生产环境
具体case能否在各环境执行视case情况而定
四、任务分发
如果本地调试用二中的方式调用就行。
如果需要快速执行完任务,把任务分发的几个不同的子job去执行就采用以下调度方式。子job需要自己创建
python distribute.py %tag% %cases% %log_level% %num% %JobOrDevice% %pool_name% %run_env% %JOB_NAME% %BUILD_NUMBER% %JOB_URL% %BUILD_USER% %oldrev% %newrev% %deployid% %cbtoken%
如果不需要分发任务到其他子job,num传参数1,JobOrDevice传本job名
#重要说明
自动化case在sit,pre,on三个环境下执行。sit环境可以直接通过命令连接数据库。而pre,on环境需要从http://idb.baobaoshu.com/ 里去查询。
我们封装的查询方法在 common/db/sql/sql.py里。登录账号及选择数据库,环境,服务器需要各业务线根据自己的需求去自主填写。
即在common/db/sql/sql.py 里找到以下内容,填入对应值。
driver.find_element_by_id('username').send_keys()
driver.find_element_by_name('password').send_keys()
#选择数据库,,括号里填入自己数据库的值
Select(driver.find_element_by_id("database")).select_by_value()
#选择环境
Select(driver.find_element_by_id("environment")).select_by_value()
#选择服务器
Select(driver.find_element_by_id("server")).select_by_value()
环境相关问题:
1、判断手机是否是锁屏态时需要用到adb,所以要保证我们的环境变量里有adb。
linux环境装完adb需要在环境变量里配置一下。
python也需要配置环境变量,配置如下:
vim ~/.bash_profile 加上
export PYTHON3=/usr/local/bin/
export ADB=/Applications/AirtestIDE.app/Contents/MacOS/airtest/core/android/static/adb/mac/
export PATH=$PATH:$PATHON3:$ADB
另外在终端里配置一下,使环境变量一直生效,不需要source
终端是zsh的话,加载的是 ~/.zshrc文件
vim ~/.zshrc 最后,增加一行:source ~/.bash_profile
windows环境可按windows设置环境变量的方式设置。
五、功能介绍
> 支持美囤和北京数据库测试环境线上环境查询、美囤测试环境update和delete
例子:
美囤调用: result_db = dbOP().selectSql('exp_expert', [0, 20])
北京调用: result_db = dbOP().selectSql('exp_expert', [0, 20], 'bj_db')
case相关问题:
1、如果case要分tag,可在写case的时候在代码里加上注释 case_tag:P0,checkList
当选择按tag去跑用例,我们会按关键字case_tag去获取对应case的级别,多个tag 逗号分隔
六、 如何进行代码review
> 代码提交到gerrit后,请通知团队的测试进行review
> review结果请写入到reply中
若用例中掉了场景,则需要填写;用例XXXX(填上.air名)差场景:XXX、场景:XXX,并通知开发修改
若case没有问题,则直接写review通过
>
......@@ -30,10 +30,10 @@ function StepPannel(data, root){
this.bindEvents()
this.init_gallery()
this.init_pagenation()
var steps = this.filterAssertSteps()
var steps = [].concat(this.original_steps)
if(steps.length >0){
this.steps = steps
this.filterSteps($('.filter#assert'))
this.filterSteps($('.filter#all'))
} else{
this.setSteps()
}
......@@ -252,7 +252,8 @@ function StepPannel(data, root){
for(var i = start; i< end; i++){
var step = this.steps[i]
var title = step.assert ? '<span lang="en">Assert: </span>' + step.assert : step.title
html += '<div class="step" index="%s">'.format(step.index) +
html += step.scene_name ? '<div class="step-scenario"> '+'<span class="step_title_scenario" lang="en">%s</span>'.format(step.scene_name) : '' +'</div>' +
'<div class="step" index="%s">'.format(step.index) +
'<img src="%simage/step_%s.svg" alt="%s.svg"/>'.format(this.static, step.status, step.status) +
'<span class="order"># %s</span>'.format(step.index +1) +
'<span class="step_title" lang="en">%s</span>'.format(title) +
......@@ -643,6 +644,7 @@ function getFormatTime(timestamp){
function getFormatDuration(delta) {
// 格式化耗时, 格式为 0hr1min6s22ms
console.log(delta)
ms = parseInt(delta % 1000)
delta = parseInt(delta / 1000)
s = delta % 60
......@@ -650,7 +652,6 @@ function getFormatDuration(delta) {
m = delta % 60
h = parseInt(delta/ 60)
msg = ''
if(h == 0)
if(m == 0)
if(s==0)
......
......@@ -112,6 +112,10 @@ class LogToHtml(object):
def _translate_step(self, step, case_img_dir):
"""translate single step"""
scene_name = ""
if 'scene_name' in step:
scene_name = step["scene_name"]
name = step["data"]["name"]
title = self._translate_title(name, step)
code = self._translate_code(step, case_img_dir)
......@@ -120,18 +124,20 @@ class LogToHtml(object):
traceback = self._translate_traceback(step)
assertion = self._translate_assertion(step)
time = step["time"]
# set test failed if any traceback exists
if traceback:
self.test_result = False
translated = {
"title": title,
"time": step["time"],
"time": time,
"code": code,
"screen": screen,
"desc": desc,
"traceback": traceback,
"assert": assertion,
"scene_name": scene_name,
}
return translated
......@@ -250,10 +256,8 @@ class LogToHtml(object):
else:
image_path = os.path.abspath(value['_filepath'] or value['filename'])
#arg["image"] = image_path
try:
arg["image"] = case_img_dir + image_path.split("air_case")[1].replace("\\", "/")
except:
arg["image"] = image_path
arg["image"] = case_img_dir + image_path.split("air_case")[1].replace("\\", "/")
if not value['_filepath'] and not os.path.exists(value['filename']):
crop_img = imread(os.path.join(self.script_root, value['filename']))
else:
......@@ -505,6 +509,7 @@ def get_parger(ap):
return ap
"""
def main(args):
# script filepath
path, name = script_dir_name(args.script)
......@@ -519,7 +524,22 @@ def main(args):
# gen html report
rpt = LogToHtml(path, log_root, static_root, export_dir=export, script_name=name, lang=lang, plugins=plugins)
rpt.report(HTML_TPL, output_file=args.outfile, record_list=record_list)
"""
def main(log_root, static_root, script, lang, plugins, report_dir, case_image_dir, output_file):
# script filepath
#ap = get_parser()
path, name = script_dir_name(script)
record_list = []
log_root = decode_path(log_root) or decode_path(os.path.join(path, LOGDIR))
#static_root = args.static_root or STATIC_DIR
static_root = decode_path(static_root)
export = None
# gen html report
rpt = LogToHtml(path, log_root, static_root, export_dir=export, script_name=name, lang=lang, plugins=plugins)
rpt.report("log_template.html", report_dir, case_image_dir, output_file=output_file)
return rpt
if __name__ == "__main__":
import argparse
......
......@@ -46,17 +46,17 @@
<table width="1000">
<caption><ul><li>测试概要</li></ul></caption>
<tr width="800">
<th width="400" class='details-col-msg'>用例总数</th>
<tr width="600">
<th width="300" class='details-col-msg'>用例总数</th>
<th class='details-col-msg'>成功数</th>
<th class='details-col-msg'>运行用时</th>
<th class='details-col-msg'>成功率</th>
</tr>
<tr width="800">
<tr width="600">
<td class='details-col-elapsed'>1</td>
<td class='details-col-elapsed'>1</td>
<td class='details-col-elapsed'>0分48</td>
<td class='details-col-elapsed'>0分0</td>
<td class="details-col-elapsed">100.0%</td>
</tr>
</table>
......@@ -64,20 +64,18 @@
<!--<div><h2>Test detail</h2></div>-->
<table width="1000">
<caption><ul><li>测试列表</li></ul></caption>
<tr width="800">
<tr width="600">
<th width="400" class='details-col-msg'>用例名称</th>
<th class='details-col-msg'>执行结果</th>
<th class='details-col-msg'>执行时间(秒)</th>
<th class='details-col-msg'>用例作者</th>
<th class='details-col-msg'>执行设备</th>
</tr>
<tr width="800">
<td class="details-col-elapsed"><a href='../log/demo/log.html' target='_blank'>demo</a></td>
<tr width="600">
<td class="details-col-elapsed"><a href='../log/登录外网系统/log.html' target='_blank'>登录外网系统</a></td>
<td class="success">成功</td>
<td class="details-col-elapsed">48.868</td>
<td class="details-col-elapsed">lihong</td>
<td class="details-col-elapsed"></td>
<td class="details-col-elapsed">0.1</td>
<td class="details-col-elapsed">xiaohesheng</td>
</tr>
</table>
......
......@@ -51,7 +51,7 @@ python-dateutil==2.8.1
python-gitlab==1.15.0
pytz==2019.3
pywinauto==0.6.3
PyYAML==3.13
PyYAML==5.3.1
redis==3.3.11
requests==2.22.0
ruamel.yaml==0.16.10
......
# -*- encoding=utf-8 -*-
# -*- encoding=utf8 -*-
import os
import sys
import platform
import shutil
import common.run_case_conditions as run
import common.case_tag_get as case_tag_get
import random
import time
import requests
import json
import platform
curPath = os.path.abspath(os.path.dirname(__file__))
rootPath = os.path.split(curPath)[0]
sys.path.append(rootPath)
def dingding_send(content):
"""
报错的用例发钉钉群
:param content:
:return:
"""
url = 'https://oapi.dingtalk.com/robot/send?access_token=d9e673ded1ab61ee6a631333a3d80b4291684e3adf61169ab6c1bb83d375e26d'
pagrem = {
"msgtype": "text",
"text": {
"content": content
},
"at": {
"atMobiles": [
],
"isAtAll": True # 是否@所有人,默认否
}
}
headers = {
'Content-Type': 'application/json'
}
response = requests.post(url, data=json.dumps(pagrem), headers=headers)
print(response.text)
return response.text
def check_phone_locked():
for device_id in devices_list:
is_ok = os.system('adb -s ' + device_id + ' get-state')
print("is_ok: " + str(is_ok))
if is_ok != 0:
if '5555' in device_id:
os.system('adb connect ' + device_id)
is_ok = os.system('adb -s ' + device_id + ' get-state')
if is_ok != 0:
devices_list.remove(device_id)
else:
if device_id != 'bb294ac8':
devices_list.remove(device_id)
if "AutoTest_" in curPath:
dingding_send("设备检查:" + device_id + "离线啦, 快去看看")
else:
try:
for i in range(3):
r = os.popen('adb -s ' + device_id + ' shell dumpsys window policy')
stdout = r.read()
r.close()
if 'mShowingLockscreen=true' in stdout or 'mScreenOnEarly=false' in stdout:
if 'mScreenOnEarly=false' in stdout:
os.system('adb -s ' + device_id + ' shell input keyevent 26')
os.system('adb -s ' + device_id + ' shell input keyevent 224')
if device_id in ['0815f81aab021502', 'WTKDU16C07003266']:
os.system('adb -s ' + device_id + ' shell input swipe 300 1500 300 300')
else:
os.system('adb -s ' + device_id + ' shell input swipe 300 1000 300 500')
os.system('adb -s ' + device_id + ' shell input keyevent 3')
check_battery(device_id)
except:
pass
print("device_list:")
print(devices_list)
def check_battery(device_id):
"""
检查电池信息
:return:
"""
reset_cmd = 'adb -s ' + device_id + ' shell dumpsys battery reset'
os.system(reset_cmd)
time.sleep(1)
check_cmd = 'adb -s ' + device_id + ' shell dumpsys battery'
r = os.popen(check_cmd)
stdout = r.read()
r.close()
level = stdout.split('level')[1].split('scale')[0]
level = level.replace('\n', '').replace('\r', '').replace(': ', '')
if int(level) >= 90:
print(level)
print('adb -s ' + device_id + ' shell dumpsys battery set status 1')
os.system('adb -s ' + device_id + ' shell dumpsys battery set status 1')
else:
if int(level) < 6:
devices_list.remove(device_id)
if "AutoTest_" in curPath:
dingding_send("设备检查:" + device_id + "电量不足6%啦,快去看看")
print(level)
print('adb -s ' + device_id + ' shell dumpsys battery set status 2')
os.system('adb -s ' + device_id + ' shell dumpsys battery set status 2')
def get_file(path):
"""
获取解压出来得文件名
:return:
"""
list = []
for dirpath, dirnames, filenames in os.walk(path):
for f in filenames:
if f.endswith('.apk'):
list.append(filenames)
return list
def download(url=""):
"""
拉取主干最新的包
:return:
"""
del_cmd = 'del temp\*.* /s /q >nul'
os.system(del_cmd)
if url != "":
dump_cmd = 'curl -u admin:YKNTJKLW9Y -O ' + url
print(dump_cmd)
p = os.popen(dump_cmd)
print(p.read())
time.sleep(1)
os.popen('move *apk temp')
time.sleep(1)
else:
dump_cmd = 'curl -u admin:YKNTJKLW9Y http://pack.babytree-inc.com/view/%E5%AD%95%E8%82%B2%E5%AE%89%E5%8D%93/job/android_pregnancy_master/lastSuccessfulBuild/artifact/temp/*zip*/temp.zip -o apk.zip'
print("dump_cmd: ", dump_cmd)
unzip_cmd = 'unzip -o apk.zip'
p = os.popen(dump_cmd)
print(p.read())
os.popen(unzip_cmd)
time.sleep(2)
if __name__ == '__main__':
# 第一个参数设备ID
devices = sys.argv[1]
devices_list = devices.split(',')
# 第二个参数 选择单机或多机或多机分布式跑
runType = sys.argv[2]
# 第三个参数 case 执行类型,'all', 'choose', 'tag'
caseType = sys.argv[3]
# 第四个参数要执行的caseName, 多个文件逗号分割
caseName = sys.argv[4]
# 第五个参数,设置日志等级
log_level = sys.argv[5]
# 复制hosts文件
# 第一个参数 case 执行类型,'all', 'sc', 'tag'
caseType = sys.argv[1]
# 第2个参数要执行的caseName, 多个文件逗号分割
caseName = sys.argv[2]
# 第3个参数,设置日志等级
log_level = sys.argv[3]
log_level = log_level.lower()
#获取运行环境,写入环境变量
env = sys.argv[4]
os.environ['ENV'] = env.lower()
job_url = ""
#判断传入过来的参数数量是否>5个,如果>5,则传过来的第5个参数为job链接
if len(sys.argv) > 5:
job_url = sys.argv[5]
#复制hosts文件
if platform.system() == 'Windows':
cmd = "xcopy /s /y data\hosts C:\Windows\System32\drivers\etc\ "
else:
cmd = 'mv data/hosts /etc/'
os.system(cmd)
workspace = os.path.abspath(".")
# 检查锁屏
check_phone_locked()
if len(sys.argv) >= 7 and sys.argv[6] == 'download':
if len(sys.argv) > 7:
url = sys.argv[7]
download(url)
else:
download()
case_path = os.path.join(workspace, 'air_case')
log_path = os.path.join(workspace, 'log')
runtime_log = os.path.join(log_path, 'runtime.txt')
if not os.path.exists(log_path):
os.makedirs('log')
if not os.path.exists(runtime_log):
os.system('type nul >log/run_time.txt')
print("workspace: " + workspace)
print("air_case_path: " + case_path)
print("air_log_path: " + log_path)
print("runType:" + runType)
print("caseType:" + caseType)
test = run.CustomAirTestCase(workspace, case_path, log_path, runtime_log, log_level)
case_list = caseName.split(',')
if caseType == 'tag':
tag = sys.argv[4]
tagList = tag.split(',')
case_list = case_tag_get.get_case_tag_list(case_path, tagList)
if caseType == 'user':
tag = sys.argv[4]
case_list = case_tag_get.get_case_by_author(case_path, tag)
random.shuffle(case_list)
"""
if '个人主页_会客厅_首次进入' in case_list:
index = case_list.index('个人主页_会客厅_首次进入')
case_list[0], case_list[index] = case_list[index], case_list[0]
print("first case is : %s " % case_list[0])
"""
if runType == 's':
test.run_case(devices_list[0], case_list)
print("执行程序里的exit(0)")
sys.exit(0)
print("执行后exit(0)")
elif runType == 'd':
if caseName == 'firstpage':
devices_list = devices_list[:3]
test.run_case_by_distri(devices_list, case_list, log_level)
print("执行程序里的exit(0)")
sys.exit(0)
print("执行后exit(0)")
else:
test.run_case_by_Multi(devices_list, case_list, log_level)
print("执行程序里的exit(0)")
sys.exit(0)
print("执行后exit(0)")
try:
if caseType == 'sc':
moduleName = sys.argv[2]
caseName = sys.argv[3]
sceName = sys.argv[4]
log_level = sys.argv[5]
log_level = log_level.lower()
# 获取运行环境,写入环境变量
env = sys.argv[6]
os.environ['ENV'] = env.lower()
test.run_by_scenario(moduleName, caseName, sceName)
else:
case_list = caseName.split(',')
if caseType == 'tag':
tag = sys.argv[2]
case_list = case_tag_get.get_case_tag_list(case_path, tag)
run_case, case_list, case_scenario_name = test.merge_new_file(case_list)
test.run_case(run_case, case_list, job_url, case_scenario_name)
except Exception as e:
print("Exception:", e)
finally:
"""
检查air_case中是否有多余的.py文件和场景文件,有就删除
"""
dir_list = os.listdir(case_path)
for cur_file in dir_list:
path = os.path.join(case_path, cur_file)
if os.path.isdir(path):
file_list = os.listdir(path)
for file in file_list:
file_path = os.path.join(path, file)
if os.path.isfile(file_path):
os.remove(file_path)
else:
if str(file).startswith("场景"):
name = str(file).replace(".air", "")
del_file = os.path.join(file_path, name + ".py")
if os.path.exists(del_file):
os.remove(del_file)
shutil.rmtree(file_path)
# -*- encoding=utf8 -*-
import os
import sys
import platform
import shutil
import common.run_case_conditions as run
import common.case_tag_get as case_tag_get
curPath = os.path.abspath(os.path.dirname(__file__))
rootPath = os.path.split(curPath)[0]
sys.path.append(rootPath)
if __name__ == '__main__':
# 第一个参数 case 执行类型,'all', 'sc', 'tag'
caseType = sys.argv[1]
# caseType="tag"
# 第2个参数要执行的caseName, 多个文件逗号分割
caseName = sys.argv[2]
# caseName="登录主数据系统"
# 第3个参数,设置日志等级
log_level = sys.argv[3]
# log_level = "DEBUG"
log_level = log_level.lower()
#获取运行环境,写入环境变量
env = sys.argv[4]
# env="sit"
os.environ['ENV'] = env.lower()
job_url = ""
#判断传入过来的参数数量是否>5个,如果>5,则传过来的第5个参数为job链接
if len(sys.argv) > 5:
job_url = sys.argv[5]
#复制hosts文件
if platform.system() == 'Windows':
cmd = "xcopy /s /y data\hosts C:\Windows\System32\drivers\etc\ "
else:
cmd = 'mv data/hosts /etc/'
os.system(cmd)
workspace = os.path.abspath(".")
case_path = os.path.join(workspace, 'air_case')
log_path = os.path.join(workspace, 'log')
runtime_log = os.path.join(log_path, 'runtime.txt')
if not os.path.exists(log_path):
os.makedirs('log')
if not os.path.exists(runtime_log):
os.system('type nul >log/run_time.txt')
print("workspace: " + workspace)
print("air_case_path: " + case_path)
print("air_log_path: " + log_path)
print("caseType:" + caseType)
test = run.CustomAirTestCase(workspace, case_path, log_path, runtime_log, log_level)
try:
if caseType == 'sc':
moduleName = sys.argv[2]
# moduleName = "spd3.0"
caseName = sys.argv[3]
# caseName = "登录主数据系统"
sceName = sys.argv[4] #场景名称
# sceName = ""
log_level = sys.argv[5]
# log_level = "debug"
log_level = log_level.lower()
# 获取运行环境,写入环境变量
env = sys.argv[6]
os.environ['ENV'] = env.lower()
test.run_by_scenario(moduleName, caseName, sceName)
else:
case_list = caseName.split(',')
if caseType == 'tag':
tag = sys.argv[2]
# tag ="登录主数据系统"
case_list = case_tag_get.get_case_tag_list(case_path, tag)
run_case, case_list, case_scenario_name = test.merge_new_file(case_list)
test.run_case(run_case, case_list, job_url, case_scenario_name)
except Exception as e:
print("Exception:", e)
finally:
"""
检查air_case中是否有多余的.py文件和场景文件,有就删除
"""
dir_list = os.listdir(case_path)
for cur_file in dir_list:
path = os.path.join(case_path, cur_file)
file_list = os.listdir(path)
for file in file_list:
file_path = os.path.join(path, file)
if os.path.isfile(file_path):
os.remove(file_path)
else:
if str(file).startswith("场景"):
name = str(file).replace(".air", "")
del_file = os.path.join(file_path, name + ".py")
if os.path.exists(del_file):
os.remove(del_file)
shutil.rmtree(file_path)
......@@ -46,14 +46,14 @@
<table width="1000">
<caption><ul><li>测试概要</li></ul></caption>
<tr width="800">
<th width="400" class='details-col-msg'>用例总数</th>
<tr width="600">
<th width="300" class='details-col-msg'>用例总数</th>
<th class='details-col-msg'>成功数</th>
<th class='details-col-msg'>运行用时</th>
<th class='details-col-msg'>成功率</th>
</tr>
<tr width="800">
<tr width="600">
<td class='details-col-elapsed'>{{summary_message.caseNum}}</td>
<td class='details-col-elapsed'>{{summary_message.passNum}}</td>
<td class='details-col-elapsed'>{{summary_message.time}}</td>
......@@ -64,20 +64,18 @@
<!--<div><h2>Test detail</h2></div>-->
<table width="1000">
<caption><ul><li>测试列表</li></ul></caption>
<tr width="800">
<tr width="600">
<th width="400" class='details-col-msg'>用例名称</th>
<th class='details-col-msg'>执行结果</th>
<th class='details-col-msg'>执行时间(秒)</th>
<th class='details-col-msg'>用例作者</th>
<th class='details-col-msg'>执行设备</th>
</tr>
{% for r in case_results %}
<tr width="800">
<tr width="600">
<td class="details-col-elapsed"><a href='{{log_path}}/{{r.name}}/log.html' target='_blank'>{{r.name}}</a></td>
<td class="{{'success' if r.result else 'fail'}}">{{"成功" if r.result else "失败"}}</td>
<td class="details-col-elapsed">{{r.time}}</td>
<td class="details-col-elapsed">{{r.author}}</td>
<td class="details-col-elapsed">{{r.device}}</td>
</tr>
{% endfor %}
</table>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment