zoukankan      html  css  js  c++  java
  • pytest_06_fixture之yield实现teardown

    上一篇讲到fixture通过scope参数控制setup级别,既然有setup作为用例之前前的操作,用例执行完之后那肯定也有teardown操作。
    这里用到fixture的teardown操作并不是独立的函数,用yield关键字呼唤teardown操作

    scope="module"

    1.fixture参数scope="module",module作用是整个.py文件都会生效,用例调用时,参数写上函数名称就行

    # coding:utf-8
    import pytest
    
    @pytest.fixture(scope="module")
    def open():
        print("打开浏览器,并且打开百度首页")
    
    def test_s1(open):
        print("用例1:搜索python-1")
    
    def test_s2(open):
        print("用例2:搜索python-2")
    
    def test_s3(open):
        print("用例3:搜索python-3")
    
    if __name__ == "__main__":
        pytest.main(["-s", "test_f1.py"])

    运行结果:

    D:Users18630AppDataLocalProgramsPythonPython36python3.exe E:/Programs/ke4/pytest/learn_06.py
    ============================= test session starts =============================
    platform win32 -- Python 3.6.4, pytest-3.8.0, py-1.6.0, pluggy-0.7.1
    rootdir: E:Programske4pytest, inifile:
    collected 3 items
    
    learn_06.py 打开浏览器,并且打开百度首页
    用例1:搜索python-1
    .用例2:搜索python-2
    .用例3:搜索python-3
    .
    
    ========================== 3 passed in 0.09 seconds ===========================
    
    Process finished with exit code 0

    从结果看出,虽然test_s1,test_s2,test_s3三个地方都调用了open函数,但是它只会在第一个用例前执行一次

    2.如果test_s1不调用,test_s2(调用open),test_s3不调用,运行顺序会是怎样的?

    # coding:utf-8
    import pytest
    
    @pytest.fixture(scope="module")
    def open():
        print("打开浏览器,并且打开百度首页")
    
    def test_s1():
        print("用例1:搜索python-1")
    
    def test_s2(open):
        print("用例2:搜索python-2")
    
    def test_s3():
        print("用例3:搜索python-3")
    
    if __name__ == "__main__":
        pytest.main(["-s", "learn_06.py"])

    运行结果:

    D:Users18630AppDataLocalProgramsPythonPython36python3.exe E:/Programs/ke4/pytest/learn_06.py
    ============================= test session starts =============================
    platform win32 -- Python 3.6.4, pytest-3.8.0, py-1.6.0, pluggy-0.7.1
    rootdir: E:Programske4pytest, inifile:
    collected 3 items
    
    learn_06.py 用例1:搜索python-1
    .打开浏览器,并且打开百度首页
    用例2:搜索python-2
    .用例3:搜索python-3
    .
    
    ========================== 3 passed in 0.09 seconds ===========================
    
    Process finished with exit code 0

    从结果看出,module级别的fixture在当前.py模块里,只会在用例(test_s2)第一次调用前执行一次

    yield执行teardown

    1.前面讲的是在用例前加前置条件,相当于setup,既然有setup那就有teardown,fixture里面的teardown用yield来唤醒teardown的执行

    # coding:utf-8
    import pytest
    
    
    @pytest.fixture(scope="module")
    def open():
        print("打开浏览器,并且打开百度首页")
    
        yield
        print("执行teardown!")
        print("最后关闭浏览器")
    
    def test_s1(open):
        print("用例1:搜索python-1")
    
    def test_s2(open):
        print("用例2:搜索python-2")
    
    def test_s3(open):
        print("用例3:搜索python-3")
    
    if __name__ == "__main__":
        pytest.main(["-s", "test_f1.py"])

    运行结果:

    ============================= test session starts =============================
    platform win32 -- Python 3.6.0, pytest-3.6.3, py-1.5.4, pluggy-0.6.0
    rootdir: D:\, inifile:
    collected 3 items
    
    ............	est	est_f1.py 打开浏览器,并且打开百度首页
    用例1:搜索python-1
    .用例2:搜索python-2
    .用例3:搜索python-3
    .执行teardown!
    最后关闭浏览器
    
    
    ========================== 3 passed in 0.01 seconds ===========================
     

    yield遇到异常

    1.如果其中一个用例出现异常,不影响yield后面的teardown执行,运行结果互不影响,并且全部用例执行完之后,yield呼唤teardown操作

    # coding:utf-8
    import pytest
    
    @pytest.fixture(scope="module")
    def open():
        print("打开浏览器,并且打开百度首页")
        yield
        print("执行teardown!")
        print("最后关闭浏览器")
    
    def test_s1(open):
        print("用例1:搜索python-1")
    
        # 如果第一个用例异常了,不影响其他的用例执行
        raise NameError  # 模拟异常
    
    def test_s2(open):
        print("用例2:搜索python-2")
    
    def test_s3(open):
        print("用例3:搜索python-3")
    
    if __name__ == "__main__":
        pytest.main(["-s", "test_f1.py"])

    运行结果:

    打开浏览器,并且打开百度首页
    用例1:搜索python-1
    F
    open = None
    
        def test_s1(open):
            print("用例1:搜索python-1")
        
            # 如果第一个用例异常了,不影响其他的用例执行
    >       raise NameError  # 模拟异常
    E       NameError
    
    D:	est	est_f1.py:16: NameError
    用例2:搜索python-2
    .用例3:搜索python-3
    .执行teardown!
    最后关闭浏览器
     

    2.如果在setup就异常了,那么是不会去执行yield后面的teardown内容了

    3.yield也可以配合with语句使用,以下是官方文档给的案例

    # 官方文档案例
    # content of test_yield2.py
    
    import smtplib
    import pytest
    
    @pytest.fixture(scope="module")
    def smtp():
        with smtplib.SMTP("smtp.gmail.com") as smtp:
            yield smtp  # provide the fixture value

    addfinalizer终结函数

    1.除了yield可以实现teardown,在request-context对象中注册addfinalizer方法也可以实现终结函数。

    # 官方案例
    
    # content of conftest.py
    import smtplib
    import pytest
    
    @pytest.fixture(scope="module")
    def smtp_connection(request):
        smtp_connection = smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
        def fin():
            print("teardown smtp_connection")
            smtp_connection.close()
        request.addfinalizer(fin)
        return smtp_connection  # provide the fixture value

    2.yield和addfinalizer方法都是在测试完成后呼叫相应的代码。但是addfinalizer不同的是:

    • 他可以注册多个终结函数。

    • 这些终结方法总是会被执行,无论在之前的setup code有没有抛出错误。这个方法对于正确关闭所有的fixture创建的资源非常便利,即使其一在创建或获取时失败

    作者:含笑半步颠√

    博客链接:https://www.cnblogs.com/lixy-88428977

    声明:本文为博主学习感悟总结,水平有限,如果不当,欢迎指正。如果您认为还不错,欢迎转载。转载与引用请注明作者及出处。

  • 相关阅读:
    The Quad
    将OrCAD Capture CIS的设计文件(.dsn)导入到PADS Logic VX.2.3
    OrCAD Capture CIS 16.6 将版本16.6的设计文件另存为版本16.2的设计文件
    Eclipse IDE 添加jar包到Java工程中
    PADS Logic VX.2.3 修改软件界面语言
    切换Allegro PCB Editor
    Allegro PCB Design GXL (legacy) 将brd文件另存为低版本文件
    Allegro PCB Design GXL (legacy) 设置自动保存brd文件
    Could not create an acl object: Role '16'
    windows 下apache开启FastCGI
  • 原文地址:https://www.cnblogs.com/lixy-88428977/p/9614131.html
Copyright © 2011-2022 走看看