web-dev-qa-db-ja.com

Python unittest:テストファイルの一部のみを実行する方法は?

非常に多くの時間を要するテストを含むテストファイルがあります(クラスターに計算を送信し、結果を待ちます)。これらはすべて特定のTestCaseクラスにあります。

それらは時間がかかり、さらに壊れる可能性が低いため、このテストのサブセットを実行するか実行しないかを選択できるようにしたいです(最良の方法は、コマンドライン引数、つまり「_./tests.py --offline_」など)、ほとんどのテストを頻繁かつ迅速に実行でき、時間があるときにたまにセット全体を実行できました。

今のところ、unittest.main()を使用してテストを開始します。

ありがとう。

68
Gohu

デフォルトのunittest.main()は、デフォルトのテストローダーを使用して、mainが実行されているモジュールからTestSuiteを作成します。

このデフォルトの動作を使用する必要はありません。

たとえば、3つの nittest.TestSuite インスタンスを作成できます。

  1. 「高速」サブセット。

    fast = TestSuite()
    fast.addTests( TestFastThis )
    fast.addTests( TestFastThat )
    
  2. 「遅い」サブセット。

    slow = TestSuite()
    slow.addTests( TestSlowAnother )
    slow.addTests( TestSlowSomeMore )
    
  3. 「全体」セット。

    alltests = unittest.TestSuite([fast, slow])
    

TestCase名を調整して、高速と低速を示すことに注意してください。 unittest.TestLoaderをサブクラス化して、クラスの名前を解析し、複数のローダーを作成できます。

その後、メインプログラムは optparse または argparse (2.7または3.2以降で使用可能)を使用してコマンドライン引数を解析し、実行するスイート、高速、低速、またはすべてを選択できます。

または、sys.argv[1]は3つの値の1つであり、次のような単純なものを使用します

if __== "__main__":
    suite = eval(sys.argv[1])  # Be careful with this line!
    unittest.TextTestRunner().run(suite)
50
S.Lott

単一の特定のテストのみを実行するには、次を使用できます。

$ python -m unittest test_module.TestClass.test_method

詳細 こちら

80
Amit Kotlovski

実際には、テストケースの名前をsys.argvとして渡すことができ、それらのケースのみがテストされます。

たとえば、あなたが持っていると仮定します

class TestAccount(unittest.TestCase):
    ...

class TestCustomer(unittest.TestCase):
    ...

class TestShipping(unittest.TestCase):
    ...

account = TestAccount
customer = TestCustomer
shipping = TestShipping

あなたは電話することができます

python test.py account

アカウントテストのみ、または

$ python test.py account customer

両方のケースをテストする

10

私はこれを単純なskipIfを使用して行っています:

_import os

SLOW_TESTS = int(os.getenv('SLOW_TESTS', '0'))

@unittest.skipIf(not SLOW_TESTS, "slow")
class CheckMyFeature(unittest.TestCase):
    def runTest(self):
        …
_

この方法では、既存のテストケースをこの1行で装飾するだけで済みます(テストスイートなどを作成する必要はなく、ユニットテストファイルの先頭にos.getenv()呼び出し行を1つだけ作成します)。デフォルトでは、このテストはスキップされます。

遅いにもかかわらず実行したい場合は、次のようにスクリプトを呼び出します。

_SLOW_TESTS=1 python -m unittest …
_
10
Alfe

基本的に2つの方法があります:

  1. クラス用の独自のテストスイートを定義する
  2. 実際のデータを返すクラスター接続の模擬クラスを作成します。

私は彼の2番目のアプローチを強く支持しています。単体テストshouldは、非常に単一のコードのみをテストし、複雑なシステム(データベースやクラスターなど)はテストしません。しかし、常に可能であるとは限らないことを理解しています。時には、モックアップの作成が単純に高すぎるか、テストの目標が本当に複雑なシステムにある場合があります。

オプション(1)に戻り、次の方法で続行できます。

suite = unittest.TestSuite()
suite.addTest(MyUnitTestClass('quickRunningTest'))
suite.addTest(MyUnitTestClass('otherTest'))

次に、スイートをテストランナーに渡します。

unittest.TextTestRunner().run(suite)

pythonドキュメンテーション: http://docs.python.org/library/unittest.html#testsuite-objects の詳細

8
rob

unittest.main()を使用しているので、単にpython tests.py --helpドキュメントを取得するには:

Usage: tests.py [options] [test] [...]

Options:
  -h, --help       Show this message
  -v, --verbose    Verbose output
  -q, --quiet      Minimal output
  -f, --failfast   Stop on first failure
  -c, --catch      Catch control-C and display results
  -b, --buffer     Buffer stdout and stderr during test runs

Examples:
  tests.py                               - run default set of tests
  tests.py MyTestSuite                   - run suite 'MyTestSuite'
  tests.py MyTestCase.testSomething      - run MyTestCase.testSomething
  tests.py MyTestCase                    - run all 'test*' test methods
                                               in MyTestCase

つまり、あなたは単にできる

python tests.py TestClass.test_method
6
Thomas Ahle

unittest.skipデコレータの動作に基づいて、別のソリューションを見つけました。 __unittest_skip__および__unittest_skip_why__を設定します。

ラベルベース

ラベルシステムを適用して、いくつかのテストにquickslowglaciermemoryhogcpuhogcoreなど。

次に、all 'quick' tests、またはrun everything except 'memoryhog' testsの基本的なホワイトリスト/ブラックリストのセットアップを実行します

実装

