代码之家  ›  专栏  ›  技术社区  ›  blokeley SERPRO

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

  •  8
  • blokeley SERPRO  · 技术社区  · 14 年前

    我希望有一个python模块,其中包含一些可以传递给我的单元测试 hg bisect --command .

    hg bisect --command manage.py test mytestapp 因为 mytestapp 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”的行应该是什么?
    2 回复  |  直到 14 年前
        1
  •  10
  •   blokeley SERPRO    14 年前

    破解了它。我现在有了一个完全独立于任何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()
    
        2
  •  5
  •   Bite code    14 年前

    必须使用内部Django测试用例来执行此操作。

    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, fixtures flush loaddata 命令。

    如果你真的想用装修工来做这项工作,你可以用 call_command 在python程序中使用任何django命令。例如:

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