我目前正在关注这个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)
不幸的是,当我执行时
py.test test_suite.py
我收到错误消息:
TypeError: test_1() takes exactly 3 arguments (1 given)
如何生成一系列test_1测试?
答案 0 :(得分:12)
如果您从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
但是,在这一点上,有点问题为什么你使用类而不是仅仅定义函数,因为测试基本上是相同的,但需要更少的整体样板和代码。
答案 1 :(得分:1)
对于那些仍然感兴趣的人,我写了一个 @pytest.mark.parametrize 替换 unittest.TestCase:https://github.com/MrMrRobat/parametrize
import unittest
from parametrize import parametrize
class FixtureTestCase(unittest.TestCase):
@parametrize(
"test_input,expected",
[
("3+5", 8),
("2+4", 6),
("6*9", 42),
]
)
def test_1(self, test_input, expected):
self.assertEqual(eval(test_input), expected)
$ pytest test.py::FixtureTestCase::test_1
Test session starts (platform: darwin, Python 3.9.4, pytest 6.2.4, pytest-sugar 0.9.4)
plugins: sugar-0.9.4, cov-2.11.1, mock-3.6.0
collecting ...
test.py ✓✓ 67% ██████▋
―――――――――――――――――――――――― FixtureTestCase.test_1[6*9-42] ――――――――――――――――――――――――
self = <test.FixtureTestCase testMethod=test_1[6*9-42]>, test_input = '6*9'
expected = 42
@parametrize(
"test_input,expected",
[
("3+5", 8),
("2+4", 6),
("6*9", 42),
]
)
def test_1(self, test_input, expected):
> self.assertEqual(eval(test_input), expected)
E AssertionError: 54 != 42
test.py:16: AssertionError
test.py ⨯ 100% ██████████
=========================== short test summary info ============================
FAILED test.py::FixtureTestCase::test_1[6*9-42] - AssertionError: 54 != 42
Results (0.09s):
2 passed
1 failed
- test.py:7 FixtureTestCase.test_1[6*9-42]
答案 2 :(得分:0)
最后,考虑到@Brendan Abel的回复和评论,我成功完成了我打算做的事情:
class TestCase(object):
@parameterized.expand([
("negative", -1.5, -2.0),
("integer", 1, 1.0),
("large fraction", 1.6, 1),
])
def test_floor(self, name, input, expected):
assert_equal(math.floor(input), expected)
@parameterized.expand([
("3+5", 8),
("2+4", 6),
("6*9", 42),
])
def test_1(self, a, b):
assert_equal(eval(a), b)
然后我可以通过nosetests命令执行测试:
nosetests -v --with-id class.py
答案 3 :(得分:0)
我不知道 5 年前是否是这种情况,但是现在您可以使用参数化 (https://pypi.org/project/parameterized/) 和 pytest 来装饰测试类上的测试方法,是的,包括 unittest.TestCase,而无需求助于鼻子。例如:
from unittest import TestCase
from parameterized import parameterized
class SomeTestCase(TestCase):
@parameterized.expand([
(1, 2),
('a', 'b')
])
def test_something(self, param1, param2):
...
唯一的问题,但您最好记住这一点,装饰器将为每个列出的输入参数生成新的测试方法,因此您将无法通过在命令行中指定来直接运行原始测试方法。例如。 pytest some_test.py::SomeTestCase::test_something
将不再起作用(因为您的测试方法现在需要两个参数)。但是,您可以直接调用生成的方法,您可以在运行整个 TestCase 或执行 pytest --collect-only
时从 pytest 错误输出中获取名称。