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

时间:2014-05-10 09:12:52

标签: python unit-testing python-2.7 pycharm parameterized

IDE: PyCharm Community Edition 3.1.1
Python: 2.7.6

我使用 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 (或使用{上下文菜单中的{1}}选项) 然后执行测试。

当我尝试使用参数化测试时,我得到错误:

Run Unittest test_print...

输出包含:

Test framework quit unexpectedly

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

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

2 个答案:

答案 0 :(得分:6)

实际上这是运行unittests的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在尝试加载test_print测试时加载测试print_1_1,print_2_2会出现问题。

当你查看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))

你将调试它,你会看到这个问题。

确定。所以我的解决方法是从课堂上加载适当的测试。这只是一种解决方法而且并不完美,但是由于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

所以在最糟糕的情况下,如果我们没有一个好的名称约定,我们将进行类似的测试,但在大多数情况下它应该适合你。

答案 1 :(得分:2)

当我遇到这个错误时,那是因为我实现了一个init函数,如下所示:

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

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

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

问题是由于我没有通过正确传播* args和** kwargs引起的。