运行Python参数化测试方法时出错



IDE: PyCharm Community Edition 3.1.1
Python: 2.7.6

I使用DDT进行测试参数化http://ddt.readthedocs.org/en/latest/example.html

我想从PyCharm ->中的测试类中选择并运行参数化测试方法,参见示例:

from unittest import TestCase
from ddt import ddt, data

@ddt
class Test_parameterized(TestCase):
    def test_print_value(self):
        print 10
        self.assertIsNotNone(10)
    @data(10, 20, 30, 40)
    def test_print_value_parametrized(self, value):
        print value
        self.assertIsNotNone(value)

当我在代码中导航到第一个测试方法test_print_value并按ctrl+Shift+F10(或从上下文菜单中使用Run Unittest test_print...选项)然后执行test。

当我尝试同样的参数化测试时,我得到错误:

Test framework quit unexpectedly

输出包含:

/usr/bin/python2 /home/s/App/pycharm-community-3.1.1/helpers/pycharm/utrunner.py
/home/s/Documents/Py/first/fib/test_parametrized.py::Test_parameterized::test_print_value_parametrized true
Testing started at 10:35 AM ...
Traceback (most recent call last):
  File "/home/s/App/pycharm-community-3.1.1/helpers/pycharm/utrunner.py", line 148, in <module>
    testLoader.makeTest(getattr(testCaseClass, a[2]), testCaseClass))
AttributeError: 'TestLoader' object has no attribute 'makeTest'
Process finished with exit code 1

然而,当我运行类中的所有测试时(通过导航到代码中的测试类名称并使用提到的运行测试选项),所有参数化和非参数化测试都被一起执行,没有错误。

问题是如何从测试类独立运行参数化方法-解决方法是为每个测试类放置一个参数化测试,但这是相当混乱的解决方案。

实际上这是PyCharm utrunner.py中运行单元测试的问题。如果使用DDT,则有一个包装器@ddt和@data——它负责为每个数据条目创建单独的测试。在后台,这些测试有不同的名称,例如

@ddt
class MyTestClass(unittest.TestCase):
    @data(1, 2)
    def test_print(self, command):
        print command

这将创建名为:——test_print_1_1——test_print_2_2

当你尝试从类中运行一个测试时(右键单击->运行'Unittest test_print') PyCharm有一个问题来加载你的测试print_1_1, print_2_2,因为它试图加载test_print测试。

查看utrunner.py的代码:

  if a[1] == "":
    # test function, not method
    all.addTest(testLoader.makeTest(getattr(module, a[2])))
  else:
    testCaseClass = getattr(module, a[1])
    try:
      all.addTest(testCaseClass(a[2]))
    except:
      # class is not a testcase inheritor
      all.addTest(
        testLoader.makeTest(getattr(testCaseClass, a[2]), testCaseClass))

你将调试它,如果你看到这个问题

Ok。我的解决办法是从类中加载适当的测试。这只是一个变通方法,它并不完美,然而,由于DDT将TestCase作为另一种方法添加到类中,很难找到一种不同的方法来检测正确的测试用例,而不是通过字符串进行比较。所以不是:

try:
          all.addTest(testCaseClass(a[2]))

你可以尝试使用:

try:
            all_tests = testLoader.getTestCaseNames(getattr(module, a[1]))
            for test in all_tests:
                if test.startswith(a[2]):
                    if test.split(a[2])[1][1].isdigit():
                        all.addTest(testLoader.loadTestsFromName(test, getattr(module,a[1])))

检查是否在主名之后找到数字是排除类似测试用例的解决方案:

  • test_print

  • test_print_another_case

当然也不排除这种情况:

  • test_if_prints_1

  • test_if_prints_2

所以在最坏的情况下,如果我们没有一个好的命名约定,我们将运行类似的测试,但在大多数情况下,它应该为您工作。

当我遇到这个错误时,这是因为我已经实现了init函数如下:

def __init__(self):
    super(ClassInheritingTestCase, self).__init__()

当我将其更改为以下内容时,它正常工作:

def __init__(self, *args, **kwargs):
    super(ClassInheritingTestCase, self).__init__(*args, **kwargs)

问题是由于我没有正确地传播*args和**kwargs。

最新更新