Py.test:从类中参数化测试用例

paf*_*de2 17 python automated-tests unit-testing pytest

我目前正在关注这个py.test示例,当我不使用类时,它会工作,但是当我将测试用例引入类时,我失败了.

我设法编写的最小案例如下:

import unittest

import pytest

class FixtureTestCase(unittest.TestCase):

    @pytest.mark.parametrize("test_input,expected", [
    ("3+5", 8),
    ("2+4", 6),
    ("6*9", 42),
    ])
    def test_1(self, a, b):
        self.assertEqual(a, b)
Run Code Online (Sandbox Code Playgroud)

不幸的是,当我执行

  py.test  test_suite.py
Run Code Online (Sandbox Code Playgroud)

我收到错误消息:

  TypeError: test_1() takes exactly 3 arguments (1 given)
Run Code Online (Sandbox Code Playgroud)

如何生成一系列test_1测试?

Bre*_*bel 16

如果您是子类unittest.TestCase,则您的测试方法不能有其他参数.如果你只是从子类object,它将工作(虽然你将不得不使用常规assert语句而不是TestCase.assertEqual方法.

import unittest

import pytest

class TestCase(object):

    @pytest.mark.parametrize("test_input,expected", [
    ("3+5", 8),
    ("2+4", 6),
    ("6*9", 42),
    ])
    def test_1(self, a, b):
        assert eval(a) == b
Run Code Online (Sandbox Code Playgroud)

但是,在这一点上,它有点问题为什么你使用类而不仅仅是定义函数,因为测试基本上是相同的,但需要更少的整体样板和代码.


小智 11

我不知道 5 年前是否是这样,但现在你可以使用参数化(https://pypi.org/project/parameterized/)和 pytest 来装饰测试类上的测试方法,是的,包括单元测试。 TestCase,无需求助于鼻子。例如:

from unittest import TestCase
from parameterized import parameterized

class SomeTestCase(TestCase):

    @parameterized.expand([
        (1, 2),
        ('a', 'b')
    ])
    def test_something(self, param1, param2):
        ...
Run Code Online (Sandbox Code Playgroud)

唯一的问题(但您最好记住这一点)是装饰器将为每个列出的输入参数生成新的测试方法,因此您将无法通过在命令行上指定来直接运行原始测试方法。例如pytest some_test.py::SomeTestCase::test_something将不再工作(因为您的测试方法现在需要两个参数)。但是,您可以直接调用生成的方法,您可以从运行整个 TestCase 时的 pytest 错误输出或通过执行pytest --collect-only.