6

在以前的生活中,我做了一些 Java 开发,发现JUnit Theories非常有用。Python有没有类似的机制?

目前我正在做类似的事情:

def some_test(self):
    cases = [('some sample input', 'some expected value'),
            ('some other input', 'some other expected value')]

    for value, expected in cases:
        result = method_under_test(value)
        self.assertEqual(expected, result)

但这相当笨拙,如果第一个“案例”失败,则所有其他“案例”都无法运行。

4

3 回答 3

2

看起来pytest可以做这样的事情:https ://docs.pytest.org/en/latest/parametrize.html

我自己没有试过。

于 2015-05-28T21:39:16.010 回答
0

我不知道在任何常见的测试框架中有任何内置函数。您的解决方案的唯一问题是迭代在测试内部。相反,它应该在外面并生成测试,也许是这样的

import unittest


def _apply(func, args):
    """Return a function with args applied after first argument"""
    def wrapped(self):
        return func(self, *args)
    return wrapped


class TheoryMeta(type):
    """Metaclass that replaces test methods with multiple methods for each test case"""
    def __new__(meta, name, bases, attrs):
        newattrs = {}
        cases = attrs.pop('cases', [])

        for name, value in attrs.items():
            if not name.startswith('test') or not callable(value):
                newattrs[name] = value
                continue

            for n, args in enumerate(cases):
                test_name = '%s_%d' % (name, n)
                newattrs[test_name] = _apply(value, args)

        return super().__new__(meta, name, bases, newattrs)


class TestCase(unittest.TestCase, metaclass=TheoryMeta):
    pass

然后要使用它,创建一个TestCase具有cases属性的子类,该属性是应用于测试用例上每个测试方法的参数列表。

class TestAdd(TestCase):
    cases = [
        # (a, b)
        (1, 1),
        (2, 0),
        (3, 0),
    ]

    def test_add(self, a, b):
        self.assertEqual(a + b, 2)

======================================================================
FAIL: test_add_2 (__main__.__qualname__)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 7, in wrapped
    return func(self, *args)
  File "test.py", line 41, in test_add
    self.assertEqual(a + b, 2)
AssertionError: 3 != 2

----------------------------------------------------------------------
Ran 3 tests in 0.001s

根据您的需求和测试设置,您可能会发现在 TestCase 上只使用猴子补丁生成的测试方法比使用元类更好。或者您可以在TestLoader. 在任何情况下,使用样本数据来生成测试方法。

于 2015-05-28T07:31:35.173 回答
0

事实证明,从 Python 3.4 开始就有这样的内置功能—— subTesthttps ://docs.python.org/3.4/library/unittest.html#distinguishing-test-iterations-using-subtests

不像 py.test 的参数化测试或 jUnit Theories 那样优雅,但如果您想要标准库方法并且使用相对较新的 Python 版本,这是一个选项。

于 2018-02-16T20:51:47.410 回答