django单元测试没有db

paw*_*que 116 testing django

是否有可能在没有设置数据库的情况下编写django单元测试?我想测试不需要db设置的业务逻辑.虽然设置db很快,但在某些情况下我真的不需要它.

moh*_*666 115

您可以继承DjangoTestSuiteRunner并覆盖要传递的setup_databases和teardown_databases方法.

创建一个新的设置文件,并将TEST_RUNNER设置为刚刚创建的新类.然后,当您运行测试时,请使用--settings标志指定新设置文件.

这是我做的:

创建一个类似于此的自定义测试套件运行器:

from django.test.simple import DjangoTestSuiteRunner

class NoDbTestRunner(DjangoTestSuiteRunner):
  """ A test runner to test without database creation """

  def setup_databases(self, **kwargs):
    """ Override the database creation defined in parent class """
    pass

  def teardown_databases(self, old_config, **kwargs):
    """ Override the database teardown defined in parent class """
    pass
Run Code Online (Sandbox Code Playgroud)

创建自定义设置:

from mysite.settings import *

# Test runner with no database creation
TEST_RUNNER = 'mysite.scripts.testrunner.NoDbTestRunner'
Run Code Online (Sandbox Code Playgroud)

当您运行测试时,如下所示运行它,并将--settings标志设置为新的设置文件:

python manage.py test myapp --settings='no_db_settings'
Run Code Online (Sandbox Code Playgroud)

更新:2018年4月

由于Django的1.8,该模块被移动到.django.test.simple.DjangoTestSuiteRunner 'django.test.runner.DiscoverRunner'

有关更多信息,请查看有关自定义测试运行器的官方doc部分

  • 很棒的答案!! 在django 1.8中,从django.test.simple导入DjangoTestSuiteRunner已经改为django.test.runner导入DiscoverRunner希望帮助某人! (26认同)
  • 如果您不想使用新的设置文件,可以使用`--testrunner`选项在命令行上指定新的TestRunner. (9认同)
  • 请注意,您需要为测试类扩展SimpleTestCase而不是TestCase.TestCase需要一个数据库. (5认同)
  • 当您有需要数据库事务的测试时,会出现此错误.显然,如果你没有数据库,你将无法运行这些测试.您应该单独运行测试.如果你只是运行通过使用python manage.py测试--settings = new_settings.py测试,它会从可能需要数据库的其他应用程序运行一大堆的其他测试. (2认同)
  • 在Django 1.8及更高版本中,可以对上述代码进行一些更正。导入语句可以从django.test.runner import更改为:import DiscoverRunner NoDbTestRunner现在必须扩展DiscoverRunner类。 (2认同)

小智 58

通常,应用程序中的测试可以分为两类

  1. 单元测试,这些测试在日照中测试代码的各个片段,不需要去数据库
  2. 实际进入数据库并测试完全集成逻辑的集成测试用例.

Django支持单元测试和集成测试.

单元测试,不需要设置和拆除数据库,这些我们应该继承SimpleTestCase.

from django.test import SimpleTestCase


class ExampleUnitTest(SimpleTestCase):
    def test_something_works(self):
        self.assertTrue(True)
Run Code Online (Sandbox Code Playgroud)

对于集成测试用例,继承自TestCase的测试用例继承自TransactionTestCase,它将在运行每个测试之前设置和拆除数据库.

from django.test import TestCase


class ExampleIntegrationTest(TestCase):
    def test_something_works(self):
        #do something with database
        self.assertTrue(True)
Run Code Online (Sandbox Code Playgroud)

此策略将确保仅为访问数据库的测试用例创建和销毁数据库,因此测试将更有效

  • 这可能会使运行测试更有效,但请注意,测试运行器仍会在初始化时创建测试数据库. (35认同)
  • 选择的答案要简单得多.非常感谢! (5认同)

the*_*max 28

django.test.simple

  warnings.warn(
      "The django.test.simple module and DjangoTestSuiteRunner are deprecated; "
      "use django.test.runner.DiscoverRunner instead.",
      RemovedInDjango18Warning)
Run Code Online (Sandbox Code Playgroud)

