【问题标题】:Error when running Python parameterized test method运行 Python 参数化测试方法时出错
【发布时间】:2014-06-28 01:20:04
【问题描述】:

IDE: PyCharm 社区版 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 (或使用 Run Unittest test_print...上下文菜单中的选项) 然后执行测试。

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

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

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

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

【问题讨论】:

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


    【解决方案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))
    

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

    好的。所以我的解决方法是从类中加载适当的测试。这只是一种解决方法,并不完美,但是由于 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

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

    【讨论】:

      【解决方案2】:

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

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-16
        • 2014-08-07
        • 1970-01-01
        相关资源
        最近更新 更多