【问题标题】:Weird behavior when calling load_tests()调用 load_tests() 时的奇怪行为
【发布时间】:2012-08-24 04:07:05
【问题描述】:

在使用 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,因为我需要已经存在的所有其他测试。我只想将这些测试添加到套件中。

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

【问题讨论】:

    标签: python unit-testing


    【解决方案1】:

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

    如果你总是要实例化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 模式——我通常只依赖nose 的自动测试发现,但所有这些都适用于您的设置。如果你以后想使用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"}))()
    

    【讨论】:

    • 感谢您的回复,但它并没有完全解决我的问题。我想我不清楚我的问题,所以我对其进行了编辑并添加了更多描述性代码。
    • @Rusty,如果您尝试使用类的__init__ 方法将 bar 添加到对象,实际会发生什么?它仍然显示相同的错误吗?这样 unittest 不应该选择额外的测试用例(虽然不是 100% 确定你在问题中的意思是“额外的测试用例”)
    • 让我解释一下我所说的“额外测试用例”是什么意思。 'load_tests()' 函数应该创建三个测试,对文件data.csv 中的每一行数据进行一个测试。但是创建并执行了 4 个测试,其中之一是通过正常的测试加载器以某种方式自动添加的测试用例。据我了解,load_tests() 的存在将完全禁用正常的测试用例加载。但显然我误解了一些东西。
    • @Jeff,如果我使用__init__ 方法,“额外”测试用例会像以前一样创建,但 self.bar == 'runTest'。
    • @Rusty 我刚刚尝试使用__init__ 方法(使用python filename.py)运行文件并且运行良好。你是把它作为一个更大的测试套件的一部分来运行吗?
    【解决方案2】:

    显然我误解了load_tests()。根据/usr/lib/python2.7/unittest/loader.py 中的 Python 代码,测试是从模块中正常加载的。然后,如果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
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多