一、登录
在注册接口的基础上,写出登录接口自动化测试
login注意点:
1.登录不需要生成动态手机号
2.不需要查询数据库
3.登录成功的手机号可以提前准备手机号跟密码:
①可以固定写在excel中
②写在yaml中,excel中以“#phone#”,"#pwd#"表示,
if “#phone#” in case_info["data"] :
case_info["data"] = case_info["data"] .replace(“#phone#” ,yaml_data["user"]["phone"])
pwd替换同理。
二、充值-----(2020.6.16课程 接口实战十)
1.充值接口需要使用member_id
① 可以member_id直接放在yaml中
②充值之前,肯定是需要登录,登录成功的返回数据里,又token跟id,在获取token的时候,顺便获取id.-------接口依赖
1)什么是接口依赖?-----面试
一个接口的测试需要另一个接口作为前置条件,比如充值接口需要登录接口:①获取token ②获取member_id
2.URL和接口拼接
excel中的url之前是默认写好的,但是在测试中,可能会又测试环境、生产环境、预发布环境等,URL 会发生变化。
因此要将URL进行拼接。
方法一:将域名放到yaml中 ---->host: http://api.lemonban.com/futureloan
方法二:将域名放到config.py的配置文件中
3.编写测试脚本
充值之前先要登录,那么登录就可以作为前置条件。登录一次即可。----------setUpClass()
取现也要用登录,那么就可以将登录这个前置条件进行封装,放在中间层middleware中----再次回顾:中间层是跟业务相关的,同时中间层又可以使用common里面的一些通用的类。
下面再handler.py中封装登录login的函数
def login(): """登录""" res = requests_handler.visit_simple( url=HandlerMiddle.yaml_data["host"]+"/member/login", method="post", headers = {"X-Lemonban-Media-Type":"lemonban.v2"}, json=HandlerMiddle.yaml_data["user"] ) #获取token token_str = res["data"]["token_info"]["token"] token_type = res["data"]["token_info"]["token_type"] token = " ".join([token_type,token_str])#或者直接拼接token = token_type + " " + token_str #获取member_id member_id = res["data"]["id"] return {"token":token,"member_id":member_id} #验证 if __name__ == '__main__': print(login())
上面取res中的token_type,token_str,使用jsonpath,不需要管层级:
token_str = jsonpath.jsonpath(res,"$..token")[0] #取到的token值存在列表里,取索引0 token_type = jsonpath.jsonpath(res,"$..token_type")[0] token = " ".join([token_type,token_str]) #或者直接拼接token =token_type +" "+ token_str
拓展知识:jsonpath-----json数据解析,多重嵌套字典,获取value时,不需要一直取key
1.pip install jsonpath
2.语法:$表示根节点,
一个点.表示子节点
两个点..表示子孙节点
import jsonpath user = {"data":{"name":"polo","age":18}}#{}表示根节点;"data":{"name":"polo","age":18}表示子节点; #如果匹配到数据,直接得到结果的列表 print(jsonpath.jsonpath(user,"$.data")) print(jsonpath.jsonpath(user,"$..name")) #如果匹配不到数据,直接返回false print(jsonpath.jsonpath(user,"$.name")) user={"data":{"name":"polo","hoppy":{"music":"jay","visit":"korea"}}} #不管嵌套多少层,最多只有2个点,$..都可以拿到数据 print(jsonpath.jsonpath(user,"$..music"))
今天踩了个坑,运行文件命名为jsonpath.py,运行一直报错:【module can not callable】
4.简化login函数的调用
上面在handler.py中封装了login(),可以在Handler类中将token,member_id单独定义成方法,调用的时候,直接在Handler类中调用。
def token(self): return login()["token"] def member_id(self): return login()["member_id"]
在recharge中要先登录,调用handler().token(),都是带有括号的对象的调用,其实我觉得这么调用也没什么不方便,老师说了不想带括号,那就来看下怎么个不带括号调用,把实例方法变成属性啊------python的功能真特么强大。
怎么变?-----实例方法的头上加:@property,这个token()方法就变成属性了!!
class HandlerMiddle: """将yaml,excel,logger定义为类属性""" #获取conf属性 conf = config #一切皆对象,可以将模块直接赋值给conf这个属性 #获取yaml数据 yaml_data = yaml_handler.read_yaml(os.path.join(config.CONFIG_PATH,'config.yaml')) #excel配置信息 __excel_data = yaml_data["excel"] login_sheet = __excel_data["sheet_login"] regist_sheet = __excel_data["sheet_register"] #获取excel对象 excel_file = yaml_data["excel"]["file"] excel_path = os.path.join(config.EXCEL_PATH,excel_file) excel = excel_handler.ExcelHandler(excel_path) #配置log信息 __logger_config = yaml_data["logger"] #配置log路径 __log_mk_path = datetime.now().strftime("%Y-%m-%d") __log_fl = datetime.now().strftime("%y-%m-%d-%H-%M-%S") __log_path = os.path.join(config.LOG_PATH,__log_mk_path) #判断__log_path是否存在 if not os.path.exists(__log_path): os.mkdir(__log_path) __log_file = os.path.join(__log_path,"futureloan--{}.log".format(__log_fl)) ##获取logger收集器 logger = logging_handler.get_logger( name = __logger_config["name"], file_name = __log_file, log_level=__logger_config["logger_level"], stream_level=__logger_config["stream_level"], file_level=__logger_config["file_level"] ) #配置report信息 report_config = yaml_data["report"] __report_mk_path = datetime.now().strftime("%Y-%m-%d") __repport_fl = datetime.now().strftime("%y-%m-%d-%H-%M-%S") __report_path = os.path.join(config.REPORT_PATH,__report_mk_path) #判断路径是否存在 if not os.path.exists(__report_path): os.mkdir(__report_path) report_file = os.path.join(__report_path,"reports--{}.html".format(__log_fl)) @property def token(self): return login()["token"] @property def member_id(self): return login()["member_id"]
在recharge中,就直接调用属性,不需要用函数取调用了:
@ddt.ddt class TestRegister(unittest.TestCase): @classmethod def setUpClass(cls): token = handler.HandlerMiddle().token member_id = handler.HandlerMiddle().member_id @ddt.data(*excel_data) def test_recharge(self,case_info): print(case_info) pass
5.替换excel中的数据(member_id,token)
def test_recharge(self,case_info): """充值接口访问""" data = case_info["data"] headers = case_info["headers"] if "#member_id#" in data: data = data.replace("#member_id#",str(self.member_id)) if "#token#" in headers: headers = headers.replace("#token#",self.token) logger.info("正在执行{}条用例:{}".format(case_info["case_id"],case_info["title"]))
6.充值是否成功------校验数据库
如何校验?
①充值前,查询数据库的余额
②充值后,查询数据库的余额
③断言:充值前的金额+充值金额 = 充值后的金额
♥♥小数相加,浮点数的精度运算----->需要要到decimal,传的参数必须是str,如果传的不是str,会丢失精度
举例:浮点数直接相加,结果错误
print(0.1 + 0.2 == 0.3) #False
举例:浮点数相加,使用Decimal(导入decimal)
from decimal import Decimal print(Decimal("0.1") + Decimal("0.2") == Decimal("0.3")) #True
6.提现的过程是充值的反序。