Python (pytest) 类中函数装饰器中调用的当前类中的另一个函数, 引发的问题

HowardWu · 2019年10月21日 · 最后由 尼古拉斯赵四 回复于 2019年10月28日 · 4189 次阅读

本人在学习 pytest, 最近一直困惑一个地方无法自解, 先上代码

class Test_case1:
    def param_info(self):
        x = '1'
        y = '2'
        z = '3'
        return [x, y, z]

    @user1ize('x', self.param_info())
    def test_x(self, x):
        assert x == 1

这里再 test_x 上使用参数化时, 调用了当前类中的另一个方法 param_info, 但因为装饰器的作用域问题, 这里或报错, 无法在装饰器中使用当前类中的函数. 因为的测试用例中的测试参数是需要适时获取, 且会变化的, 不是固定值, 所以必须要从之前的 test 步骤中执行后生成参数, 并用在后面的测试方法上. 所以这里如何 pytest 的中的装饰器中调用当前类的方法,或变量, 还想请教各位大神!

最佳回复

一般很少这样用吧,pytest 就是单元测试,注意控制变量啊,我用 pytest-lazy-fixture 插件试了下好像可以,如果有更好的方式请告诉我🤔

import pytest


class Test_case123:

    @pytest.fixture(params=[pytest.lazy_fixture('get_x'),
                            pytest.lazy_fixture('get_y')])
    def param_info(self, request):
        return request.param

    @pytest.fixture
    def get_x(self):
        return self.__class__.x

    @pytest.fixture
    def get_y(self):
        return self.__class__.y

    def test_1(self):
        self.__class__.x = "希望小学"

    def test_2(self):
        self.__class__.y = "希望小学生"

    @pytest.mark.parametrize('z', [pytest.lazy_fixture('param_info')])
    def test_3(self, z):
        assert "希望" in z
共收到 8 条回复 时间 点赞

好像是不支持的,pytest 执行分成 3 个阶段:1-收集用例,2-执行用例,3-生成报告,所有用例在第一阶段就确定了,没法在用例执行的时候再去根据执行结果参数化。
而且测试用例应该是固定的吧,你这样设计肯定是有问题的,你可以把你的场景再详细描述下,再分析分析。

把 param_info 放到 Test_case1 外面看看。

chen 回复

放到外面是可以, 但是需要传参, 传递的参数是当前类中的变量, 所以这里还是会存在装饰器中的作用域问题.

arrow 回复

测试场景: 学生列表标记. 第 1 个用例是获取学校信息, 第 2 个用例是获取学生列表信息, 第 3 个用例是从第 1 个用例中获取的学校信息中组合成测试参数, 将第 2 个用例中学生信息组合成参数, 用于第 3 个用例的测试参数进行验证. 其实测试数据要是固定的话, 将测试参数直接预先设置好也是可以的, 但我想用于多个测试数据上. 所以测试参数不能固定.

arrow 回复

不过我有点启发了, 可以在 fixture 中把测试数据准备好. 就是麻烦一些. 谢谢

一般很少这样用吧,pytest 就是单元测试,注意控制变量啊,我用 pytest-lazy-fixture 插件试了下好像可以,如果有更好的方式请告诉我🤔

import pytest


class Test_case123:

    @pytest.fixture(params=[pytest.lazy_fixture('get_x'),
                            pytest.lazy_fixture('get_y')])
    def param_info(self, request):
        return request.param

    @pytest.fixture
    def get_x(self):
        return self.__class__.x

    @pytest.fixture
    def get_y(self):
        return self.__class__.y

    def test_1(self):
        self.__class__.x = "希望小学"

    def test_2(self):
        self.__class__.y = "希望小学生"

    @pytest.mark.parametrize('z', [pytest.lazy_fixture('param_info')])
    def test_3(self, z):
        assert "希望" in z
HowardWu 回复

哎~~又是一个关联性的 case 设计。个人建议不要搞这种 case 用 fixture 做 setUp 将前置步骤最短化实现,这样做唯一的坏处就是相关前置步骤修改可能会导致修改量比较大,但 fixture 是能套 fixture 的合理的 “拆封” 是很又必要的。

改成类方法应该就可以了

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册