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
但是当我在类中运行所有测试时(通过在代码中导航到测试类名并使用提到的运行测试选项),所有参数化和非参数化测试一起执行而没有错误。
问题是如何从测试类中独立运行参数化方法 - 解决方法是为每个测试类进行一次参数化测试,但这是一个相当混乱的解决方案。
答案 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引起的。