如何在django单元测试中只加载一次灯具?

时间:2009-06-11 05:18:28

标签: django unit-testing

在单元测试中,我需要加载灯具,如下所示:

   class TestQuestionBankViews(TestCase):

        # Load fixtures
        fixtures = ['qbank']

        def setUp(self):                           
            login = self.client.login(email="mail@gmail.com",password="welcome")        


        def test_starting_an_exam_view(self):               
            candidate = Candidate.objects.get(email="mail@gmail.com")
            .......etc


        def test_review_view(self):
            self.assertTrue(True)            
            .........

       def test_review_view2(self):
            self.assertTrue(True)
            .........

问题:

这些灯具正在为每次测试加载,即在 test_review_view test_review_view2 等之前加载,因为Django会在每次测试后刷新数据库。

此行为导致测试需要很长时间才能完成。

如何防止这种冗余夹具加载?

有没有办法在setUp中加载灯具并在测试类完成后冲洗它们,而不是在每次测试之间刷新?

7 个答案:

答案 0 :(得分:18)

使用django-nose和一些代码,您可以完全按照要求执行操作。使用django-nose,您可以拥有每个包,每个模块和每个类别的设置和拆卸功能。这允许您在其中一个较高级别的设置函数中加载灯具,并禁用django.test.TestCase在测试之间重置灯具。

以下是一个示例测试文件:

from django.test import TestCase
from django.core import management

    def setup():
        management.call_command('loaddata', 'MyFixture.json', verbosity=0)

    def teardown():
        management.call_command('flush', verbosity=0, interactive=False)

    class MyTestCase(TestCase):

        def _fixture_setup(self):
            pass

        def test_something(self):
            self.assertEqual(1, 1)

请注意,设置和拆除都在课堂之外。设置将在此文件中的所有测试类之前运行,并且将在所有测试类之后运行拆解。

在课堂上,你会注意到 def _fixture_setup(self)方法。这将覆盖在每次测试之间重置数据库的功能。

请记住,如果您的测试向数据库写入任何内容,则可能会使测试无效。因此,任何其他需要为每个测试重新加载灯具的测试都应放在不同的测试文件中。

答案 1 :(得分:12)

或者使用setUpModule:

def setUpModule():
    print 'Module setup...'

def tearDownModule():
    print 'Module teardown...'

class Test(unittest.TestCase):
    def setUp(self):
       print 'Class setup...'

    def tearDown(self):
       print 'Class teardown...'

    def test_one(self):
        print 'One'

    def test_two(self):
        print 'Two'

打印:

Creating test database for alias 'default'...
Module setup...
Class setup...
One
Class teardown...
Class setup...
Two
Class teardown...
Module teardown...

答案 2 :(得分:5)

如果您不想为此目的安装新软件包,可以将Tom Wainwright's solutionmhost's solution合并。

在您的测试文件中,在任何类之外添加这些函数:

from django.core.management import call_command

def setUpModule():
    call_command(
        'loaddata', 
        'path_to_fixture.json',
        verbosity=0
    )

def tearDownModule():
    call_command('flush', interactive=False, verbosity=0)

如果您不希望将这些灯具加载到数据库中以用于所有测试用例,split the test into multiple files通过在名为tests的应用中创建新目录,请添加空__init__.py文件告诉Python这是一个包,并添加包含以test开头的文件名的测试文件,因为运行器将查找与模式test*.py匹配的文件

答案 3 :(得分:5)

由于它的价值,并且由于没有接受的答案,Django 1.8现在提供了开箱即用的功能 - 前提是您使用的是支持事务的数据库后端。

它还为每个TestCase类添加一次TestCase.setUpTestData()方法,用于手动创建测试数据。

请参阅the Django 1.8 release notes

答案 4 :(得分:3)

我遇到了同样的问题。一般来说,使用django的测试运行器没有一个非常好的方法。您可能对此thread

感兴趣

话虽如此,如果所有测试用例都使用相同的fixture,并且他们不以任何方式修改数据,那么使用initial_data就可以了。

答案 5 :(得分:1)

我曾遇到过类似的问题,并最终编写了自己的测试运行器。在我的情况下,initial_data不是正确的地方,initial_data会在syncdb期间加载,这是我不想要的。我在测试套件运行之前覆盖setup_teardown_test_environment方法来加载我的自定义夹具,并在完成后将其删除。

答案 6 :(得分:0)

django-nose为这个问题提供了一个现成的解决方案:简单地将django_nose.FastFixtureTestCase子类化。

此外,django-nose支持夹具捆绑,通过每次测试运行只加载一组固定装置,可以加快测试运行速度。在适当的情况下将FastFixtureTestCase子类化后,使用--with-fixture-bundling选项运行django-nose测试运行器。

有关详细信息,请参阅django-nose on pypi