代码之家  ›  专栏  ›  技术社区  ›  Rama Vadakattu

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

  •  24
  • Rama Vadakattu  · 技术社区  · 17 年前

    在单元测试中,我需要加载固定装置,如下所示:

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

    问题:

    这些固定装置在每次试验前都在加载 测试回顾视图 , 测试回顾视图2 等等,因为Django在每次测试后都会刷新数据库。

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

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

    有办法把固定装置装进去吗 setUp 在测试类完成时刷新它们,而不是在每次测试之间刷新它们?

    7 回复  |  直到 12 年前
        1
  •  20
  •   mhost    14 年前

    使用 django-nose 再加上一点代码,你就可以按你的要求做了。使用django nose,您可以拥有每个包、每个模块和每个类的设置和拆卸功能。这允许您在一个更高的设置函数中加载fixture,并禁用django.test.TestCase在测试之间重置fixture。

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

    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)
    

    注意,setup和teardown不在类中。安装程序将在此文件中的所有测试类之前运行,而拆卸程序将在所有测试类之后运行。

    在课堂上,你会注意到 固定装置设置(自) 方法。这将重写在每次测试之间重置数据库的函数。

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

        2
  •  13
  •   Tom Wainwright    12 年前

    或使用设置模块:

    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...
    
        3
  •  7
  •   Community Mohan Dere    9 年前

    如果您不想为此目的安装一个新包,可以将 Tom Wainwright's solution mhost'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)
    

    如果不想将这些fixture加载到所有测试用例的数据库中, split the test into multiple files 通过在应用程序中创建名为 tests ,添加空 __init__.py 文件来告诉Python这是一个包,并添加以 test ,因为运行程序将查找与模式匹配的文件 test*.py

        4
  •  6
  •   oogles    10 年前

    既然没有公认的答案,Django 1.8现在就提供了这种现成的功能——只要您使用的是支持事务的数据库后端。

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

    the Django 1.8 release notes .

        5
  •  3
  •   jamesls    17 年前

    我也遇到过同样的问题。一般来说,使用django的测试运行程序并不是一个很好的方法。你可能对这个感兴趣 thread

    也就是说,如果所有的测试用例使用相同的fixture,并且它们没有以任何方式修改数据,那么使用初始的_数据就可以了。

        6
  •  1
  •   Manoj Govindan    17 年前

    有一次我也遇到过类似的问题,最后我自己写了一篇测试报告。就我而言 initial_data 不是一个合适的地方 初始数据 将在 syncdb ,一些我不想要的东西。我唱过头了 setup_ teardown_test_environment 方法在运行测试套件之前加载自定义fixture并在完成后将其移除。

        7
  •  0
  •   Joel Crocker    12 年前

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

    此外,django nose支持fixture绑定,通过每次测试运行只加载一次每个惟一的fixture集,可以更快地运行测试。子类化之后 FastFixtureTestCase 在适当的情况下,使用 --with-fixture-bundling 选择。

    django-nose on pypi 更多信息。