前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >unittest批量组织依赖用例(组织依赖用例,结果前端展示,测试报告发送 )

unittest批量组织依赖用例(组织依赖用例,结果前端展示,测试报告发送 )

作者头像
软件测试君
发布2019-11-04 16:45:26
4470
发布2019-11-04 16:45:26
举报
文章被收录于专栏:测试人生测试人生

关注测试君 | 会上瘾

在上一篇《unittest批量组织依赖用例(一)》,我们讲了在拿到依赖case的情况下如何批量生成测试方法,那么如何组织依赖case呢,我们今天来试试~本次以Excel为例,做一个简单的依赖case读取与执行~实现代码与业务逻辑解耦(这篇只介绍如何设计,具体设计可以自行根据需求变化~)

第一步,搭建几个依赖接口,流程如下:

那么我们这次脚本的流程图设计如下~

上次用flask,那我们这次还是用django写几个简单依赖接口吧~ views中伪代码如下(路由省略):

代码语言:javascript
复制
def test_api_01(request):
    global A
    if request.method =='POST':
        username = request.POST['username']
        password = request.POST['password']
        if username=='root' and password=='123456':
            A=random.randint(111111,999999)
            resp = {
                'number': A,
            }
            return HttpResponse(json.dumps(resp), status=520, content_type="application/json")
        else:
            resp = {
                'status':'error',
            }
            return HttpResponse(json.dumps(resp), status=520, content_type="application/json")
    else:
        return  render(request,"api1.html")

def test_api_02(request):
    global A
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        number = request.POST['number']
        number2 =  request.POST['number2']
        if username == 'root' and password == '123456' and int(number)==int(A) and number2=="ASDYUASIDKLASD":
           resp = {
                    'code': '200',
                    'message': 'success',
                  }
           return HttpResponse(json.dumps(resp),status=520, content_type="application/json")
        else:
            resp = {
                'code': '100',
                'message': 'fail',
            }
            return HttpResponse(json.dumps(resp), status=444, content_type="application/json")

    else:
        return render(request, "api2.html")


def test_api_03(request):
    global A
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        if username == 'root' and password == '123456':
           resp = {
                    'code': '200',
                    'orderid': '78562564DASDJSK655656',
                  }
           return HttpResponse(json.dumps(resp),status=520, content_type="application/json")
        else:
            resp = {
                'code': '100',
                'message': 'fail',
            }
            return HttpResponse(json.dumps(resp), status=444, content_type="application/json")

    else:
        return render(request, "api2.html")

def test_api_04(request):
    global A
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        if username == 'root' and password == '123456':
           resp = {
                    'code': '200',
                    'number2': 'ASDYUASIDKLASD',
                  }
           return HttpResponse(json.dumps(resp),status=520, content_type="application/json")

接下来我们新建一个excel,我们这次只看关于body中的依赖,其他字段设计暂时忽略。api_sum_list 为汇总表记录所有api,而api对应的具体测试用例分别在各自的sheet,url列可以自行填写不同环境的baseURL,当然也可以在配置文件中进行配置~

咱们再来看看具体API中依赖表的设计(可点击查看大图),依赖数据存于dependenceCase 这一列,多个依赖为了方便看起来不费劲,我用‘===’当做分割符~ 而data中的占位符用%s表示~ 如果请求中有%怎么办呢~可以用%%来代替~这一列中的sheet:代表依赖case所在的sheet ,case 代表所在sheet中的位置,dependence 代表需要保存依赖case中的返回值~

哈哈那么如何组织case的运行顺序呢,从流程图上不难看出 A依赖B,B依赖C,C依赖D 那么则他们的运行顺序则为 D=>C=>B=>A,也就是入栈的方式,先进后出~那么如何获得到最后一层依赖数据呢~那就要去递归啦~伪代码如下:

代码语言:javascript
复制
if api_data['dependenceCase']:
                if '===' in api_data['dependenceCase']: #多平行依赖
                    for i  in  (api_data['dependenceCase']).split('==='):
                        dependenceCase = exchange(i)
                        if run == 'y':
                            depencedata(dependenceCase)
                else:
                    dependenceCase = exchange(api_data['dependenceCase'])
                    depencedata(dependenceCase)

