对于一组自动化测试,只运行一次setUp


81

我的Python版本是2.6。

我只想执行一次test setUp方法,因为我在那里执行了所有测试所需的操作。

我的想法是创建一个布尔变量,该变量在第一次执行后将设置为“ true”,然后禁用对setup方法的多个调用。

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

Answers:


113

您可以使用setUpClass定义每个测试套件只能运行一次的方法。


感谢您的回复。由于我使用的是Python 2.6.6,因此setUpClass不可用。
Kesandal

2
@JohnM .:您可以下载unittest2 backport软件包,并在旧的python-dist上获取所有新内容。
Macke

这个问题与Python 2有关,但是由于答案也对Python 3有效,因此自Python 2弃用以来,我更改了URL。
CharlesB

64

丹尼尔的回答是正确的,但在这里是为了避免一些常见的错误,我发现,如不调用一个例子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 '18 -10-22

3

如果由于需要加载一些数据进行测试而最终来到这里...那么就您使用Django 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)

另一种可能性是,您具有实例化的Singleton类,该类setUp()将仅运行__new__一次代码,并为其余调用返回对象实例。请参阅:是否有一种简单,优雅的方法来定义单例?

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)

1

我正在使用Python 3,发现clssetup方法中也提供了引用,因此可以进行以下工作:

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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.