5. 内置插件 fixtures
插件路径:_pytest.fixtures
实现的 hook
调用的 hook
pytest_fixture_setup
pytest_fixture_post_finalizer
插件功能
创建文件配置项:usefixtures,用来强制用例自动使用 fixture
创建装饰器@pytest.fixture,用来申明 fixture:_pytest.fixtures.FixtureFunctionMarker
创建插件funcmanage,用来收集、管理 fixture:_pytest.fixtures.FixtureManager
创建 fixturerequest,用来使用 fixture,_pytest.fixtures.FixtureRequest
代码片段
class FixtureRequest:
def _get_active_fixturedef( self, argname: str ) -> Union["FixtureDef[object]", PseudoFixtureDef[object]]: try: return self._fixture_defs[argname] except KeyError: try: fixturedef = self._getnextfixturedef(argname) except FixtureLookupError: if argname == "request": cached_result = (self, [0], None) return PseudoFixtureDef(cached_result, Scope.Function) raise
@fixture(scope="session")def pytestconfig(request: FixtureRequest) -> Config:
return request.config
def call_fixture_func( fixturefunc: "_FixtureFunc[FixtureValue]", request: FixtureRequest, kwargs) -> FixtureValue: if is_generator(fixturefunc): fixturefunc = cast( Callable[..., Generator[FixtureValue, None, None]], fixturefunc ) generator = fixturefunc(**kwargs) try: fixture_result = next(generator) except StopIteration: raise ValueError(f"{request.fixturename} did not yield a value") from None finalizer = functools.partial(_teardown_yield_fixture, fixturefunc, generator) request.addfinalizer(finalizer) else: fixturefunc = cast(Callable[..., FixtureValue], fixturefunc) fixture_result = fixturefunc(**kwargs) return fixture_result
fixture 插件提供了个 fixture 叫requests,实现方式非常有趣
没有用@pytest.fixture的方式进行创建
拦截用例请求的 fixture 名,如果是request的话,就把自己给出去
通过返回值,使自己的 scope 成为 session 级
pytestconfig才是第一个用@pytest.fixture创建的 fixture
fixture 的执行细节:
如果是函数 fixture:直接调用,返回结果,没有 teardown 阶段
如果是生成器 fixture:
setup + 返回值 :按照迭代器协议调用
teardown:调用request.addfinalizer委托给 runner 插件
简评
funcmanage 和 session 插件都是【由插件创建的插件】,虽然露面的挺早,但是加载的很晚,
尤其 funcmanage,它是最后一个被加载的 pytest 内置插件。
...
在使用 fixture 时,我们不说【调用】fixture,而是说【请求】fixture。
因为在使用时,pytest 都会根据上下文判断,是重新调用 fixture 取结果,还是直接返回上一次的结果
也就是说,你使用的时候能够拿到 fixture 返回值,但是不确定有没有进行调用。
...
使用yield为 fixture 添加 teardown 是更加直接、更干净推荐方案,。
相反,request.addfinalizer是一种偏底层的写法,应该小心使用,可能会出现 setup 异常,却依然尝试 teadrown 的糟糕局面
note:生成器 fixture 是在 setup 成功才调用 request.addfinalizer,所以能避免这种情况
...
fixture 相关的内容太多了,比如:
怎么从各个地方找到 fixture、
怎么处理同名 fixture 优先级的,
怎么处理参数的,
怎么进行参数化的,
怎么验证 fixture 之间的范围关系
等等。。。
这些留到介绍 funcmanage 插件的时候再细说吧,如果还是说不完,就再单独开一个 fixture 章节。
...
我在上篇文章中提到:
有些提供了 hook 实现
有些插件提供了 fixture 实现
有些插件提供了 hook 和 fixture 实现
pytest中,fixture和hook同为最重要的特性之一,
对于还未掌握 hook 的人来说,用好 fixure 可以拉进你和 pytest 的距离
对于已经掌握 hook 的人来说,用好 fixure 可以拉进你和用例的距离
领取专属 10元无门槛券
私享最新 技术干货