大家好,我是刚哥。tep已经支持两种开发模式:用例数据集成和HttpRunner(第三版)。HttpRunner已经广为人知,这里不再过多介绍。用例数据集成是指将用例和数据都写在一个test.py文件中。这样做的好处是简单明了。特别适合刚开始使用pytest编写自动化代码的同学。他们从上到下完成了一个自动化。用例在获得成就感的同时,也可以轻松分享给他人使用,单文件运行。但是当我在公司用SpringBoot开发后端服务时,我尝到了MVC架构带来的高可维护性。另外跟大家聊天的时候也听说很多公司都有分层接口自动化。设计,所以tep支持用例数据分离的开发就变得很重要了。用例数据分离,就是用例只有逻辑,没有数据,这样在修改数据的时候,用例基本可以适配而不用改变。用例看起来非常简洁,像这样:classTest:case_vars=TepVars()case_vars.vars_={"domain":"http://127.0.0.1:5000","skuNum":"3"}deftest(self):#登录Login(Test).post()#搜索商品SearchSku(Test).get()#添加购物车AddCart(Test).post()#下单Order(Test).post()#PaymentPay(test).post()这就是tep支持的用例数据分离的用例的样子。我添加了一个services文件夹来存放接口:先看Login.py:classLogin(BaseRequest):defpost(self):response=self.request("post",url=self.case_vars.get("domain")+"/login",headers={"Content-Type":"application/json"},json={"username":"dongfanger","password":"123456",})assertresponse.status_code<400self.case_vars.put("token",response.jmespath("token"))必须继承自BaseRequest。self.request和requests.request的用法是完全一样的。self.case_vars用于在测试用例的测试步骤之间传递变量,有两个操作:get和put。response.jmespath("token")是在封装requests.Response之后添加的方法,替代jmespath.search("token",response.json())。BaseRequest定义如下::returnjmespath.search(expression,self.json())classBaseRequest:def__init__(self,clazz):self.case_vars=clazz.case_varsdefrequest(self,method,url,**kwargs):response=request(method,url,**kwargs)returnTepResponse(response)TepResponse封装了requests.Response并添加了jmespath方法。BaseRequest的__init__在初始化时传入测试类(test.py中测试用例的类),提取case_vars对象,这样继承接口类后,可以使用self.case_vars获取和放变量。同时调用tep.client.request,将response作为封装后的TepResponse返回。那么问题来了,接口之间如何传递参数呢?请看test_login_pay_mvc.py、Login和SearchSku这三段代码:#test_login_pay_mvc.pyclassTest:case_vars=TepVars()case_vars.vars_={"domain":"http://127.0.0.1:5000","skuNum":"3"}deftest(self):#LoginLogin(Test).post()#搜索商品SearchSku(Test).get()#添加购物车AddCart(Test).post()#Order(Test).post()#PayPay(Test).post()#Login.pyclassLogin(BaseRequest):defpost(self):response=self.request("post",url=self.case_vars.get("domain")+"/login",headers={"Content-Type":"application/json"},json={"username":"dongfanger","password":"123456",})assertresponse.status_code<400self.case_vars.put("token",response.jmespath("token"))#SearchSku.pyclassSearchSku(BaseRequest):defget(self):response=self.request("get",url=self.case_vars.get("域")+"/searchSku",headers={"token":self.case_vars.get("token")},params={"skuName":"e-book"})self.case_vars.put("skuId",response.jmespath("skuId"))self.case_vars.put("skuPrice",response.jmespath("price"))assertresponse.status_code<400test_login_pay_mvc.py文件的Test测试用例中,定义了用例级别的变量:domainLogin.py文件通过self.case_vars.get("domain"),然后通过self.case_vars.put("token",response.jmespath("token"))将token放入token中。SearchSku.py文件通过self.case_vars.get("token")获取token,并使用self.case_vars.put()存储skuId和skuPrice,供下一个接口AddCart等使用。用例数据分离的写法遵循MVC架构,借鉴了HttpRunner和JMeter的部分设计。相对于用例数据的整合,书写体验可能没有那么方便,但可维护性和复用性非常高。其中接口类Get和post可以根据数据需要定义get_a、post_b等多个,以支持多种数据,略显复杂,适合有编码经验的同学。用例数据集成、用例数据分离、HttpRunner这三种开发模式如何使用?tep0.9.4发布后,升级使用tepstartprojectdemo命令创建项目脚手架,其中将包含所有登录订单流程的三种开发模式示例代码,开箱即用,一键运行成功。从此,tep的实用性又提升了一个档次,但我要停下来,专注于HttpRunner3的源码学习,出系列文章,只有站在巨人的肩膀上,才能看到更多更远。为什么HttpRunner如此重要?因为tep的技术毕竟是从HttpRunner学来的。
