对于实现的接口代码,如登陆,我们常常会有多种情况的登陆,但其实本质就是每次发送登陆的请求参数不一样,我们如何只写一个测试接口,实现我们多条不同数据的登陆呢?

1、固件/前后置处理方法

'''
 pytest fixture仓库 ,全部是都fixture内容
 '''import pytest
from global_session import global_session as s
 @pytest.fixture()
 def login():
     '''
     封装登录 前置步骤
     :return:
     '''    url = "  "
     x = {
         "username": "  ",
         "password": "  ",
         "verifycode": "  "
     }
     s.post(url = url , data = x) # 发送post请求登录    print(id(s))
     yield
    # 退出
     s.close()

pytest main执行多个用例 pytest获取用例执行结果_优先级

核心配置文件

[pytest]
 addopts = -v -s  --setup-show  test_cases/test_batch_upload.py --alluredir=temp --clean-alluredir
 testpaths = ./test_casesmarkers = {smoke: smoking test case}

pytest main执行多个用例 pytest获取用例执行结果_pytest main执行多个用例_02

使用@pytest.fixture()装饰器实现部分用例的前后置

参数解释: 

注意事项:

  1. 如果一个测试用例,用到了多个fixture(少见),次序是,范围大的先执行,相同级别的。从左到右执行。
  2. fixture可以使用相同级别或者 级别高的fixture
  3. class级别的,并不是说,只能在class 里面的测试方法可以用!!!包括测试函数也可以用(行为 = 函数级别),只是测试用例封装在类里面。多个类里面的测试用例,class级别的fixture只会执行一次

4、使用usefixture装饰器指定使用fixture

4、实现参数化

(1)使用@pytest.fixture() 实现参数化

import pytest
# 数据fixture  返回测试数据
@pytest.fixture(params=[{"name":"zs"}, [1,2,3], "c"])
def my_fixture(request):
    print("这是我自己定义的前置的方法")
    yield request.param  # # 通过yield关键字 在后面填写后置的方法
    print("这是我自己定义的后置的方法")

class TestLogin():

    @pytest.mark.user
    def testaddsale(self, my_fixture):
        print("------->test_b------------>",my_fixture)
        assert 1  # 断言失败

if __name__ == '__main__':
    pytest.main(["-vs", "test_aaa.py"])  # 调用pytest的main函数执行测试
 
(2)使用@pytest.mark.parametrize()实现参数化
• scope表示的是被@pytest.fixture标记的方法的作用域
• function 默认 针对函数
• class 针对类
• module 针对模块
• package 针对包(没有实现)
• session 针对整个测试会话 开始执行pytest到结束 算一个测试会话
• params 实现参数化
• autouse=True 自动使用,默认是false,当为True时表示在它所作用域的范围内都会自动使用该装置
• ids 当使用params参数化时,给每一个值设置一个变量名。意义不大
• name 给被@pytest.fixture()标记的方法取一个别名,意义不大,起了别名后,原来的函数名称就不能使用
• 关于形参中出现 / * 的意义 python函数参数中的/和*是什么意思? - 知乎
• fixture默认是函数级别的,还有session级别,这2个最常用。module级别的也偶尔见到。
• 调用fixture的四种方法
• (1)函数或类里面方法直接传fixture的名称作为用例函数参数名称 import pytest

@pytest.fixture()
def my_fixture():
    print("这是我自己定义的前置的方法")
    yield  # 通过yield关键字 在后面填写后置的方法
    print("这是我自己定义的后置的方法")

class TestLogin():
    @pytest.mark.smoke
    def testsales(self):  # test开头的测试函数
        print("------->test_a")
        assert 1  # 断言成功

    @pytest.mark.user
    def testaddsale(self,my_fixture):
        print("------->test_b")
        assert 0  # 断言失败


if __name__ == '__main__':
    pytest.main(["-s","test_aaa.py"])  # 调用pytest的main函数执行测试 (2)使用装饰器@pytest.mark.usefixtures(fixture_name)修饰需要运行的用例 。
usefixtures装饰器除了可以装饰函数和类里面的方法外,还可以装饰类,而且其优先级还比传参方式的优先级高• 验证 @pytest.mark.usefixtures 和传参的形式的优先级 # 验证 @pytest.mark.usefixtures 和传参的形式的优先级
@pytest.fixture(scope="function")
def function1_fixture(request):
    print("这是我自己定义的function1前置的方法")
    yield   # # 通过yield关键字 在后面填写后置的方法
    print("这是我自己定义的function1后置的方法")
@pytest.fixture(scope="function")
def function2_fixture(request):
    print("这是我自己定义的function2前置的方法")
    yield   # # 通过yield关键字 在后面填写后置的方法
    print("这是我自己定义的function2后置的方法")

