Mark
(关于测试框架,面试问的不多,比如:项目用到多少,跑出来多少问题等,不会详细问怎么写)基础知识一、Python+request测试接口案例1、测试get接口import requestsr = requests.get('https://api.github.com/events')print(r.status_code)print(r.json())2、测试get param接口import requestsparams={    "shouji":"***",    "appkey":"***"}r = requests.get(url = 'http://api.binstd.com/shouji/query',params=params)print(r.json())3、测试post json接口import requestsjson_data = {    "title":"foo",    "body":"bar",    "userId":1}r = requests.post(url = "https://jsonplaceholder.typicode.com/posts",json = json_data)print(r.status_code)print(r.json())4、测试post param接口import requestsparams ={    "shouji":"***",    "appkey":"***"}r = requests.post(url = "http://api.binstd.com/shouji/query",params = params)print(r.status_code)print(r.json())5、测试post formdata接口import requestsdata = {    "text":"hello"}r = requests.post(url = "https://dict.youdao.com/keyword/key",data = data)print(r.json())二、pytest框架Pytest是什么:单元测试框架,在自动化测试或者白盒测试中针对软件的最小单元(函数、方法)进行测试主要做什么:发现测试用例、执行测试用例、判断测试结果、生成测试报告插件:pytestpytest-html(生成html报告的插件)pytest-xdist(多线程运行的插件)pytest-ordering(改变用例的执行顺序的插件)pytest-rerunfailres(失败用例重跑的插件)allure-pytest(生成美观自定义的allure报告)(pip insatll -r requirements.txt(去运行安装所有的插件))命名规则:1、模块名必须以test_开头或者以_test结尾2、测试类必须以test开头,并且不能带有init方法3、测试用例必须以test_开头Testcase  Test  test如何执行:1、命令行的方式执行pytest-v 输出详细信息-s 输出调试信息  -vs-n 多线程运行(pytest -xdist) pytest -vs -n =2(一个线程里面有多个进程,6秒,两个线程运行5秒--每个线程需要创建时间)-reruns num失败重跑(插件:rerunfailres) pytest -vs --reruns=2 Raise Exception(“”)抛出异常  try except解决异常-x 出现一个用例失败则停止测试  pytest -vs -x-maxfail 出现几个失败才终止-html生成html的测试报告(插件:pytest -html) pytest -vs --html ./reports/result.html-k运行测试用例名称中包含某个字符串的测试用例 pytest -vs -k “baili or xingyao”2、通过main方式执行if __name__ == '__main__':    pytest.main(["-vs"])3、通过全局配置文件pytest.ini文件执行,一般放在项目的根目录下1、可以改变默认的测试用例规则2、主函数和命令行都可以加载3、测试用例分组执行4、 -m “smoke’只执行冒烟用例   @pytest.mark.smoke[pytest]addopts = -vs --alluredir=./temps --clean-alluredirtestpaths = ./testcasepython_files = test_*.pypython_classes = Test*python_functions = test_*pytest如何跳过测试用例:()1、无理由跳过 2、有理由跳过import pytest@pytest.mark.skip(reason = "无理由跳过")def test01():    print("测试")@pytest.mark.skipif(12>10,reason = "有理由跳过")def test02():    print("测试01")def test03():    print("测试03")if __name__ == '__main__':    pytest.main(['-vs'])Pytest测试用例的前后置,setup和teardown,不同等级,封装在一个公共包、公共类里面函数级别、类级别模块级:setup_module/teardown_module函数级:setup_function/teardown_function类级:setup_class/teardown_class类中的方法级:setup_method/teardown_method使用fixture实现部分前后置(共享初始化、清理代码)1、scope:作用域  @pytest.fixture(scope = “function”,autouse = True)Function:在函数之前或者之后执行(可以手动调用,也可以自动执行),有return或者yield返回值,可以把这个值传递到测试用例当中,yield后置Return和yield区别:1、返回某个值,返回后函数不在继续执行彻底结束2、yield生成器 返回结果后函数不结束 暂定 再次调用时暂定的地方继续执行,可执行多次@pytest.fixture(scope = "function",autouse=True)def func():    print("我是前置步骤")    yield    print("我是后置步骤")Class:在类之前和类之后执行,自动执行或者手动调用(@pytest.mark.usefixtures(“exe_sql”))    @pytest.mark.usefixtures(“”)Package、session:在整个项目会话之前和之后执行,需要结合contest.py文件使用2、autouse:自动执行,默认是False3、Params:实现参数化,如何把值传到fixture,通过fixture函数的参数里面加入request来接收这个参数,可以通过request.param取值@pytest.fixture(scope ="function",autouse=False,params=read_yaml())def exe_database_sql(request):    print(request.param)    print("执行sql查询")    yield    print("关闭数据库连接")4、ids:不能单独使用,必须和params一起使用,作用是对参数起别名@pytest.fixture(scope ="function",autouse=False,params=read_yaml(),ids=['z','m'])5、name:给fixture起别名,一旦使用,只能用别名Fixtrue结合conftest.py文件使用:1、conftest.py专门用来存放fixtrue的配置文件2、在conftest.py文件里面所有的方法在调用时都不需要导包3、Conftest.py文件可以有多个,并且conftest.py文件里面的多个fixtrue可以被同一个用例调用优先级:fixture的sessionfixture的classSetup_classfixture的functionSetuppytest执行过程:1、查找当前目录下的conftest.py文件2、查找当前目录下的pytest.ini文件(找测试用例的位置)3、查找用例目录下的conftest.py4、查找py文件中是否有setup、teardown、setup_class、tear_class5、在根据pytest.ini文件中的测试用例规则去查找用例并执行Pytest断言:assertAllure-pytest插件生成更美观的报告1、安装插件2、下载allure,解压,解压后配置环境变量3、验证allure   https://www.cnblogs.com/lirongyu-test/p/16656478.html4、生成allure报告a、生成临时的json报告,在pytest.ini文件里面加入以下内容addopts = -vs --alluredir=./temps --clean-alluredirb、生成更美观的allure报告c、定制化Pytest之parametrize()实现数据驱动,@pytest.mark.parametrize(args_name,args_value),args_name:参数名称,用于将参数的值传递给函数;args_value:参数值(列表和字典列表,元祖和字典元祖),有n个值用例执行n次#单参数单次循环@pytest.mark.parametrize("name",['老白'])def test_parametrize01(name):    print("测试参数化"+name)#单参数多次循环,运行时将数组里的值分别赋值给变量,每赋值一次,运行一次@pytest.mark.parametrize("name",['老白','老黑'])def test_parametrize02(name):    print("测试参数化" + name)#可以数组\可以元祖@pytest.mark.parametrize("name,word",[['老白','123'],['老黑','456']])def test_parametrize03(name,word):    print(f'{name}的台词是{word}')Yaml格式测试用例读写封装1、yaml是一种数据格式,扩展名可以使yaml.xml,#注释 ,缩进表示层级关系,区分大小写yaml读取出来是一个字典列表  每加一次就多一个用例2、用于做配置文件(yaml.ini);用于编写自动化测试用例-  name: 获取统一的鉴权码  request:    method: get    url: https://api.weixin.qq.com/cgi-bin/token    data:      grant_type: client_credential      appid: ***      secret: ***  validate: None实战项目分享一、requests使用1)testcase:定义测试用例 1、导包 2、定义登录方法3、定义测试数据 4、发送post请求 5、输出结果#1、导包import requests#2、定义登录方法def login():    #3、定义测试数据    url = 'https://api.weixin.qq.com/cgi-bin/token'    params = {        "grant_type":"client_credential",        "appid":"wx71385b4e0a37259d",        "secret":"8963b6138d123eb0edf9fb5d8f453c8f"    }    #4、发送post、get请求    r = requests.get(url=url,params = params)    #5、输出结果    print(r.json())2)utils:封装公共方法  封装get和post方法:1、创建封装get和post的方法 2、发送requests get或post请求 3、获取结果相应内容 4、内容存到相应字典 5、字典返回 #单独封装get请求def request_get(url,params):    r = requests.get(url,params = params)    code = r.status_code    try:        body = r.json()    except Exception as e:        body = r.text    res = dict()    res['code'] = code    res['body'] = body    return res#get方法调用r = request_get(url,params = params)print(r)    #单独封装post请求    def request_post(url,params,json):        r = requests.post(url,params = params,json = json)        code = r.status_code        try:            body = r.json()        except Exception as e:            body = r.text        res = dict()        res["code"] = code        res['body'] = body        return res#post方法调用r = request_post(url,params=params,json = json)print(r)get和post方法重构:1、定义一个类 2、定义判断方法:如果是get发送get方法,如果是post发送post方法  获取相应的code  body 3、重构get post方法  4、在测试用例里面调用  初始化类 调用相应的get post方法#重构:1、创建类 2、定义公共方法 3、重构get和post方法class Request:    def request_api(self,url,data = None,params = None,json = None,cookies = None,method = "get"):        #1、增加方法的参数,根据参数来验证方法get / post请求,方法请求        if method == "get":            r = requests.get(url, params=params, json=json,cookies = cookies)        elif method == "post":            r = requests.post(url, params=params, json=json,cookies = cookies)        # 2、重复的内容,复制进来        code = r.status_code        try:            body = r.json()        except Exception as e:            body = r.text        res = dict()        res['code'] = code        res['body'] = body        return res#get、post方法重构:1、定义方法 2、定义参数(可变参数) 3、调用公共方法    def get(self,url,**kwargs):        #url method json headers cookies        return self.request_api(url,method = "get",**kwargs)    def post(self,url,**kwargs):        return self.request_api(url,method = "post",**kwargs)#调用:1、初始化类 2、接收get post方法 3、打印信息request = Request()r = request.post(url,params = params,json = json)print(r)二、yaml配置文件yaml文件格式:字典和列表字典:1、字典里的键值对“:”分隔 2、字典直接写key和value,每一个键值对占一行 3、后面要有空格name: "test_yaml"result: "sucess"列表:1、一组按序排列的值(简称序列或列表)2、数组前加有“-”符号,符号与值之间需要用空格分隔#["a","b","c"]- "a"- "b"- "c"1、字典嵌套字典#{person1:{"name":"xiaoming","age":"18"},person2:{"name":"xiaohong","age":"20"}}person1: name: xiaoming age: 18person2: name: xiaohong age: 202、字典嵌套列表#{person:["a","b","c"]}person: - "a" - "b" - "c"3、列表嵌套列表- - "a" - "b" - "c"- - "1" - "2" - "3"4、列表嵌套字典#[{"username1":"test1",{"password1":"111","username2":"test2"}}]- username1: "test1"- password1: "111"  username2: "test2"读取文件:1、读取单个文件2、读取多个文件# 1、创建yaml格式文件# 2、读取这个文件 (1、导入yaml包 2、打开文件 3、使用yaml读取文件)  字典格式 :注意空格# 3、输出这个文件#读取单个文档import yamlwith open("./data.yml","r",encoding="utf-8") as f:    r = yaml.safe_load(f)    print(r)#读取多个文档---"用户名称1": "text123""密码": "123456"---"用户名称1": "text456""密码": "123456"#1、编辑或修改data.yml 2、yaml 读物方法,all 3、循环打印import yamlwith open("./data.yml","r",encoding="utf-8") as f:    r = yaml.safe_load_all(f)    for i in r:        print(i)utils包-创建yamlReader类,初始化类读取yaml文件:1、创建一个YamlReader类 2、初始化,判断文件是否存在   os.path.existd()  不存在就抛出异常   初始化文件的内容dat  3、读取单个文件  没数据返回初始化数据 有数据返回读取到的数据 4、读取多个文件  没数据返回初始化数据 有数据返回读取到的数据 (list接收)#1、创建类 2、初始化,文件是否存在 3、yaml文件读取import osimport yamlclass YamlReader:    #初始化,判断文件是否存在    def __init__(self,yamlIf):        if os.path.exists(yamlIf):            self.yamlIf = yamlIf        else:            raise FileNotFoundError("文件不存在")        self._data = None        self._data_all = None#yaml读取    #单个文档读取    def data(self):        #第一次调用data,读取yaml文档,如果不是,直接返回之前保存的数据        if not self._data:            with open(self.yamlIf,"rb") as f:                self._data = yaml.safe_load(f)        return self._data    #多个文档读取    def data_all(self):        #第一次调用data,读取yaml文档,如果不是,直接返回之前保存的数据        if not self._data_all:            with open(self.yamlIf,"rb") as f:                self._data_all = list(yaml.safe_load_all(f))        return self._data_all#yaml_demo.py文件中调用from utils.YamlUtil import YamlReader# res = YamlReader("./data.yml").data()res = YamlReader("./data.yml").data_all()print(res)config包:1、创建yaml文件:填写url相关信息  2、创建conf.py文件1)获取conf.yaml的目录2读取conf.yaml文件import osfrom utils.YamlUtil import YamlReader#1、获取项目基本目录#获取当前项目的绝对路径current = os.path.abspath(__file__)# print(current)BASE_DIR  = os.path.dirname(os.path.dirname(current) )  #获取父级目录,获取两次#定义config目录的路径_config_path = BASE_DIR + os.sep + "config"#定义conf.yml文件的路径_config_file = _config_path + os.sep +"conf.yaml"#变量是私有的,定义一个方法访问def get_config_path():    return _config_pathdef get_config_file():    return _config_file#2、读取配置文件#创建类class ConfigYaml:    #初始yaml读取配置文件    def __init__(self):        self.config = YamlReader(get_config_file()).data()#定义方法获取需要的信息    def get_conf_url(self):        return self.config["BASE"]["test"]["url"]if __name__ == '__main__':    conf_read = ConfigYaml()    print(conf_read.get_conf_url())#以上方法用来读取yaml配置文件的url,以下代码用来在测试用例中获取urlconf_y = ConfigYaml()url_path = conf_y.get_conf_url()url = url_path + "/tags/get"三、日志文件logging模块是python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径等#log_demo.py#1、导入logging包import logging#2、设置配置信息logging.basicConfig(level=logging.INFO,format = '%(asctime)s - %(name)s-%(levelname)s-%(message)s')#3、定义日志名称getloggerlogger = logging.getLogger("log_demo")#4、info、debuglogger.info("info")logger.debug("debug")logger.warning("warning")日志输出控制台或文件:1、设置logger名称2、设置log级别3、创建hander,用于输出控制台或写入日志文件4、设置日志级别5、定义handler的输出格式6、添加handler#输出控制台import logging# 1、设置logger名称logger = logging.getLogger("log_file_demo")# 2、设置log级别logger.setLevel(logging.INFO)# 3、创建handlerfh_stream = logging.StreamHandler()# 4、设置日志级别fh_stream.setLevel(logging.INFO)#5、定义输出格式formatter = logging.Formatter('%(asctime)s %(name)s %(levelname) %(message)s')fh_stream.setFormatter(formatter)#6、添加handlerlogger.addHandler(fh_stream)#7、运行输出logger.info("this is a info")logger.debug(fh_stream)#写入文件import logging# 1、设置logger名称logger = logging.getLogger("log_file_demo")# 2、设置log级别logger.setLevel(logging.INFO)# 3、创建handlerfh_stream = logging.StreamHandler()#写入文件fh_file = logging.FileHandler("./test.log")# 4、设置日志级别fh_stream.setLevel(logging.INFO)fh_file.setLevel(logging.INFO)#5、定义输出格式formatter = logging.Formatter('%(asctime)s %(name)s %(levelname)s %(message)s')fh_stream.setFormatter(formatter)fh_file.setFormatter(formatter)#6、添加handlerlogger.addHandler(fh_stream)logger.addHandler(fh_file)#7、运行输出logger.info("this is a info")logger.debug("this is a debug")四、pytest基本使用pytest demo:步骤:1、创建普通方法 2、创建测试方法 3、pytest断言import pytestdef func(x):    return x+1@pytest.mark.flaky(reruns=3,reruns_delay=2)  #部分失败重跑,--reruns n --reruns-delay(出错重试的时间)def test_a():    print("---test a---")    assert func(3) == 5def test_b():    print("---test b ---")    assert func(4) == 5if __name__ == '__main__':    pytest.main(["-vs","pytest_demo.py"])setup teardown:函数级别的方法,运行于测试方法的始末;setup_class teardown_class:类级别方法,运行于测试类始末import pytest#1、定义类class TestFunc:    # 3、创建setup teardown    def setup(self):        print("setup")    def teardown(self):        print("teardown")    #2、创建测试方法test开头    def test_a(self):        print("testaaa")    def test_b(self):        print("testbbb")# 4、运行查看结果if __name__ == '__main__':    pytest.main(["-vs","pytest_func.py"])import pytestclass TestClass:    def setup_class(self):        print("setup")    def teardown_class(self):        print("teardown")    def test_a(self):        print("testaaa")    def test_b(self):        print("testbbb")if __name__ == '__main__':    pytest.main(["-vs","pytest_class.py"])parametrize参数化:1、单个参数 2、多个参数import pytest#传入单个参数:@pytest.mark.parametrize(argnames,argvalues)第一个参数为参数名 第二个参数为参数对应值,类型必须为可迭代类型,一般使用list# 1、创建类和测试方法class TestDemo:    # 2、创建测试数据    data_list = ["xiaoxiao","xixi"]    # 3、参数化    @pytest.mark.parametrize("name",data_list)    def test_a(self,name):        print("test_a")        print(name)        assert 1if __name__ == '__main__':    pytest.main(["-vs","pytest_one.py"])import pytest#传入多个参数 list的每一个元素都是一个元祖,元祖里的每个元素和按参数顺序一一对应# 1、创建类和测试方法class TestDemo:    # 2、创建测试数据    data_list = [("xiaoxiao","123456"),("xixi","345678")]    # 3、参数化    @pytest.mark.parametrize(("name","password"),data_list)    def test_a(self,name,password):        print("test_a")        print(name,password)        assert 1if __name__ == '__main__':    pytest.main(["-vs","pytest_two.py"])断言:自动化最终目的,一个用例没有断言,就失去了自动化测试的意义了;assert;预期结果和实际结果做对比常用断言import pytestdef test_01():    a = True    assert adef test_02():    a = True    assert not adef test_03():    a = "hello"    b = "hello world"    assert a in bdef test_04():    a = b = "hello"    assert a==bdef test_05():    a="hello"    b = "hello world"    assert a != bif __name__ == '__main__':    pytest.main(["pytest_assert.py"])结果断言验证1、断言应用接口用例:返回状态码、结果验证   返回的code、返回的body包含信息是否正确#封装结果断言import jsonfrom utils.LogUtil import my_log#1、定义封装类class AssertUtil:    #2、初始化数据,日志    def __init__(self):        self.log = my_log("AssertUtil")    #3、code相等    def assert_code(self,code,expected_code):        try:            assert int(code) == int(expected_code)            return True        except:            self.log.error("code error,code is %s,excepted_code is %s"%(code,expected_code))            raise    #4、body相等    def assert_body(self,body,expected_body):        try:            assert body == expected_body            return True        except:            self.log.error("body error,body is %s,expected_body is %s"%(body,expected_body))            raise    #5、body包含    def assert_in_body(self,body,expected_body):        #验证返回的结果是否包含期望的结果        try:            body = json.dumps(body)            assert expected_body in body            return True        except:            self.log.error("不包含或者body是错误,body is %s,expected_body is %s"%(body,expected_body))            raise#接口用例应用from utils.AssertUtil import AssertUtilcode = r['code']AssertUtil().assert_code(code,200)# body = json.dump(r["body"])# AssertUtil().assert_body(body,'"user_id":1,"username":"zzz"')数据库结果断言接口请求、返回结果验证1、pymysql 2、工具类封装#1、导包 2、连接database 3、获取执行sql的光标对象 4、执行sql 5、关闭对象import pymysqlconn = pymysql.connect(    host = '',    user = '',    password='',    database='',    charset='',    port = 7090)cursor = conn.cursor()sql = "select username,password from tb_users"cursor.execute(sql)res = cursor.fetchone()print(res)cursor.close()conn.close()1、创封装类 2、初始化数据、连接数据库、光标对象 3、创建查询、执行方法 4、关闭对象 import pymysqlfrom utils.LogUtil import my_logclass Mysql:    def __init__(self,host,user,password,database,charset = "utf8",port = 3306):       self.log = my_log()       self.conn = pymysql.connect(            host=host,            user=user,            password=password,            database=database,            charset=charset,            port=port        )       self.cursor = self.conn.cursor()    def fetchone(self,sql):        self.cursor.execute(sql)        return self.cursor.fetchone()    def fetchall(self,sql):        self.cursor.execute(sql)        return self.cursor.fetchall()    def exec(self):        try:            if self.conn and self.cursor:                self.cursor.execute(sql)                self.conn.commit()        except Exception as ex:            self.conn.rollback()            self.log.error("mysql执行失败")            self.log.error(ex)            return False        return True    def __del__(self):        if self.cursor is not None:            self.cursor.close()        if self.conn is not None:            self.cursor.close()五、数据驱动数据参数化:目的数据和代码进行分离yaml数据驱动、excel数据驱动1、编写yaml文件放置在data目录下 2、创建读取yaml文件的方法列表方式:多个文档---"case_name": "success""url": "/cgi-bin/tags/create/""data":  tag:    name: "guangdong""except": '"code":200'---"case_name": "fail""url": "/cgi-bin/tags/create/""data":  tag:    name: """except": '"code":200'1、conf目录下conf.py添加data目录的路径 2、读取yaml文件路径、读取yaml文件内容#获取路径_data_path = BASE_DIR + os.sep + "data"def get_data_path():    return _data_path#1、获取测试用例内容:获取yaml文件路径、使用工具类读取多个文档内容 #2、参数化执行import osimport pytestfrom config import conffrom utils.YamlUtil import YamlReaderfrom config.conf import ConfigYamlfrom utils.RequestsUtil import Request#1、获取测试用例内容:获取testlogin.yml文件路径;使用工具类读取多个文档内容test_file = os.path.join(conf.get_data_path(),'testlogin.yml')# print(test_file)data_list = YamlReader(test_file).data_all()# print(data_list)#2、参数化执行测试用例@pytest.mark.parametrize("tagadd",data_list)def test_yaml(tagadd):    url = ConfigYaml().get_conf_url()+tagadd["url"]    # print(url)    data = tagadd['data']    # print(data)    request = Request()    res = request.post(url,json = data)    print(res)if __name__ == '__main__':    pytest.main(["-vs","test_tagadd.py"])2、编写测试用例:读取excel数据(导入包:xlrd;创建wordbook对象;sheet对象;读取每行、读取每列、读取固定列的内容)用例设计、excel读取、excel参数化demo:把创建好的excel用例放在t_excel下,创建demo简单测试#1、导包import xlrd#2、创建workbook对象book = xlrd.open_workbook("testdata.xls")#3、sheet对象sheet = book.sheet_by_index(0)#4、获取行数和列数rows = sheet.nrowscols = sheet.ncols#5、读取每行、每列for r in range(rows):    r_values = sheet.row_values(r)    # print(r_values)for c in range(cols):    r_values = sheet.col_values(c)    # print(r_values)#6、读取固定列的内容print(sheet.cell(1,1))excel工具类封装:#目的:参数化,pytest, listimport osimport xlrdclass SheetTypeError:    pass#1、验证文件是否存在,存在读取,不存在报错class ExcelReader:    def __init__(self,excel_file,sheet_by):        if os.path.exists(excel_file):            self.excel_file = excel_file            self.sheet_by = sheet_by            self._data = list()        else:            raise FileNotFoundError("文件不存在")#2、读取sheet名称 索引    def data(self):        #存在不读取,不存在读取        if not self._data:            wordbook = xlrd.open_workbook(self.excel_file)            if type(self.sheet_by) not in [str,int]:                raise SheetTypeError("请输入整数或字符串")            elif type(self.sheet_by) == int:                sheet = wordbook.sheet_by_index(self.sheet_by)            elif type(self.sheet_by) == str:                sheet = wordbook.sheet_by_name(self.sheet_by)    #3、读取sheet内容        #返回list 字典 [{"a":11,"b":"12"} {"a":22,"b":b2}]        #1、获取首行信息 2、遍历测试行 与首行组成dict 放在list            title = sheet.row_values(0)            for col in range(1,sheet.nrows):                col_value = sheet.row_values(col)                self._data.append(dict(zip(title,col_value)))#4、结果返回        return self._dataif __name__ == '__main__':    reader = ExcelReader("../data/testdata.xls","Sheet1")    print(reader.data())excel参数化运行:获取是否运行、参数化、结果断言from utils.ExcelUtil import ExcelReader#1、使用excel工具类,获取结果listreader = ExcelReader("../data/testdata.xls","Sheet1")# print(reader.data())#2、列是否运行内容  yrun_list = list()for line in reader.data():    if line["是否运行"] == "y":        # print(line)#3、保存要执行结果,放到新的列表        run_list.append(line)print(run_list)将excel参数化  封装为方法:#common-dataconfig:#定义类  定义列属性class DataConfig:    case_id = "用例ID"    case_model = "模块"    case_name = "接口名称"    url = "请求url"    pre_exec = "前置条件"    method = "请求类型"    params_type = "请求参数类型"    params = "请求参数"    expect_result = "预期结果"    actual_result = "实际结果"    is_run = "是否运行"    headers = "headers"    cookies = "cookies"    code = "status_code"    db_verify = "数据库验证"#common-exceldata.pyfrom utils.ExcelUtil import ExcelReaderfrom common.ExcelConfig import DataConfigclass Data:    #1、使用excel工具类,获取结果list    def __init__(self,testcase_file,sheet_name):        # self.reader = ExcelReader("../data/testdata.xls", "Sheet1")        self.reader = ExcelReader(testcase_file,sheet_name)    #2、列是否运行内容  y    def get_run_data(self):        #根据是否运行列==y  获取执行测试用例        run_list = list()        for line in self.reader.data():            if str(line[DataConfig().is_run]).lower() == "y":                # print(line)        #3、保存要执行结果,放到新的列表                run_list.append(line)        print(run_list)        return run_list#conf获取路径def get_excel_file(self):    #获取测试用例名称    return self.config["BASE"]["test"]["testcase_file"]def get_excel_sheet(self):    #获取测试用例名称    return self.config["BASE"]["test"]["case_sheet"]  初始化信息,执行测试用例import jsonimport pytestfrom config.conf import ConfigYamlimport osfrom common.ExcelData import Datafrom utils.LogUtil import my_logfrom common import ExcelConfigfrom utils.RequestsUtil import Request#1、初始化信息#1)初始化测试用例文件case_file = os.path.join("../data",ConfigYaml().get_excel_file())#2)测试用例sheet名称sheet_name = ConfigYaml().get_excel_sheet()#3)获取运行测试用例列表run_list = Data(case_file,sheet_name).get_run_data()#4)日志log = my_log()#2、测试用例方法,参数化运行#一个用例的执行#1、初始化信息  2、接口请求class TestExcel:    #1、增加pytest 2、修改方法参数 3、重构函数内容 4、pytest.main    @pytest.mark.parametrize("case",run_list)    def test_run(self,case):        data_key = ExcelConfig.DataConfig        #run_list第一个用例  key获取values        url = ConfigYaml().get_conf_url()+case[data_key.url]        case_id = case[data_key.case_id]        case_model = case[data_key.case_model]        case_name = case[data_key.case_name]        pre_exec = case[data_key.pre_exec]        method = case[data_key.method]        params_type = case[data_key.params_type]        params = case[data_key.params]        expect_result = case[data_key.expect_result]        actual_result = case[data_key.actual_result]        is_run = case[data_key.is_run]        headers = case[data_key.headers]        cookies = case[data_key.cookies]        code = case[data_key.code]        #接口请求        request = Request()        #params转义json        if len(str(params).strip()) is not 0:            params = json.loads(params)        #method get post        if str(method).lower()=="get":            res = request.get(url,json = params)        elif str(method).lower()=="post":            res = request.post(url, json=params)        else:            log.error("错误的请求")        print(res)if __name__ == '__main__':    pytest.main(['-s','test_excel_case.py'])pytest.ini[pytest]addopts = -s --html=./report/report.htmltestpaths = testcasepython_files = test_*.pypython_classes = Test_*python_functions = test_*
点赞 4
评论 2
全部评论

相关推荐

喜欢吃蛋糕仰泳鲈鱼是我的神:字节可以找个hr 给你挂了,再放池子捞
点赞 评论 收藏
分享
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务