自動テストのセットに対してsetUpを1回だけ実行します


81

私のPythonバージョンは2.6です。

すべてのテストに必要なことを行うので、テストsetUpメソッドを1回だけ実行したいと思います。

私のアイデアは、最初の実行後に「true」に設定されるブール変数を作成し、セットアップメソッドへの複数の呼び出しを無効にすることでした。

class mySelTest(unittest.TestCase):
    setup_done = False

    def setUp(self):
        print str(self.setup_done)
            
        if self.setup_done:
            return
        self.setup_done = True
        print str(self.setup_done)

出力:

False

True

--- Test 1 ---

False

True

--- Test 2 ---

なぜこれが機能しないのですか?私は何かを逃しましたか?


6
Unittestは、テストごとに個別のインスタンスを作成します
David Robinson

2
これをしないでください。他のメカニズムを実装します。ただし、の意味を変更しようとしないでくださいsetUp
David Heffernan 2013年

回答:


115

setUpClassテストスイートごとに1回だけ実行されるメソッドを定義するために使用できます。


お返事をありがとうございます。Python 2.6.6を使用しているため、setUpClassは使用できません。
ケサンダル2013年

2
@JohnM。:unittest2バックポートパッケージをダウンロードして、古いpython-distですべての新しいものを入手できます。
マッケ2013年

質問はPython2を扱っていますが、答えはPython 3にも有効であるため、Python2が非推奨になったためURLを変更しました。
CharlesB

66

ダニエルの答えは正しいのですが、ここでは、そのような呼び出していないとして私が見つけたいくつかの一般的な間違い、回避するための一例であるsuper()setUpClass()するときTestCaseのサブクラスであるunittest.TestCase(のようにdjango.testfalcon.testing)を。

のドキュメントにsetUpClass()super()、そのような場合に呼び出す必要があるとは記載されていません。そうしないと、この関連する質問に見られるように、エラーが発生します。

class SomeTest(TestCase):
    def setUp(self):
        self.user1 = UserProfile.objects.create_user(resource=SomeTest.the_resource)

    @classmethod
    def setUpClass(cls):
        """ get_some_resource() is slow, to avoid calling it for each test use setUpClass()
            and store the result as class variable
        """
        super(SomeTest, cls).setUpClass()
        cls.the_resource = get_some_resource()

1
これは、TestCaseがのサブクラスである場合にのみ関係することに注意してくださいunittest.TestCase
EliadL 2018年

3

あなたはので、あなたが行ってください1.9+ジャンゴを使用しているとして、その後限り...テストのためのいくつかのデータをロードする必要があるため、ここで終わった場合setUpTestData

class MyTests(TestCase):

    @classmethod
    def setUpTestData(cls):
        # Set up data for the whole TestCase
        cls.foo = Foo.objects.create(bar="Test")

    def test1(self):
        self.assertEqual(self.foo.bar, 'Test') 

2

setUpの呼び出しを重複排除しようとせず、一度だけ呼び出します。

例えば:

class MyClass(object):
    ...

def _set_up():
    code to do one-time setup

_set_up()

これにより、モジュールが最初にロードされたときに_set_up()が呼び出されます。モジュールレベルの関数として定義しましたが、MyClassのクラスメソッドにすることもできます。


2

設定するすべてのコードをmySelTestの外に一度配置します。

setup_done = False

class mySelTest(unittest.TestCase):

    def setUp(self):
        print str(setup_done)

        if setup_done:
            return

        setup_done = True
        print str(setup_done)

もう1つの可能性は、インスタンス化するシングルトンクラスを使用することです。このクラスはsetUp()__new__コードを1回だけ実行し、残りの呼び出しでオブジェクトインスタンスを返します。参照:シングルトンを定義するためのシンプルでエレガントな方法はありますか?

class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(
                            cls, *args, **kwargs)
            # PUT YOUR SETUP ONCE CODE HERE!
            cls.setUpBool = True

        return cls._instance

class mySelTest(unittest.TestCase):

    def setUp(self):
        # The first call initializes singleton, ever additional call returns the instantiated reference.
        print(Singleton().setUpBool)

あなたのやり方もうまくいきます。


2

setup_doneはクラス変数であり、インスタンス変数ではありません。

これをインスタンス変数として参照しています。

self.setup_done

ただし、クラス変数として参照する必要があります。

mySelTest.setup_done

修正されたコードは次のとおりです。

class mySelTest(unittest.TestCase):
    setup_done = False

    def setUp(self):
        print str(mySelTest.setup_done)

        if mySelTest.setup_done:
            return
        mySelTest.setup_done = True
        print str(mySelTest.setup_done)

2

Python 3をcls使用していますが、setupメソッドでも参照を使用できるため、次のように機能します。

class TestThing(unittest.TestCase):

  @classmethod
  def setUpClass(cls):
    cls.thing = Thing() # the `thing` is only instantiated once

  def setup(self):
    self.thing = cls.thing # ...but set on each test case instance

  def test_the_thing(self):
    self.assertTrue(self.thing is not None)

1
インスタンスメソッドであるsetUp内のclsにアクセスすることはできません(小文字のsetup()は、unittestのsetUpメソッドでも、「test」で始まるメソッドでもないため、呼び出されません。これが、おそらく取得しなかった理由です。エラー)ただし、setUpClassでクラス変数を定義すると、すべてのインスタンスメソッドでself.thingを呼び出すことができます
khuang834 2010

ありがとう、@ khuang834。あなたが正しい。これは私の側の見落としでした。
グレッグロス

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.