class TestLogin():

    @pytest.mark.usefixtures('function1_fixture')
    def testsales(self,function2_fixture):  # test开头的测试函数
        print("------->test_a")
        assert 1  # 断言成功

    def testaddsale(self):
        print("------->test_b")
        assert 0  # 断言失败

class TestLogin1():
    def testsales(self):  # test开头的测试函数
        print("------->test_a")
        assert 1  # 断言成功
    def testaddsale(self):
        print("------->test_b------------>")
        assert 1  # 断言失败

if __name__ == '__main__':
    pytest.main(["-vs", "test_aaa.py"])  # 调用pytest的main函数执行测试
 (3)验证类 使用fixture 及autouse的使用 及 不同级别作用域的fixture的优先级 import pytest

@pytest.fixture(scope="module",autouse=True)
def module_fixture(request):
    print("这是我自己定义的module前置的方法")
    yield   # # 通过yield关键字 在后面填写后置的方法
    print("这是我自己定义的module后置的方法")

@pytest.fixture(scope="class")
def class_fixture(request):
    print("这是我自己定义的class前置的方法")
    yield   # # 通过yield关键字 在后面填写后置的方法
    print("这是我自己定义的class后置的方法")

@pytest.fixture(scope="function")
def function1_fixture(request):
    print("这是我自己定义的function1前置的方法")
    yield   # # 通过yield关键字 在后面填写后置的方法
    print("这是我自己定义的function1后置的方法")
@pytest.fixture(scope="function")
def function2_fixture(request):
    print("这是我自己定义的function2前置的方法")
    yield   # # 通过yield关键字 在后面填写后置的方法
    print("这是我自己定义的function2后置的方法")

@pytest.mark.usefixtures('class_fixture')
class TestLogin():

    @pytest.mark.usefixtures('function1_fixture')
    def testsales(self,function2_fixture):  # test开头的测试函数
        print("------->test_a")
        assert 1  # 断言成功

    def testaddsale(self):
        print("------->test_b")
        assert 0  # 断言失败

class TestLogin1():
    def testsales(self):  # test开头的测试函数
        print("------->test_a")
        assert 1  # 断言成功
    def testaddsale(self):
        print("------->test_b------------>")
        assert 1  # 断言失败


if __name__ == '__main__':
    pytest.main(["-vs", "test_aaa.py"])  # 调用pytest的main函数执行测试

• 不同作用域的fixture,遵循:session > package > module > class > function
• 相同级别的fixture,且有依赖关系的fixture:遵循fixture之间的依赖关系 fixture 可以使用同级别或者以上级别的fixture
• fixture设置autouse=True
• 使用conftest.py文件共享fixture实例(主要用户项目的全局登陆,模块的全局处理,说白了就是其他地方都会调用的fixture可以写在conftest.py中)
• conftest.py单独用来存放固件的一个配置文件,名称不能更改
• 作用:可以在不同的py文件中使用同一个fixture函数。使用的时候也不需要导入conftest.py,pytest会自动寻找
• 一个工程下可以建多个conftest.py的文件,不同子目录下也可以放conftest.py的文件
• conftest.py文件的作用域是当前包内(包括子包)。如果有函数调用fixture,会优先从当前测试类中寻找,然后是模块(.py文件)中,接着是当前包中寻找(conftest.py中),如果没有再找父包直至根目录;如果我们要声明全局的conftest.py文件,我们可以将其放在项目根目录下。
• 相同级别的fixture,同时用装饰器和参数传递方式调用: usefixtures装饰的优先级高于传参形式的fixture
• 相同级别的fixture,都使用装饰器调用时,先执行的放底层,后执行的放上层
• 里面写两个参数,第一个参数是字符串,如果要表示多个参数每个参数中间用逗号隔开,第二个参数是list,表示传入的参数化数据 import pytest


class TestLogin():

    @pytest.mark.parametrize("data",[1,2,3])
    def test_1(self,data):  # test开头的测试函数
        print(f"------->test_1---------->data:{data}")


    @pytest.mark.parametrize("name,age",[['zs',18],['ls',15]])
    def test_2(self,name,age):
        print(f"------->test_2------->name:{name}---------age:{age}")

    @pytest.mark.parametrize("data",[['zs',18],['ls',15]])
    def test_3(self,data:list):
        print(f"------->test_3------->data:{data},data的type:{type(data)}")

    @pytest.mark.parametrize("data",[{"name":"zs","age":18},{"name":"ls","age":20}])
    def test_4(self,data:dict):
        print(f"------->test_4------->data:{data},data的type:{type(data)}")



if __name__ == '__main__':
    pytest.main(["test_aaa.py"])  # 调用pytest的main函数执行测试

  1. 装饰器有2个必填参数, 第一个参数,是字符串 ,第二个参数是列表( 元组,列表,多个字典)