0

Python 2.7 の新しい検出機能を使用すると、奇妙なエラーが発生します。少し余分なセットアップとファイルからのメンバーデータを必要とするいくつかの単体テストがあります。に渡される現在のテスト スイートにセットアップ テスト ケースを追加しようとしていますload_tests()。しかし、テスト スイートtestsには既に標準テスト (現在のモジュール内のオブジェクトを含むTestCase) が含まれているため、自動的に追加されたテストケースの適切なセットアップが行われず、AttributeError が発生します。

以下のコードでは、load_tests()を使用して、csv ファイルの各データ行に対して 1 つのテスト ケースを作成しています。ファイルには 3 行ありますが、何らかの理由で 4 番目のテストケースが作成されています。

#!/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 つのテストが実行され、そのうちの 1 つが失敗したことが出力に示されます。データ ファイルには 3 行しか含まれてFoo.setup()おらず、3 回しか呼び出されていません。そのload_tests()ため、設計どおりに 3 つのテスト ケースを作成しました。

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

どうやら私は誤解して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 に答える
0

これを行うにはいくつかの方法があります。

__init__常に Foo をインスタンス化する場合は、クラスのメソッドに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"))()

または、typefoo をサブクラス化し、メンバーに要素を設定するために使用します (本質的には前と同じ) 例:

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

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