7

TextTestRunnerPython unittest フレームワークから実行する非常に大きな TestSuite があります。残念ながら、テストの実行中に既にいくつのテストが行​​われたかはわかりません。

基本的に、この出力を変換したいと思います:

test_choice (__main__.TestSequenceFunctions) ... ok
test_sample (__main__.TestSequenceFunctions) ... ok
test_shuffle (__main__.TestSequenceFunctions) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.110s

OK

[1/3] test_choice (__main__.TestSequenceFunctions) ... ok
[2/3] test_sample (__main__.TestSequenceFunctions) ... ok
[3/3] test_shuffle (__main__.TestSequenceFunctions) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.110s

OK

これを達成するためにサブクラス化する必要がTextTestRunnerありますか? はいの場合、どのようにしますか?

注: ノーズと利用可能なプラグインは認識していますが、私のアプリケーションにはあまり適合しないため、依存関係を避けたいと考えています。

編集を避けたい理由:

My Application は基本的に、テスト用の追加フレームワークです。正しいテストケースを選択し、それらにライブラリ関数を提供し、長期テストのためにテストを複数回実行します。(テストは外部マシンに対して実行されます)

したがって、今すぐテストを実行する方法は次のとおりです。

# do all sort of preperations
[...]
test_suite = TestSuite()

repeatitions = 100
tests = get_tests()
for i in range(0, repeatitions):
    test_suite.addTests(tests)
TextTestRunner(verbosity=2).run(test_suite)

ノーズに関する私の問題は、ファイルシステムからテストを検出するように設計されており、特定の TestSuite で Python から直接実行する方法について明確なドキュメントを見つけることができなかったことです。

4

2 に答える 2

7

パーティーに遅れましたが、うまくいけば、これは私のように、この同じ問題に対する答えを探してここに来た他の誰かに役立つでしょう:

サブクラスTextTestRunnerTextTestResultして目的の結果を得る1 つの方法を次に示します。

import unittest
import unittest.runner
import itertools
import collections

class CustomTextTestResult(unittest.runner.TextTestResult):
    """Extension of TextTestResult to support numbering test cases"""

    def __init__(self, stream, descriptions, verbosity):
        """Initializes the test number generator, then calls super impl"""

        self.test_numbers = itertools.count(1)

        return super(CustomTextTestResult, self).__init__(stream, descriptions, verbosity)

    def startTest(self, test):
        """Writes the test number to the stream if showAll is set, then calls super impl"""

        if self.showAll:
            progress = '[{0}/{1}] '.format(next(self.test_numbers), self.test_case_count)
            self.stream.write(progress)

            # Also store the progress in the test itself, so that if it errors,
            # it can be written to the exception information by our overridden
            # _exec_info_to_string method:
            test.progress_index = progress

        return super(CustomTextTestResult, self).startTest(test)

    def _exc_info_to_string(self, err, test):
        """Gets an exception info string from super, and prepends 'Test Number' line"""

        info = super(CustomTextTestResult, self)._exc_info_to_string(err, test)

        if self.showAll:
            info = 'Test number: {index}\n{info}'.format(
                index=test.progress_index,
                info=info
            )

        return info


class CustomTextTestRunner(unittest.runner.TextTestRunner):
    """Extension of TextTestRunner to support numbering test cases"""

    resultclass = CustomTextTestResult

    def run(self, test):
        """Stores the total count of test cases, then calls super impl"""

        self.test_case_count = test.countTestCases()
        return super(CustomTextTestRunner, self).run(test)

    def _makeResult(self):
        """Creates and returns a result instance that knows the count of test cases"""

        result = super(CustomTextTestRunner, self)._makeResult()
        result.test_case_count = self.test_case_count
        return result


class TestSequenceFunctions(unittest.TestCase):
    """Dummy test case to illustrate usage"""

    fail_1 = 0
    fail_2 = 0

    def test_choice(self):
        pass

    def test_sample(self):
        self.fail_1 += 1
        if self.fail_1 == 2:
            raise Exception()

    def test_shuffle(self):
        self.fail_2 += 1
        if self.fail_2 == 3:
            raise Exception()


def get_tests():
    test_funcs = ['test_choice', 'test_sample', 'test_shuffle']
    return [TestSequenceFunctions(func) for func in test_funcs]


if __name__ == '__main__':
    test_suite = unittest.TestSuite()

    repetitions = 3
    tests = get_tests()
    for __ in xrange(0, repetitions):
        test_suite.addTests(tests)

    CustomTextTestRunner(verbosity=2).run(test_suite)

上記のコードを実行すると、次の出力が生成されます。

>>> ================================ RESTART ================================
>>> 
[1/9] test_choice (__main__.TestSequenceFunctions) ... ok
[2/9] test_sample (__main__.TestSequenceFunctions) ... ok
[3/9] test_shuffle (__main__.TestSequenceFunctions) ... ok
[4/9] test_choice (__main__.TestSequenceFunctions) ... ok
[5/9] test_sample (__main__.TestSequenceFunctions) ... ERROR
[6/9] test_shuffle (__main__.TestSequenceFunctions) ... ok
[7/9] test_choice (__main__.TestSequenceFunctions) ... ok
[8/9] test_sample (__main__.TestSequenceFunctions) ... ok
[9/9] test_shuffle (__main__.TestSequenceFunctions) ... ERROR

======================================================================
ERROR: test_sample (__main__.TestSequenceFunctions)
----------------------------------------------------------------------
Test number: [5/9] 
Traceback (most recent call last):
  File "stackoverflow.py", line 75, in test_sample
    raise Exception()
Exception

======================================================================
ERROR: test_shuffle (__main__.TestSequenceFunctions)
----------------------------------------------------------------------
Test number: [9/9] 
Traceback (most recent call last):
  File "stackoverflow.py", line 80, in test_shuffle
    raise Exception()
Exception

----------------------------------------------------------------------
Ran 9 tests in 0.042s

FAILED (errors=2)
>>> 
于 2015-12-07T17:05:59.743 に答える
1

TextTestRunnerをサブクラス化する必要がありますが、方法がわかりません。鼻を使うことへの嫌悪感を再検討することを強くお勧めします。それはあなたの問題を簡単に解決する非常に強力なツールです。

于 2012-07-18T01:18:57.013 に答える