conftest.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import copy
  2. import shutil
  3. from textwrap import dedent
  4. import pytest
  5. import six
  6. from django.conf import settings
  7. try:
  8. import pathlib
  9. except ImportError:
  10. import pathlib2 as pathlib
  11. pytest_plugins = "pytester"
  12. REPOSITORY_ROOT = pathlib.Path(__file__).parent
  13. def pytest_configure(config):
  14. config.addinivalue_line(
  15. "markers", "django_project: options for the django_testdir fixture"
  16. )
  17. def _marker_apifun(extra_settings="", create_manage_py=False, project_root=None):
  18. return {
  19. "extra_settings": extra_settings,
  20. "create_manage_py": create_manage_py,
  21. "project_root": project_root,
  22. }
  23. @pytest.fixture
  24. def testdir(testdir, monkeypatch):
  25. monkeypatch.delenv("PYTEST_ADDOPTS", raising=False)
  26. return testdir
  27. @pytest.fixture(scope="function")
  28. def django_testdir(request, testdir, monkeypatch):
  29. from pytest_django_test.db_helpers import DB_NAME, TEST_DB_NAME
  30. marker = request.node.get_closest_marker("django_project")
  31. options = _marker_apifun(**(marker.kwargs if marker else {}))
  32. if hasattr(request.node.cls, "db_settings"):
  33. db_settings = request.node.cls.db_settings
  34. else:
  35. db_settings = copy.deepcopy(settings.DATABASES)
  36. db_settings["default"]["NAME"] = DB_NAME
  37. db_settings["default"]["TEST"]["NAME"] = TEST_DB_NAME
  38. test_settings = (
  39. dedent(
  40. """
  41. import django
  42. # Pypy compatibility
  43. try:
  44. from psycopg2ct import compat
  45. except ImportError:
  46. pass
  47. else:
  48. compat.register()
  49. DATABASES = %(db_settings)s
  50. INSTALLED_APPS = [
  51. 'django.contrib.auth',
  52. 'django.contrib.contenttypes',
  53. 'tpkg.app',
  54. ]
  55. SECRET_KEY = 'foobar'
  56. MIDDLEWARE = [
  57. 'django.contrib.sessions.middleware.SessionMiddleware',
  58. 'django.middleware.common.CommonMiddleware',
  59. 'django.middleware.csrf.CsrfViewMiddleware',
  60. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  61. 'django.contrib.messages.middleware.MessageMiddleware',
  62. ]
  63. if django.VERSION < (1, 10):
  64. MIDDLEWARE_CLASSES = MIDDLEWARE
  65. TEMPLATES = [
  66. {
  67. 'BACKEND': 'django.template.backends.django.DjangoTemplates',
  68. 'DIRS': [],
  69. 'APP_DIRS': True,
  70. 'OPTIONS': {},
  71. },
  72. ]
  73. %(extra_settings)s
  74. """
  75. )
  76. % {
  77. "db_settings": repr(db_settings),
  78. "extra_settings": dedent(options["extra_settings"]),
  79. }
  80. )
  81. if options["project_root"]:
  82. project_root = testdir.mkdir(options["project_root"])
  83. else:
  84. project_root = testdir.tmpdir
  85. tpkg_path = project_root.mkdir("tpkg")
  86. if options["create_manage_py"]:
  87. project_root.ensure("manage.py")
  88. tpkg_path.ensure("__init__.py")
  89. app_source = REPOSITORY_ROOT / "../pytest_django_test/app"
  90. test_app_path = tpkg_path.join("app")
  91. # Copy the test app to make it available in the new test run
  92. shutil.copytree(six.text_type(app_source), six.text_type(test_app_path))
  93. tpkg_path.join("the_settings.py").write(test_settings)
  94. monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "tpkg.the_settings")
  95. def create_test_module(test_code, filename="test_the_test.py"):
  96. r = tpkg_path.join(filename)
  97. r.write(dedent(test_code), ensure=True)
  98. return r
  99. def create_app_file(code, filename):
  100. r = test_app_path.join(filename)
  101. r.write(dedent(code), ensure=True)
  102. return r
  103. testdir.create_test_module = create_test_module
  104. testdir.create_app_file = create_app_file
  105. testdir.project_root = project_root
  106. testdir.makeini(
  107. """
  108. [pytest]
  109. addopts = --strict
  110. console_output_style=classic
  111. """
  112. )
  113. return testdir
  114. @pytest.fixture
  115. def django_testdir_initial(django_testdir):
  116. """A django_testdir fixture which provides initial_data."""
  117. django_testdir.project_root.join("tpkg/app/migrations").remove()
  118. django_testdir.makefile(
  119. ".json",
  120. initial_data="""
  121. [{
  122. "pk": 1,
  123. "model": "app.item",
  124. "fields": { "name": "mark_initial_data" }
  125. }]""",
  126. )
  127. return django_testdir