【问题标题】:How to setup and teardown temporary django db for unit testing?如何为单元测试设置和拆除临时 django db?
【发布时间】:2010-03-28 15:41:27
【问题描述】:

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

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

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

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 db”和“拆除临时 django db”的行应该是什么?

【问题讨论】:

    标签: python django unit-testing mercurial


    【解决方案1】:

    破解它。我现在有一个完全独立于任何可以使用测试数据库运行单元测试的 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()
    

    【讨论】:

    • 谢谢。我希望这可以向其他人展示如何为任意单元测试(包括鼻子测试)设置 django 测试数据库。
    【解决方案2】:

    您必须使用内部 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.')
    

    它与 unittest 完全兼容,因此您的代码无需进行太多更改。

    您可以了解有关django.test, fixturesflushloaddata 命令的更多信息。

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

    from django.core.management import call_command
    
    call_command('flush', 'myapp')
    call_command('loaddata', 'myapp')
    

    【讨论】:

    • 如果我将你的代码放到一个名为 mytest.py 的文件中,我仍然不能只运行python mytest.py 来运行单元测试,而这正是我所需要的。
    • @blokeley:你有两个明显的选择。测试进入models.py 或进入tests.py。如果您使用tests.py 而不是mytest.py,您会很高兴。
    猜你喜欢
    • 1970-01-01
    • 2019-11-17
    • 1970-01-01
    • 2011-06-20
    • 2014-11-25
    • 1970-01-01
    • 1970-01-01
    • 2015-01-25
    • 2014-03-02
    相关资源
    最近更新 更多