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

Posted

技术标签:

【中文标题】对一组自动化测试只运行一次 setUp【英文标题】:Run setUp only once for a set of automated tests 【发布时间】:2012-12-27 16:11:47 【问题描述】:

我的 Python 版本是 2.6。

我只想执行一次测试 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 ---

为什么这不起作用?我错过了什么吗?

【问题讨论】:

Unittest 为每个测试创建单独的实例 不要这样做。实施一些其他机制。但不要试图改变setUp的含义。 Unittest setUp/tearDown for several tests的可能重复 【参考方案1】:

我正在使用 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 = TestThing.thing # ...but set on each test case instance

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

【讨论】:

不能在setUp中访问cls,它是一个实例方法(小写的setup()不会被调用,因为它不是unittest的setUp方法,也不是'test'开头的方法,这可能是您没有收到错误的原因)但是,一旦您在 setUpClass 中定义了类变量,您就可以在所有实例方法中简单地调用 self.thing 谢谢@khuang834。你说得对。这是我的疏忽。【参考方案2】:

对于 python >3,您可以通过定义 startTestRun,stopTestRununittest.TestResult class 来实现。回复https://***.com/a/64892396/2679740

【讨论】:

【参考方案3】:

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

【讨论】:

感谢您的回复。由于我使用的是 Python 2.6.6,所以 setUpClass 不可用。 @JohnM.:你可以下载 unittest2 backport 包并在旧的 python-dist 上获取所有新的东西。 该问题涉及 Python 2,但由于该答案对 Python 3 也有效,因此我更改了 URL,因为不推荐使用 Python 2。【参考方案4】:

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

【讨论】:

【参考方案5】:

Daniel's answer 是正确的,但这里有一个例子可以避免我发现的一些常见错误,例如当TestCaseunittest.TestCase 的子类时,在setUpClass() 中不调用super()(如django.testfalcon.testing)。

setUpClass() 的文档没有提到在这种情况下您需要调用 super()。如果不这样做,您将收到错误消息,如 this related question 所示。

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()

【讨论】:

请注意,这仅在 TestCaseunittest.TestCase 的子类时才相关。【参考方案6】:

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)

【讨论】:

【参考方案7】:

将您想要设置的所有代码放在 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)

另一种可能性是在setUp() 中实例化一个Singleton 类,它只会运行一次__new__ 代码并为其余调用返回对象实例。 见:Is there a simple, elegant way to define singletons?

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)

不过你的方法也行。

【讨论】:

【参考方案8】:

不要尝试对 setUp 的调用进行重复数据删除,只需调用一次即可。

例如:

class MyClass(object):
    ...

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

_set_up()

这将在模块第一次加载时调用 _set_up()。我已将其定义为模块级函数,但您同样可以将其设为 MyClass 的类方法。

【讨论】:

以上是关于对一组自动化测试只运行一次 setUp的主要内容,如果未能解决你的问题,请参考以下文章

pytest--测试用例setup和teardown

pytest文档4-测试用例setup和teardown

Python 单元测试 之setUP() 和 tearDown()

测试用例 setup 和 和 teardown

unittest

使用 timeit 为不同的测试语句只运行一次设置代码