一、Pytest前置setup后置teardown在用例中的运行级别
1. 模块级 setup_module/teardown_module
这是全局的,在模块始末
def setup_module():
print("整个py文件执行前执行一次前置")
def teardown_module():
print("整个py文件执行完执行一次后置")
def test_a():
print("case_aaaaaaaaaaaaa")
def test_b():
print("case_bbbbbbbbbbbbb")
def test_c():
print("case_ccccccccccccc")
运行结果如下所示:
2. 函数级 setup_function/teardown_function
只对函数用例生效,不在类中
每个用例的开始和结束调用一次
def setup_function():
print("前置-每条用例执行前都会执行一次前置")
def teardown_function():
print("后置-每条用例执行后都会执行一次后置")
def test_a():
print("case_aaaaaaaaaaaaa")
def test_b():
print("case_bbbbbbbbbbbbb")
def test_c():
print("case_ccccccccccccc")
执行结果如下所示:
3. 类级 setup_class/teardown_class
在类中的始末运行
setup/teardown和 unittest 里面的setup/teardown是一样的功能,
setup_class和 teardown_class 等价于 unittest 里面的 setupClass 和 teardownClass
class Test_cases:
def setup_class(self):
print("所有用例执行前执行一次前置")
def teardown_class(self):
print("所有用例执行完执行一次前置")
def test_a(self):
print("case_aaaaaaaaaaaaa")
def test_b(self):
print("case_bbbbbbbbbbbbb")
运行结果如下所示:
4. 方法级 setup_method/teardown_method
在类中的方法始末运行
等同于function
class Test_cases:
def setup_method(self):
print("每个用例执行前执行一次method前置")
def teardown_method(self):
print("每个用例执行完执行一次method后置")
def test_a(self):
print("case_aaaaaaaaaaaaa")
def test_b(self):
print("case_bbbbbbbbbbbbb")
def test_c(self):
print("case_ccccccccccccc")
运行结果如下所示:
5. 类里面setup/teardown设置在调用方法前后
等同于method,function
class Test_cases:
def setup(self):
print("每个用例执行前执行一次前置")
def teardown(self):
print("每个用例执行完执行一次后置")
def test_a(self):
print("case_aaaaaaaaaaaaa")
def test_b(self):
print("case_bbbbbbbbbbbbb")
def test_c(self):
print("case_ccccccccccccc")
运行结果如下:
如果把这些都放在一起,那会是怎样的一个执行顺序呢?
setup_function和teardown_function除外,不适用于类
def setup_module():
print("整个py文件执行前执行一次module前置")
def teardown_module():
print("整个py文件执行完执行一次module后置")
class Test_cases:
def setup(self):
print("每个用例执行前执行一次setup前置")
def teardown(self):
print("每个用例执行完执行一次teardown后置")
def setup_method(self):
print("每个用例执行前执行一次method前置")
def teardown_method(self):
print("每个用例执行完执行一次method后置")
def setup_class(self):
print("所有用例执行前执行一次class前置")
def teardown_class(self):
print("所有用例执行完执行一次class前置")
def test_a(self):
print("case_aaaaaaaaaaaaa")
def test_b(self):
print("case_bbbbbbbbbbbbb")
def test_c(self):
print("case_ccccccccccccc")
运行结果如下所示:
这里面没有setup/teardown,因为被method覆盖了。
我们可以得到优先级:
setup_module>setup_class>setup_method>setup_function>setup
Tips:
1. 系统内置的前置和后置操作无法进行参数变量的传递,前后置的变量无法给到某条用例,包括session.
2. 光标所在位置不同,执行pytest用例也不同。
光标在某个用例内部,则只执行该单个用例
其他位置,头部,用例之间,尾部,都是执行所有用例。
class Test_cases:
def setup(self):
s = "hhh"
print("每个用例执行前执行一次setup前置")
def teardown(self):
print("每个用例执行完执行一次teardown后置")
def setup_method(self):
a = "test"
print("每个用例执行前执行一次method前置")
def teardown_method(self):
print("每个用例执行完执行一次method后置")
def setup_class(self):
print("所有用例执行前执行一次class前置")
def teardown_class(self):
print("所有用例执行完执行一次class前置")
def test_a(self):
print(a) # 这里的a是无法定义的
print(s) # 这里的s是无法定义的
print("case_aaaaaaaaaaaaa")
那么,像这种变量参数无法传递的情况该怎么处理呢?或者说如果只针对多条用例中的其中一条或多条用例进行前置后置操作,该如何处理?我们可以用Fixture解决这些问题。
二、Pytest中Fixture的运用
fixture构造
源码注释
fixture_marker = FixtureFunctionMarker(
scope=scope,
params=params,
autouse=autouse,
ids=ids,
name=name,
)
"""
:param scope:
The scope for which this fixture is shared; one of ``"function"``
(default), ``"class"``, ``"module"``, ``"package"`` or ``"session"``.
This parameter may also be a callable which receives ``(fixture_name, config)``
as parameters, and must return a ``str`` with one of the values mentioned above.
See :ref:`dynamic scope` in the docs for more information.
:param params:
An optional list of parameters which will cause multiple invocations
of the fixture function and all of the tests using it. The current
parameter is available in ``request.param``.
:param autouse:
If True, the fixture func is activated for all tests that can see it.
If False (the default), an explicit reference is needed to activate
the fixture.
:param ids:
Sequence of ids each corresponding to the params so that they are
part of the test id. If no ids are provided they will be generated
automatically from the params.
:param name:
The name of the fixture. This defaults to the name of the decorated
function. If a fixture is used in the same module in which it is
defined, the function name of the fixture will be shadowed by the
function arg that requests the fixture; one way to resolve this is to
name the decorated function ``fixture_<fixturename>`` and then use
``@pytest.fixture(name='<fixturename>')``.
"""
这里是使用装饰器decorator来定义并设计fixture的
1. param scope:作用范围,不传则默认是"function",还有"class",“module”,“session”;
function,每条用例前/后都会执行一次fixture;
class,class下所有用例执行前/后只执行一次fixture;
module,整个py文件执行前/后只执行一次fixture;
session,整个会话执行前/后只执行一次fixture,可以是多条用例,多个模块.
2. param autouse:自动使用/激活fixture,如果autouse=True,引用它的用例可以不用传方法名了。
import pytest
@pytest.fixture(autouse=True)
def test_login():
print("login 前置")
def test_a():
print("case_aaaaaaaaaaaaa")
def test_b():
print("case_bbbbbbbbbbbbb")
def test_c():
print("case_ccccccccccccc")
3. param params:可选参数list,list里有几个参数,就会分别去执行引用的用例几次。
4. param ids:一般结合params一起用,给每个param赋予一个id,有点用例编号的意思,如果不传ids会默认自动生成一个id.
import pytest
@pytest.fixture(scope="function", params=['idle', 'pandding', 'finish'], ids=['case_1','case_2','case_3'], name="hello")
def test_login(request):
print("login 前置")
print(request.param) #此处应该用return,这里用print只为了方便打印出param.
def test_a(hello):
print("case_aaaaaaaaaaaaa")
def test_b():
print("case_bbbbbbbbbbbbb")
def test_c():
print("case_ccccccccccccc")
5. param name:给你定义的fixture起个别名,后面用例引用它时,直接传它的别名即可。
import pytest
@pytest.fixture(scope="function", name="hello")
def test_login():
print("login 前置")
def test_a(hello):
print("case_aaaaaaaaaaaaa")
def test_b():
print("case_bbbbbbbbbbbbb")
def test_c(hello):
print("case_ccccccccccccc")