问答 pytest 在并发的时候 后置处理的 teardown_class() 方法不受控制,也就是不是所有用例运行完成后才运行,大家有什么解决方法吗

罗罗 · 2024年03月20日 · 最后由 今晚打老虎 回复于 2024年03月21日 · 6690 次阅读

pytest 在并发的时候 后置处理的 teardown_class() 方法不受控制,也就是不是所有用例运行完成后才运行,大家有什么解决方法吗

共收到 10 条回复 时间 点赞
1楼 已删除

不是所有用例运行完成后才运行 , 改成用 fixture 的后置条件,范围设定为会话级别 试试呢

罗罗 #10 · 2024年03月20日 Author

您提到的这个方式我也尝试过,代码如下,在并发的时候也控制不住,整个类文件里的用例 还没执行完,就调用了后置处理部分用例需要用的数据被提前在数据库中删除了,导致这些用例报查询不到数据

pytest.fixture(scope="class")
def setup_and_teardown():
    logging.info("Setting up...")
    yield params
    logging.info("Tearing down...")

不受控制是怎么个不受控制?代码能不能贴一下?和并发有实际关系吗?
你这啥啥都没有,咋给你解决方法

涉及到一些安全项 代码无法直接提供问题场景样例描述如下:

#!/usr/bin/python
# -*- coding:utf-8 -*-

import pytest
import logging

class TestDemo():


    def setup_class(self):
        logging.info("这里做初始化操作,比如读取相关参数")


    def teardown_class(self):
        logging.info("后置操作:删除自动化创建测试项")
    # 此处批量删除,比如测试项是以AT-TEST开头的均会删除



    @pytest.mark.run(order=1)
    def test_1(self):
        # 创建了测试服务1,返回服务ID
        # 创建后需要根据ID,查询后续操作
        pass

   @pytest.mark.run(order=1)
    def test_2(self):
        # 创建了测试服务2,返回服务ID
        # 创建后需要根据ID,查询后续操作
        pass


    @pytest.mark.run(order=1)
    def test_3(self):
        # 创建了测试服务3,返回服务ID
        # 创建后需要根据ID,查询后续操作
        pass    

    # 省略更多类似的创建服务用例...

在并发的时候,test_n 并没有全部执行完成,teardown_class 就会执行,导致部分用例需要根据 ID 做后续处理的时候,查询数据库已经无此 ID 数据了
原因就是因为被批量删除了

罗罗 回复

没咋用过这种方式,test_n 是在一个进程中执行吗?不在一个进程里,set_up 和 teardown_class 执行了几次?创建的测试数据是相同的吗?用 xdist 中的 group 将共用测试数据的用例放到一个 group 里试试@pytest.mark.xdist_group(name="group1")

dubda 回复

1、test_n 不是在一个进程中执行,我用的是线程
2、set_up 和 teardown_class 执行 1 次
3、创建的测试数据相同
4、xdist 有一个问题,就是没办法控制 conftest.py 文件中,@pytest.fixture(scope="session",autouse=True) 执行的次数,也就是说每个进程都会执行一次,导致一个问题,即:我需要在 conftest 中做全局的 token 初始化,我希望@pytest.fixture(scope="session",autouse=True) 只执行一次
5、针对第 4 点我提的问题,您有什么解决方案吗

dubda 回复

不知道你并发执行的逻辑,第 4 点的话试试这样?

import pytest


@pytest.fixture(scope='session')
def token(request):
    cache_key = 'token'
    token_value = request.config.cache.get(cache_key, None)
    if token_value:
            return token_value
    token_value = "生成token的方法"
    request.config.cache.set(cache_key, token_value)
    return token_value

@q243899640

dubda 回复

好的 我这边尝试下,看看能否满足我的场景,非常感谢您的帮助😃

怎么哪里都有你

xiaohuozi666 回复

是吗?我怎么头次见到你

罗罗 关闭了讨论 03月21日 16:08
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册