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

时间:2022-11-19 10:27:21

In unit tests I need to load fixtures, as below:

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

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

Problem:

问题:

These fixtures are loading for every test, i.e. before test_review_view, test_review_view2, etc., as Django flushes the database after every test.

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

This behaviour is causing tests to take a long time to complete.

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

How can I prevent this redundant fixture loading?

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

Is there a way to load fixtures in setUp and flush them when the test class is finished, instead of flushing between every test?

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

7 个解决方案

#1


17  

Using django-nose and a bit of code, you can do exactly what you asked for. With django-nose, you can have per-package, per-module and per-class setup and teardown functions. That allows you to load your fixtures in one of the higher-up setup functions and disable the django.test.TestCase's resetting of the fixtures between tests.

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

Here is an example test file:

这是一个示例测试文件:

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)

Notice that setup and teardown are outside of the class. The setup will be run before all the test classes in this file, and the teardown will be run after all test classes.

请注意,安装和拆卸不在课堂之内。设置将在此文件中的所有测试类之前运行,并且将在所有测试类之后运行拆卸。

Inside the class, you will notice the def _fixture_setup(self) method. This overrides the function that resets the database in between each test.

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

Keep in mind that if your tests write anything to the database, this could invalidate your tests. So any other tests that need fixtures reloaded for each test should be put in a different test file.

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

#2


10  

Or use setUpModule:

或者使用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'

prints:

打印:

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

#3


5  

If you don't feel like installing a new package just for this purpose, you can combine Tom Wainwright's solution and mhost's solution.

如果您不想为此目的安装新软件包,可以将Tom Wainwright的解决方案与mhost的解决方案结合起来。

In your testfile, add these functions outside of any classes:

在testfile中,在任何类之外添加这些函数:

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)

If you don't want to have these fixtures loaded into the database for all test cases, split the test into multiple files by creating a new directory in the app called tests, add an empty __init__.py file to tell Python that this is a package, and add your test files with file names that begin with test, since the runner will look for files matching the pattern test*.py

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

#4


5  

For what it's worth, and since there's no accepted answer, Django 1.8 now provides this functionality out of the box - provided you're using a database backend that supports transactions.

对于它的价值,并且因为没有可接受的答案,Django 1.8现在提供开箱即用的功能 - 只要您使用支持事务的数据库后端。

It also adds the TestCase.setUpTestData() method for the manual creation of test data once per TestCase class.

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

See the Django 1.8 release notes.

请参阅Django 1.8发行说明。

#5


3  

I've ran into the same problem. In general, there isn't a really good way to do that using django's test runner. You might be interested in this thread

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

With that being said, if all the testcases use the same fixture, and they don't modify the data in any way, then using initial_data would work.

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

#6


1  

I had a similar problem once and ended up writing my own test runner. In my case initial_data was not the right place as initial_data would be loaded during syncdb, something I did not want. I overrode setup_ and teardown_test_environment methods to load my custom fixture before the test suite was run and to remove it once done.

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

#7


0  

django-nose provides a readymade solution to this problem: simply subclass django_nose.FastFixtureTestCase.

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

Additionally, django-nose supports fixture bundling, which can speed up your test runs even more by only loading each unique set of fixtures once per test run. After having subclassed FastFixtureTestCase where appropriate, run the django-nose test runner using the --with-fixture-bundling option.

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

See django-nose on pypi for more information.

有关更多信息,请参阅pypi上的django-nose。

#1


17  

Using django-nose and a bit of code, you can do exactly what you asked for. With django-nose, you can have per-package, per-module and per-class setup and teardown functions. That allows you to load your fixtures in one of the higher-up setup functions and disable the django.test.TestCase's resetting of the fixtures between tests.

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

Here is an example test file:

这是一个示例测试文件:

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)

Notice that setup and teardown are outside of the class. The setup will be run before all the test classes in this file, and the teardown will be run after all test classes.

请注意,安装和拆卸不在课堂之内。设置将在此文件中的所有测试类之前运行,并且将在所有测试类之后运行拆卸。

Inside the class, you will notice the def _fixture_setup(self) method. This overrides the function that resets the database in between each test.

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

Keep in mind that if your tests write anything to the database, this could invalidate your tests. So any other tests that need fixtures reloaded for each test should be put in a different test file.

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

#2


10  

Or use setUpModule:

或者使用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'

prints:

打印:

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

#3


5  

If you don't feel like installing a new package just for this purpose, you can combine Tom Wainwright's solution and mhost's solution.

如果您不想为此目的安装新软件包,可以将Tom Wainwright的解决方案与mhost的解决方案结合起来。

In your testfile, add these functions outside of any classes:

在testfile中,在任何类之外添加这些函数:

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)

If you don't want to have these fixtures loaded into the database for all test cases, split the test into multiple files by creating a new directory in the app called tests, add an empty __init__.py file to tell Python that this is a package, and add your test files with file names that begin with test, since the runner will look for files matching the pattern test*.py

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

#4


5  

For what it's worth, and since there's no accepted answer, Django 1.8 now provides this functionality out of the box - provided you're using a database backend that supports transactions.

对于它的价值,并且因为没有可接受的答案,Django 1.8现在提供开箱即用的功能 - 只要您使用支持事务的数据库后端。

It also adds the TestCase.setUpTestData() method for the manual creation of test data once per TestCase class.

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

See the Django 1.8 release notes.

请参阅Django 1.8发行说明。

#5


3  

I've ran into the same problem. In general, there isn't a really good way to do that using django's test runner. You might be interested in this thread

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

With that being said, if all the testcases use the same fixture, and they don't modify the data in any way, then using initial_data would work.

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

#6


1  

I had a similar problem once and ended up writing my own test runner. In my case initial_data was not the right place as initial_data would be loaded during syncdb, something I did not want. I overrode setup_ and teardown_test_environment methods to load my custom fixture before the test suite was run and to remove it once done.

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

#7


0  

django-nose provides a readymade solution to this problem: simply subclass django_nose.FastFixtureTestCase.

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

Additionally, django-nose supports fixture bundling, which can speed up your test runs even more by only loading each unique set of fixtures once per test run. After having subclassed FastFixtureTestCase where appropriate, run the django-nose test runner using the --with-fixture-bundling option.

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

See django-nose on pypi for more information.

有关更多信息,请参阅pypi上的django-nose。