0

在 Python 2.7 中使用新的发现功能时,我遇到了一个奇怪的错误。我有一些单元测试需要一些额外的设置和文件中的一些成员数据。我正在尝试将我的设置测试用例添加到传递给load_tests(). 但是因为测试套件tests已经包含标准测试(包括TestCase当前模块中的对象),所以自动添加的测试用例的正确设置没有完成,我得到一个 AttributeError。

在下面的代码中,load_tests()用于为 csv 文件中的每一行数据创建一个测试用例。该文件有三行,但由于某种原因,正在创建第四个测试用例。

#!/usr/bin/python
import unittest

class Foo(unittest.TestCase):    
    def setup(self,bar):
        print "Foo.setup()"
        self.bar = bar 
    def runTest(self):
        print self.bar

def load_tests(loader, tests, pattern):
    f = open('data.csv')  # data.csv contains three lines: "a\nb\nc"
    for line in f:
        tc = Foo()
        tc.setup(line)
        tests.addTest(tc)
    return tests

unittest.main()

当我执行这段代码时,输​​出显示执行了 4 个测试,其中一个失败了。数据文件只包含三行,并且Foo.setup()只被调用了 3 次。因此load_tests()按设计创建了三个测试用例。

Foo.setup()
Foo.setup()
Foo.setup()
Ea

.b

.c

.
======================================================================
ERROR: runTest (__main__.Foo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./foo.py", line 11, in runTest
    print self.bar
AttributeError: 'Foo' object has no attribute 'bar'

----------------------------------------------------------------------
Ran 4 tests in 0.002s

有没有办法删除套件中自动加载的 TestCase?我无法创建一个新的空 TestSuite,因为我需要已经存在的所有其他测试。我只想将这些测试添加到套件中。

编辑:澄清了我的问题和代码示例。我之前有点模棱两可。

4

2 回答 2

0

有几种方法可以做到这一点。

如果你总是要实例化 Foo,你可以在__init__类的方法中设置 bar。

class Foo(unittest.TestCase):
    def __init__(self, bar, *args, **kwargs):
        super(Foo, self).__init__(*args, **kwargs)
        self.bar = bar
    def runTest(self):
        print self.bar

f = Foo("some string")

我之前没有load_tests直接使用过该模式——我通常只依赖鼻子的自动测试发现,但所有这些都适用于您的设置。如果你以后想使用TestSuites 和unittest/nose的测试自动发现,并且想使用类,你可以使用类工厂:

def make_foo_case(the_bar):
    class Foo(unittest.TestCase):
        bar = the_bar
        def runTest(self):
            print self.bar
    return Foo

f = (make_testcase("some string"))()

或用于type子类化 foo 并在成员中设置元素,(与前一个基本相同)例如:

class Foo2(object):
    def runTest(self):
        print self.bar

f = (type("Tester2", (Foo2,unittest.TestCase), {"bar":"some string"}))()
于 2012-08-23T02:54:59.337 回答
0

显然我误会了load_tests()。根据 中的 Python 代码/usr/lib/python2.7/unittest/loader.py,测试是从模块中正常加载的。然后,如果load_tests()存在,它也会被调用。

def loadTestsFromModule(self, module, use_load_tests=True):
    """Return a suite of all tests cases contained in the given module"""
    tests = []
    for name in dir(module):
        obj = getattr(module, name)
        if isinstance(obj, type) and issubclass(obj, case.TestCase):
            tests.append(self.loadTestsFromTestCase(obj))

    load_tests = getattr(module, 'load_tests', None)
    tests = self.suiteClass(tests)
    if use_load_tests and load_tests is not None:
        try:
            return load_tests(self, tests, None)
        except Exception, e:
            return _make_failed_load_tests(module.__name__, e,
                                           self.suiteClass)
    return tests

所以我想我的解决方案是接受创建的额外测试用例,检查它,然后通过它。非常感谢杰夫试图帮助我。

于 2012-08-23T20:07:05.623 回答