如何设置和拆卸临时 django 数据库以进行单元测试?

发布于 2024-08-26 16:41:59 字数 1110 浏览 5 评论 0原文

我想要一个包含一些单元测试的 python 模块,我可以将其传递给 hg bisect --command。

单元测试正在测试 django 应用程序的某些功能,但我认为我不能使用 hg bisect --command manage.py test mytestapp ,因为 mytestapp 必须在 settings.py 中启用,并且当 hg bisect 更新工作目录时,对 settings.py 的编辑将被破坏。

因此,我想知道以下内容是否是最好的方法:

import functools, os, sys, unittest

sys.path.append(path_to_myproject)
os.environ['DJANGO_SETTINGS_MODULE'] = 'myapp.settings'


def with_test_db(func):
    """Decorator to setup and teardown test db."""
    @functools.wraps
    def wrapper(*args, **kwargs):
        try:
            # Set up temporary django db
            func(*args, **kwargs)
        finally:
            # Tear down temporary django db


class TestCase(unittest.TestCase):

    @with_test_db
    def test(self):
        # Do some tests using the temporary django db
        self.fail('Mark this revision as bad.')


if '__main__' == __name__:
    unittest.main()

如果您能提出建议,我将不胜感激:

  1. 如果有更简单的方法,也许可以子类化django.test.TestCase 但不编辑settings.py,或者,如果不编辑;
  2. 上面的“设置临时 django 数据库”和“拆除临时 django 数据库”应该是什么?

I would like to have a python module containing some unit tests that I can pass to hg bisect --command.

The unit tests are testing some functionality of a django app, but I don't think I can use hg bisect --command manage.py test mytestapp because mytestapp would have to be enabled in settings.py, and the edits to settings.py would be clobbered when hg bisect updates the working directory.

Therefore, I would like to know if something like the following is the best way to go:

import functools, os, sys, unittest

sys.path.append(path_to_myproject)
os.environ['DJANGO_SETTINGS_MODULE'] = 'myapp.settings'


def with_test_db(func):
    """Decorator to setup and teardown test db."""
    @functools.wraps
    def wrapper(*args, **kwargs):
        try:
            # Set up temporary django db
            func(*args, **kwargs)
        finally:
            # Tear down temporary django db


class TestCase(unittest.TestCase):

    @with_test_db
    def test(self):
        # Do some tests using the temporary django db
        self.fail('Mark this revision as bad.')


if '__main__' == __name__:
    unittest.main()

I should be most grateful if you could advise either:

  1. If there is a simpler way, perhaps subclassing django.test.TestCase but not editing settings.py or, if not;
  2. What the lines above that say "Set up temporary django db" and "Tear down temporary django db" should be?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

暗恋未遂 2024-09-02 16:41:59

破解了它。我现在拥有一个完全独立于任何可以使用测试数据库运行单元测试的 django 应用程序的 python 文件:

#!/usr/bin/env python
"""Run a unit test and return result.

This can be used with `hg bisect`.
It is assumed that this file resides in the same dir as settings.py

"""

import os
from os.path import abspath, dirname
import sys
import unittest

# Set up django
project_dir = abspath(dirname(dirname(__file__)))
sys.path.insert(0, project_dir)
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'

from django.db import connection
from django.test import TestCase
from django.test.utils import setup_test_environment, teardown_test_environment

from myproject import settings
from myproject.myapp.models import MyModel


class MyTestCase(TestCase):

    def test_something(self):
        # A failed assertion will make unittest.main() return non-zero
        # which if used with `hg bisect` will mark the revision as bad
        self.assertEqual(0, len(MyModel.objects.all())) # and so on


if '__main__' == __name__:
    try:
        setup_test_environment()
        settings.DEBUG = False    
        verbosity = 0
        old_database_name = settings.DATABASE_NAME
        connection.creation.create_test_db(verbosity)
        unittest.main()
    finally:
        connection.creation.destroy_test_db(old_database_name, verbosity)
        teardown_test_environment()

Cracked it. I now have one python file completely independent of any django app that can run unit tests with a test database:

#!/usr/bin/env python
"""Run a unit test and return result.

This can be used with `hg bisect`.
It is assumed that this file resides in the same dir as settings.py

"""

import os
from os.path import abspath, dirname
import sys
import unittest

# Set up django
project_dir = abspath(dirname(dirname(__file__)))
sys.path.insert(0, project_dir)
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'

from django.db import connection
from django.test import TestCase
from django.test.utils import setup_test_environment, teardown_test_environment

from myproject import settings
from myproject.myapp.models import MyModel


class MyTestCase(TestCase):

    def test_something(self):
        # A failed assertion will make unittest.main() return non-zero
        # which if used with `hg bisect` will mark the revision as bad
        self.assertEqual(0, len(MyModel.objects.all())) # and so on


if '__main__' == __name__:
    try:
        setup_test_environment()
        settings.DEBUG = False    
        verbosity = 0
        old_database_name = settings.DATABASE_NAME
        connection.creation.create_test_db(verbosity)
        unittest.main()
    finally:
        connection.creation.destroy_test_db(old_database_name, verbosity)
        teardown_test_environment()
调妓 2024-09-02 16:41:59

您必须使用内部 Django TestCase 才能执行此操作。

from django.test import TestCase

class TestCase(TestCase):

    # before every call to setUp(), the db is automatically 
    # set back to the state is was after the first syncdb then
    # all these fixture files will be loaded in the db   
    fixtures = ['mammals.json', 'birds']

    # put whatever you want here, you don't need to call the
    # super()
    def setUp(self):
        # Test definitions as before.
        call_setup_methods()

    def test(self):
        # Do some tests using the temporary django db
        self.fail('Mark this revision as bad.')

它与单元测试完全兼容,因此您的代码不需要进行太多更改。

您可以了解有关django.test、装置的更多信息, flushloaddata 命令。

如果您确实想使用装饰器来完成这项工作,您可以使用 call_command 在您的 python 程序中使用任何 django 命令。例如:

from django.core.management import call_command

call_command('flush', 'myapp')
call_command('loaddata', 'myapp')

You must use the internal Django TestCase to do so.

from django.test import TestCase

class TestCase(TestCase):

    # before every call to setUp(), the db is automatically 
    # set back to the state is was after the first syncdb then
    # all these fixture files will be loaded in the db   
    fixtures = ['mammals.json', 'birds']

    # put whatever you want here, you don't need to call the
    # super()
    def setUp(self):
        # Test definitions as before.
        call_setup_methods()

    def test(self):
        # Do some tests using the temporary django db
        self.fail('Mark this revision as bad.')

It's fully compatible with unittest so your code don't need to change much.

You can learn more about django.test, fixtures, flush and loaddata commands.

If you do want to use a decorator to do the job, you can use the call_command to use in your python program any django command. e.g :

from django.core.management import call_command

call_command('flush', 'myapp')
call_command('loaddata', 'myapp')
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文