• Pytest setup、teardown、fixture的详细使用


    一、setup、teardown使用案例

    1、代码

    '''
    @Date:2022/2/13  13:02
    @Author:GP
    '''
    import pytest
    
    def setup_module():
        print("=====整个.py模块开始前只执行一次:打开浏览器=====")
    
    def teardown_module():
        print("=====整个.py模块结束后只执行一次:关闭浏览器=====")
    
    def setup_function():
        print("===每个函数级别用例开始前都执行setup_function===")
    
    def teardown_function():
        print("===每个函数级别用例结束后都执行teardown_function====")
    
    def test_one():
            print("one")
    
    def test_two():
            print("two")
    
    class TestCase():
        def setup_class(self):
            print("====整个测试类开始前只执行一次setup_class====")
    
        def teardown_class(self):
            print("====整个测试类结束后只执行一次teardown_class====")
    
        def setup_method(self):
            print("==类里面每个用例执行前都会执行setup_method==")
    
        def teardown_method(self):
            print("==类里面每个用例结束后都会执行teardown_method==")
    
        def setup(self):
            print("=类里面每个用例执行前都会执行setup=")
    
        def teardown(self):
            print("=类里面每个用例结束后都会执行teardown=")
    
        def test_three(self):
            print("three")
    
        def test_four(self):
            print("four")
    
    if __name__ == '__main__':
        pytest.main(["-q", "-s", "-ra", "setup_test.py"])

    2、执行结果

     二、fixture的优势

    • 命名方式灵活,不局限于 setup 和teardown 这几个命名
    • conftest.py 配置里可以实现数据共享,不需要 import 就能自动找到fixture
    • scope="module" 可以实现多个.py 跨文件共享前置
    • scope="session" 以实现多个.py 跨文件使用一个 session 来完成多个用例

    三、Fixture参数列表

    @pytest.fixture(scope="function", params=None, autouse=False, ids=None, name=None)
    def test():
        print("fixture初始化的参数列表")
    • scope:可以理解成fixture的作用域,默认:function,还有class、module、package、session四个【常用】
    • autouse:默认:False,需要用例手动调用该fixture;如果是True,所有作用域内的测试用例都会自动调用该fixture
    • name:默认:装饰器的名称,同一模块的fixture相互调用建议写个不同的name

    注意 session的作用域:是整个测试会话,即开始执行pytest到结束测试

    四、Fixture的三种调用方法

    1、方式一:函数或类里面方法直接传fixture的函数参数名称

      定义fixture跟定义普通函数差不多,唯一区别就是在函数上加个装饰器@pytest.fixture(),fixture命名不要以test开头,跟用例区分开。

      fixture是有返回值的,没有返回值默认为None。

      用例调用fixture的返回值,直接就是把fixture的函数名称当做变量名称。

    import pytest
    
    @pytest.fixture()
    def test1():
        a = "南京"
        return a
    
    def test2(test1):
        assert test1 == "南京"
    
    if __name__ == '__main__':
        pytest.main("-s fixture_test.py")

    2、方式二:使用装饰器@pytest.mark.usefixtures()修饰需要运行的用例

    import pytest
    
    @pytest.fixture()
    def test1():
        a = "南京"
        print("fixture")
        return a
    
    def test2(test1):
        assert test1 == "南京"
    
    @pytest.fixture()
    def login():
        print("请先登录")
    
    @pytest.mark.usefixtures("login","test1")    
    def test3():
        print("用例1:调用fixture") 
    
    @pytest.mark.usefixtures("login")
    @pytest.mark.usefixtures("test1")
    def test4():
        '''
        叠加usefixtures:如果一个方法或者一个class用例想要同时调用多个fixture,
        可以使用@pytest.mark.usefixture()进行叠加。
        注意叠加顺序,先执行的放底层,后执行的放上层。
        :return: 
        '''
        print("用例2:叠加userfixture")
    
    if __name__ == '__main__':
        pytest.main("-s fixture_test.py")

    注意:usefixtures与传fixture区别

     如果fixture有返回值,那么usefixture就无法获取到返回值,这个是装饰器usefixture与用例直接传fixture参数的区别。

    当fixture需要用到return出来的参数时,只能讲参数名称直接当参数传入,不需要用到return出来的参数时,两种方式都可以。

    3、方式三:fixture自动使用autouse=True

    当用例很多的时候,每次都传这个参数,会很麻烦。fixture里面有个参数autouse,默认是False没开启的,可以设置为True开启自动使用fixture功能,这样用例就不用每次都去传参了,autouse设置为True,自动调用fixture功能

    import pytest
    
    @pytest.fixture(autouse=True)
    def login3():
        print("====auto===,自动执行该fixture")
    
    def test5():
        print("用例3:执行前自动执行fixture")
    
    if __name__ == '__main__':
        pytest.main("-s fixture_test.py")

     4、知识点

    • 在类声明上面加 @pytest.mark.usefixtures() ,代表这个类里面所有测试用例都会调用该fixture
    • 可以叠加多个 @pytest.mark.usefixtures() ,先执行的放底层,后执行的放上层
    • 可以传多个fixture参数,先执行的放前面,后执行的放后面
    • 如果fixture有返回值,用 @pytest.mark.usefixtures() 是无法获取到返回值的,必须用传参的方式(方式一)
    • 添加了 @pytest.fixture ,如果fixture还想依赖其他fixture,需要用函数传参的方式,不能用 @pytest.mark.usefixtures() 的方式,否则会不生效

    五、Fixture之yield实现teardown

      前面讲的,其实都是setup的操作,那么现在就来讲下teardown是怎么实现的

    import pytest
    
    @pytest.fixture(scope="session")
    def open():
        # 会话前置操作setup
        print("===打开浏览器===")
        test = "测试变量是否返回"
        yield test
        # 会话后置操作teardown
        print("==关闭浏览器==")
    
    
    @pytest.fixture
    def login(open):
        # 方法级别前置操作setup
        print(f"输入账号,密码先登录{open}")
        name = "==我是账号=="
        pwd = "==我是密码=="
        age = "==我是年龄=="
        # 返回变量
        yield name, pwd, age
        # 方法级别后置操作teardown
        print("登录成功")
    
    
    def test_s1(login):
        print("==用例1==")
        # 返回的是一个元组
        print(login)
        # 分别赋值给不同变量
        name, pwd, age = login
        print(name, pwd, age)
        assert "账号" in name
        assert "密码" in pwd
        assert "年龄" in age
    
    
    def test_s2(login):
        print("==用例2==")
        print(login)
    
    if __name__ == '__main__':
        pytest.main("-s fixture_test.py")

    六、Conftest.py的使用

    1、什么是conftest.py

    可以理解成一个专门存放fixture的配置文件

    2、实际开发场景

    多个测试用例文件(test_*.py)的所有用例都需要用登录功能来作为前置操作,那就不能把登录功能写到某个用例文件中去了

    3、如何解决上述场景问题?

    conftest.py的出现,就是为了解决上述问题,单独管理一些全局的fixture

    4、conftest.py配置fixture注意事项

    • pytest会默认读取conftest.py里面的所有fixture
    • conftest.py 文件名称是固定的,不能改动
    • conftest.py只对同一个package下的所有测试用例生效
    • 不同目录可以有自己的conftest.py,一个项目中可以有多个conftest.py
    • 测试用例文件中不需要手动import conftest.py,pytest会自动查找

    5、实例

           参考博客:https://www.cnblogs.com/poloyy/p/12663601.html

    1)目录结构

     2)HttprunnerProject目录下

    conftest.py代码

    最顶层的conftest,一般写全局的fixture,在Web UI自动化中,可能会初始化driver

    import pytest
    
    '''最顶层的conftest,一般写全局的fixture,在Web UI自动化中,可能会初始化driver'''
    
    @pytest.fixture(scope="session")
    def login():
        print("====登录功能,返回账号,token===")
        name="test"
        token="123bfdaj"
        yield name,token #如果有返回值,可以在yield后面直接写返回值就好了,如果有多个直接用(返回值1,返回值2)
        print("====退出登录!!!====")
    
    @pytest.fixture(autouse=True)
    def get_info(login):
        name,token=login
        print(f"== 每个用例都调用的外层fixture:打印用户token: {token} ==")

    test_conftest.py代码

    同级目录下的测试用例

    '''跟最顶层的conftest目录下的测试用例'''
    import pytest
    
    def test_get_info(login):
        name,token = login
        print("***基础用例:获取用户个人信息***")
        print(f"用户名:{name}, token:{token}")

    执行结果

     3)baidu目录下

    conftest.py代码

    配置一些针对baidu这个网站的测试用例独有的fixture,譬如:打开baidu网站

    '''baidu目录下的conftest.py,配置一些针对baidu这个网站的测试用例独有的fixture,譬如:打开baidu网站'''
    
    import pytest
    @pytest.fixture(scope="module")
    def open_baidu(login):
        name,token=login
        print(f"###用户 {name} 打开baidu网站###")

    test_baidu_conftest.py

    某个功能模块下的测试用例

    '''某个功能模块下的测试用例'''
    
    def test_case01(open_baidu):
        print("正确打开百度搜索")

    执行结果

  • 相关阅读:
    android应用程序的混淆打包
    sql 语句的limit的用法
    Android SDK开发包国内下载地址
    在android应用程序中启动其他apk程序
    docker+k8s基础篇五
    docker+k8s基础篇四
    docker+k8s基础篇三
    docker+k8s基础篇二
    docker+k8s基础篇一
    LVS的基础使用
  • 原文地址:https://www.cnblogs.com/Chilam007/p/15890271.html
Copyright © 2020-2023  润新知