これを2つの部分に分けて実装しました。

  1. 最初にテストにラベルを追加します(カスタム@testlabelクラスデコレーターを使用)
  2. カスタムunittest.TestRunnerは、スキップするテストを識別し、実行前にテストリストの内容を変更します。

作業の実装はこの要点にあります: https://Gist.github.com/fragmuffin/a245f59bdcd457936c3b51aa2ebb3f6c

(完全に機能する例は長すぎてここに入れることができませんでした)

結果は...

$ ./runtests.py --blacklist foo
test_foo (test_things.MyTest2) ... ok
test_bar (test_things.MyTest3) ... ok
test_one (test_things.MyTests1) ... skipped 'label exclusion'
test_two (test_things.MyTests1) ... skipped 'label exclusion'

----------------------------------------------------------------------
Ran 4 tests in 0.000s

OK (skipped=2)

すべてのMyTests1クラステストは、fooラベルがあるためスキップされます。

--whitelistも機能します

2
FraggaMuffin

または、unittest.SkipTest()関数を使用できます。たとえば、次のようにskipOrRunTestメソッドをテストクラスに追加します。

def skipOrRunTest(self,testType):
    #testsToRun = 'ALL'
    #testsToRun = 'testType1, testType2, testType3, testType4,...etc'
    #testsToRun = 'testType1'
    #testsToRun = 'testType2'
    #testsToRun = 'testType3'
    testsToRun = 'testType4'              
    if ((testsToRun == 'ALL') or (testType in testsToRun)):
        return True 
    else:
        print "SKIPPED TEST because:\n\t testSuite '" + testType  + "' NOT IN testsToRun['" + testsToRun + "']" 
        self.skipTest("skipppy!!!")

次に、このskipOrRunTestメソッドの呼び出しを、次のように各ユニットテストの最初に追加します。

def testType4(self):
    self.skipOrRunTest('testType4')
2
joe

私は@slottの答えを試しました:

if __== "__main__":
    suite = eval(sys.argv[1])  # Be careful with this line!
    unittest.TextTestRunner().run(suite)

しかし、それは私に次のエラーを与えました:

Traceback (most recent call last):
  File "functional_tests.py", line 178, in <module>
    unittest.TextTestRunner().run(suite)
  File "/usr/lib/python2.7/unittest/runner.py", line 151, in run
    test(result)
  File "/usr/lib/python2.7/unittest/case.py", line 188, in __init__
    testMethod = getattr(self, methodName)
TypeError: getattr(): attribute name must be string

次は私のために働いた:

if __== "__main__":
    test_class = eval(sys.argv[1])
    suite = unittest.TestLoader().loadTestsFromTestCase(test_class)
    unittest.TextTestRunner().run(suite)
1
Dirty Penguin

Py.test、nose、またはzope.testingなどの専用のテストランナーの使用を検討してください。これらにはすべて、テストを選択するためのコマンドラインオプションがあります。

例として鼻を探します: https://pypi.python.org/pypi/nose/1.3.

1
Lennart Regebro

テストを低速テストとしてマークし、環境変数を使用してスキップできるようにするデコレーターを作成しました

from unittest import skip
import os

def slow_test(func):
    return skipIf('SKIP_SLOW_TESTS' in os.environ, 'Skipping slow test')(func)

次のように、テストを低速としてマークできます。

@slow_test
def test_my_funky_thing():
    perform_test()

SKIP_SLOW_TESTS環境変数を設定して、遅いテストをスキップします。

SKIP_SLOW_TESTS=1 python -m unittest
0
devsnd

これを行う良い方法を以前に見つけていないので、ここで共有してください。

目標:テストファイルのセットをまとめて、ユニットとして実行できるようにしますが、それらのいずれかを選択して単独で実行できます。

問題:検出方法では、実行する単一のテストケースを簡単に選択できません。

デザイン:以下を参照してください。これはflattens名前空間であるため、TestCaseクラス名で選択でき、 "tests1.test_core"プレフィックスは省略できます。

./run-tests TestCore.test_fmap

コード

  test_module_names = [
    'tests1.test_core',
    'tests2.test_other',
    'tests3.test_foo',
    ]

  loader = unittest.defaultTestLoader
  if args:
    alltests = unittest.TestSuite()
    for a in args:
      for m in test_module_names:
        try:
          alltests.addTest( loader.loadTestsFromName( m+'.'+a ) )
        except AttributeError as e:
          continue
  else:
    alltests = loader.loadTestsFromNames( test_module_names )

  runner = unittest.TextTestRunner( verbosity = opt.verbose )
  runner.run( alltests )
0
FDS

これは私のために働いた唯一のものです。

if __== '__main__':
unittest.main( argv=sys.argv, testRunner = unittest.TextTestRunner(verbosity=2))

呼び出したとき、クラス名とテスト名を渡す必要がありました。クラスとテスト名の組み合わせが記憶されていないため、少し不便です。

python ./tests.py class_Name.test_30311

クラス名とテスト名を削除すると、ファイル内のすべてのテストが実行されます。 CLIでコマンドを実際に変更することはないので、この方法は組み込みの方法よりもはるかに簡単に処理できます。パラメータを追加するだけです。

楽しんで、キース

0
Keith

属性を追加するだけで実行したいtest_ *メソッドを選択する別の方法を見つけました。基本的にメタクラスを使用して、TestCaseクラス内の呼び出し可能オブジェクトを装飾し、UnitDebug.skipデコレーターでStepDebug属性を使用します。の詳細

Pythonデコレータとメタクラスを使用して、1つを除くすべてのユニットテストをスキップします

上記のソリューションよりも優れたソリューションであるかどうかはわかりませんが、オプションとして提供しています。

0
Satrapes