其中exchange 方法用来生成依赖字典,传入depencedata,更方便的是从chrome抓如的请求经常为 XX:XX 使用此方法可以转化成字典,自动使用formdata进行请求~

代码语言:javascript
复制
def exchange(data):
    data_star = data.replace(':',' ').split()
    data = {data_star[x]: data_star[x + 1] for x in range(len(data_star) - 1) if x % 2 == 0}
    return data

重点来了,递归函数如下~也就是传入依赖sheet ,case,dependence,将会递归到最后一层,然后依次请求。

代码语言:javascript
复制
def depencedata(dependenceCase):# 依赖case 的递归提取传入的case
    if dependenceCase:
        depen_st = TestCases().api_detail(data_sum_list=None,
                                        assign=dependenceCase["sheet"],
                                        case=dependenceCase["case"])  # 取到Case 后继续取的依赖用例
        depen = depen_st[0]
        url_new = depen['url']
        header_new  = exchange(depen['header'])
        data_mode =depen['data_mode']
        if 'json' in data_mode:
            if not isinstance(depen['data'], str):
                data_new = str(depen['data'])
            else:
                data_new = str(depen['data'])
        else:
            data_new = exchange(depen['data'])  # 转化成字典 默认formdata
        dependence_new = depen['dependence']
        method = depen['method']
        dependencecase = exchange(depen['dependenceCase'])
        if  dependencecase:
            depencedata(dependencecase)
        if  dependence_new:
            data_end = eval(str(data_new) % (getattr(dependenceClass,dependence_new)))
        if  method == 'post':
            req = requests.post(url=url_new, data=data_end, headers=header_new, verify=False)
            depen_name = dependenceCase['dependence']
            if isinstance(req.text,str):
                json_data = eval(req.text) #依赖dict
            depen_data = json_ex(param=depen_name, json_c=json_data)   #提取依赖
            setattr(dependenceClass,str(depen_name),depen_data)
        if method == 'get':
            req = requests.get(url=url_new, data=data_end, headers=header_new, verify=False)
            depen_name = dependenceCase['dependence']
            if isinstance(req.text,str):
                json_data = eval(req.text)
            depen_data = json_ex(param=depen_name, json_c=json_data)   #提取依赖
            setattr(dependenceClass, str(depen_name), depen_data)

其中 json_ex 这个方法,可以快去提取需要的key对应的value,如果json数据量大不需要再[][][]一层一层的去写啦~(使用yield 记住所在递归位置)

代码语言:javascript
复制
def json_recursion(dic,rec=[]):
    if isinstance(dic, dict):
        for k,v in dic.items():
            if isinstance(v,dict):
                for d in json_recursion(v, rec + [k]):
                    yield d
            elif isinstance(v,list):
                for i in v:
                    for d in json_recursion(i, rec + [k]):
                        yield d
            else:
                yield rec+[k,v] #output
    else:
        yield dic

def json_ex(param,json_c,back=True):
    """
    :param param: 提取key值
    :param json_c: 提取json
    :param back:  是否return 第一次匹配值
    :return:
    """
    applist=[]
    for i in json_recursion(dic=json_c):
        # print(i)
        if param in str(i):
            applist.append(['.'.join(i[0:-1]),i[-1]])
    if len(applist)==1:
        return applist[0][1]
    elif len(applist)>1 and  back :
        return  applist[0][1]
    else:
        return applist

这样大概的框架已经形成啦,再把咋们上次写的装饰器用上稍作补充~得到run_all文件,为啥这么写?哈哈哈 其实这么写很麻烦~但是我觉得看着很好看哈哈~

代码语言:javascript
复制
@runTime
@deco_setarrt
@run(title="Api Test",description="API TEST RESULTS", tester="Ayo")
def run():
    Log.info('======>测试已完成')

run一下瞧瞧~哈哈我们依赖的case 全在我们主case 运行之前全部跑完~

我们再多run 几个case~并结合前端页面进行结果审查~(本次暂不详细介绍如何结合vue+element UI)

最后看看咋们运行邮件报告~ 嘻嘻这样一个完整的 用例脚本就这么设计好啦~可以根据自己项目进行diy,主要思想就是递归取依赖~

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 软件测试君 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档