所以覆盖DiscoverRunner而不是DjangoTestSuiteRunner.

 from django.test.runner import DiscoverRunner

 class NoDbTestRunner(DiscoverRunner):
   """ A test runner to test without database creation/deletion """

   def setup_databases(self, **kwargs):
     pass

   def teardown_databases(self, old_config, **kwargs):
     pass
Run Code Online (Sandbox Code Playgroud)

使用那样:

python manage.py test app --testrunner=app.filename.NoDbTestRunner
Run Code Online (Sandbox Code Playgroud)


Pau*_*aul 8

我选择继承django.test.runner.DiscoverRunner并对该run_tests方法进行了一些补充.

我的第一个添加检查是否需要设置数据库,并允许在需要数据库时启动正常setup_databases功能.teardown_databases如果setup_databases允许该方法运行,我的第二次添加允许正常运行.

我的代码假定任何继承的TestCase django.test.TransactionTestCase(因此django.test.TestCase)都需要设置数据库.我做了这个假设,因为Django文档说:

如果您需要任何其他更复杂和重量级的Django特定功能,如...测试或使用ORM ...那么您应该使用TransactionTestCase或TestCase.

https://docs.djangoproject.com/en/1.6/topics/testing/tools/#django.test.SimpleTestCase

mysite的/脚本/ settings.py

from django.test import TransactionTestCase     
from django.test.runner import DiscoverRunner


class MyDiscoverRunner(DiscoverRunner):
    def run_tests(self, test_labels, extra_tests=None, **kwargs):
        """
        Run the unit tests for all the test labels in the provided list.

        Test labels should be dotted Python paths to test modules, test
        classes, or test methods.

        A list of 'extra' tests may also be provided; these tests
        will be added to the test suite.

        If any of the tests in the test suite inherit from
        ``django.test.TransactionTestCase``, databases will be setup. 
        Otherwise, databases will not be set up.

        Returns the number of tests that failed.
        """
        self.setup_test_environment()
        suite = self.build_suite(test_labels, extra_tests)
        # ----------------- First Addition --------------
        need_databases = any(isinstance(test_case, TransactionTestCase) 
                             for test_case in suite)
        old_config = None
        if need_databases:
        # --------------- End First Addition ------------
            old_config = self.setup_databases()
        result = self.run_suite(suite)
        # ----------------- Second Addition -------------
        if need_databases:
        # --------------- End Second Addition -----------
            self.teardown_databases(old_config)
        self.teardown_test_environment()
        return self.suite_result(suite, result)
Run Code Online (Sandbox Code Playgroud)

最后,我将以下行添加到项目的settings.py文件中.

mysite的/ settings.py

TEST_RUNNER = 'mysite.scripts.settings.MyDiscoverRunner'
Run Code Online (Sandbox Code Playgroud)

现在,当只运行非数据库相关的测试时,我的测试套件运行速度提高了一个数量级!:)


Roc*_*ite 6

更新:另请参阅此答案以了解如何使用第三方工具pytest.


@Cesar是对的.意外运行后./manage.py test --settings=no_db_settings,未指定应用程序名称,我的开发数据库被清除.

为了更安全的方式,使用相同的NoDbTestRunner,但结合以下内容mysite/no_db_settings.py:

from mysite.settings import *

# Test runner with no database creation
TEST_RUNNER = 'mysite.scripts.testrunner.NoDbTestRunner'

# Use an alternative database as a safeguard against accidents
DATABASES['default']['NAME'] = '_test_mysite_db'
Run Code Online (Sandbox Code Playgroud)

您需要创建一个_test_mysite_db使用外部数据库工具调用的数据库.然后运行以下命令以创建相应的表:

./manage.py syncdb --settings=mysite.no_db_settings
Run Code Online (Sandbox Code Playgroud)

如果您使用的是South,请运行以下命令:

./manage.py migrate --settings=mysite.no_db_settings
Run Code Online (Sandbox Code Playgroud)

好!

您现在可以通过以下方式快速(和安全)地运行单元测试:

./manage.py test myapp --settings=mysite.no_db_settings
Run Code Online (Sandbox Code Playgroud)