рдХрдИ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде Django рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп pytest-django рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рдмреАрдЪ рд╕рд╛рдл рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рд╕рдорд╕реНрдпрд╛ рдЗрд╕ рд╕реНрдЯреИрдХ рдУрд╡рд░рдлреНрд▓реЛ рдкреНрд░рд╢реНрди рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИ: http://stackoverflow.com/questions/10121485/django-testcase-not-use-transactions-on-secondary-database
db
рд╕реНрдерд┐рд░рддрд╛ рдХрд╡рд░ рдХреЗ рддрд╣рдд Django рдХреЗ рдЯреЗрд╕реНрдЯрдХреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИред
рдореВрд▓ db
рд╕реНрдерд┐рд░рддрд╛ рд╕реЗ рдХреЛрдб рдпрд╣рд╛рдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
case = TestCase(methodName='__init__')
case._pre_setup()
request.addfinalizer(case._post_teardown)
request.addfinalizer(_django_cursor_wrapper.disable)
рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдореИрдВрдиреЗ рдЗрд╕реЗ рдЕрдкрдиреЗ рдХреЛрдб рдореЗрдВ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХреЗ рд░реВрдк рдореЗрдВ рдХреИрд╕реЗ рдкреИрдЪ рдХрд┐рдпрд╛:
case = TestCase(methodName='__init__')
case.multi_db = True
case._pre_setup()
request.addfinalizer(case._post_teardown)
request.addfinalizer(_django_cursor_wrapper.disable)
рдЬрд╛рд╣рд┐рд░ рд╣реИ рдХрд┐ multi_db рдзреНрд╡рдЬ рдореМрдЬреВрдж рд╣реИ рдФрд░ рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рдЧрд▓рдд рдкрд░ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╣реИред рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ pytest_django рдореЗрдВ multi_db рд╕рдорд░реНрдерди рд╢рд╛рдорд┐рд▓ рдХрд░рдиреЗ рдХрд╛ рд╕рд╣реА рддрд░реАрдХрд╛ рд╣реИ, рдФрд░ рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрд╕ рддрд░рд╣ рдХреЗ рдмрджрд▓рд╛рд╡ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХрд╛ рд╕рд╣реА рддрд░реАрдХрд╛ рд╣реИред
рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдХреЛрдИ рд╕реБрдЭрд╛рд╡ рд╣реИ рддреЛ рдореИрдВ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рдкрд░ рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВред
рдХреНрдпрд╛ рдЖрдк рдЕрдкрдиреЗ рдкреИрдЪ рдХрд┐рдП рдЧрдП рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдкрд░реАрдХреНрд╖рдг рджреЗ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рджреЛ рдбреЗрдЯрд╛рдмреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ? рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдордЭрдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ рдХрд┐ рдХрд┐рддрдиреЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЖрдкрдХреЛ рджреВрд╕рд░реЗ рдкрд░ рдирд┐рдпрдВрддреНрд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдФрд░ рдлрд┐рд░ multi_db рдХреЛ рд╕рддреНрдп рдкрд░ рд╕реЗрдЯ рдХрд░рдирд╛ред
DATABASES = {
'default': {
'ENGINE' : 'django.db.backends.sqlite3',
'NAME' : 'default.db',
},
'operations': {
'ENGINE' : 'django.db.backends.sqlite3',
'NAME' : 'operations.db',
},
}
рдореЗрд░реЗ рдЕрдзрд┐рдХрд╛рдВрд╢/рд╕рднреА рдореЙрдбрд▓ рджреВрд╕рд░реЗ рдбреЗрдЯрд╛рдмреЗрд╕ "рдСрдкрд░реЗрд╢рдВрд╕" рд╕реЗ рдЬреБрдбрд╝реЗ рд╣реИрдВред рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛтАЛтАЛрд╣реИ рдХрд┐ Django рдХрд╛ рдЯреЗрд╕реНрдЯрдХреЗрд╕ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдбреАрдмреА рдкрд░ рд▓реЗрдирджреЗрди рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдлреНрд▓рд╢ рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рдЕрдиреНрдп рдирд╣реАрдВ рдЬрдм рддрдХ multi_db=True
ред
рдпрд╣рд╛рдВ рдХреБрдЫ рдирдореВрдирд╛ рдкрд░реАрдХреНрд╖рдг рджрд┐рдП рдЧрдП рд╣реИрдВ:
from collection.models import Foo
def test_one(db):
Foo.objects.create()
assert Foo.objects.count() == 1
def test_two(db):
assert Foo.objects.count() == 0
рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдореЗрд░реЗ рдкреИрдЪ рдХрд┐рдП рдЧрдП db
рд╕реНрдерд┐рд░рддрд╛ рдХреЗ рд╕рд╛рде рдЖрдЙрдЯрдкреБрдЯ рдпрд╣рд╛рдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
$ py.test multi_db_test/ -vv
======================================= test session starts =======================================
platform linux2 -- Python 2.7.2 -- py-1.4.20 -- pytest-2.5.2 -- bin/python
plugins: django
collected 2 items
multi_db_test/test_foo.py:3: test_one PASSED
multi_db_test/test_foo.py:7: test_two PASSED
==================================== 2 passed in 5.75 seconds =====================================
рдпрд╣рд╛рдБ pytest_django рдХреЗ рдЕрдкрдиреЗ db
рд╕реНрдерд┐рд░рддрд╛ рдХреЗ рд╕рд╛рде рдЖрдЙрдЯрдкреБрдЯ рд╣реИ:
$ py.test multi_db_test/ -vv
======================================= test session starts =======================================
platform linux2 -- Python 2.7.2 -- py-1.4.20 -- pytest-2.5.2 -- bin/python
plugins: django
collected 2 items
multi_db_test/test_foo.py:3: test_one PASSED
multi_db_test/test_foo.py:7: test_two FAILED
============================================ FAILURES =============================================
____________________________________________ test_two _____________________________________________
db = None
def test_two(db):
> assert Foo.objects.count() == 0
E assert 1 == 0
E + where 1 = <bound method Manager.count of <django.db.models.manager.Manager object at 0x3cd0890>>()
E + where <bound method Manager.count of <django.db.models.manager.Manager object at 0x3cd0890>> = <django.db.models.manager.Manager object at 0x3cd0890>.count
E + where <django.db.models.manager.Manager object at 0x3cd0890> = Foo.objects
multi_db_test/test_foo.py:8: AssertionError
=============================== 1 failed, 1 passed in 5.85 seconds ===============================
рддреЛ рдПрдХ рддреНрд╡рд░рд┐рдд рд░реВрдк рд╕реЗ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ multi_db
рд╕реНрдерд┐рд░рддрд╛ рдФрд░ pytest.mark.django_db(multi=True)
рдПрдХ рдПрдкреАрдЖрдИ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИ? рдХрд┐рд╕реА рдФрд░ рдХреЗ рдкрд╛рд╕ рдХреЛрдИ рдмреЗрд╣рддрд░ рд╡рд┐рдЪрд╛рд░ рд╣реИ?
рдпрд╣ рд╡рд╛рдЬрд┐рдм рд▓рдЧрддрд╛ рд╣реИред рдореЗрд░реЗ рдкрд╛рд╕ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЕрдиреНрдп рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рд╣реИрдВ, рдмреЗрд╣рддрд░ рдпрд╛ рдЕрдиреНрдпрдерд╛ред
рдирдорд╕реНрдХрд╛рд░ред рдХреНрдпрд╛ рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛ multi_db
рд╕рдорд░реНрдерди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреЛрдИ рдЪрд░реНрдЪрд╛ рд╣реИ? рдбреЙрдХреНрд╕ рдХрд╛ рдХрд╣рдирд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рдХреЛ рд╕рдВрдкрд░реНрдХ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рд▓реЗрдХрд┐рди рдЗрд╕ рдкрд░ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреНрдпрд╛ рд╣реИ?
@slafs рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдмрд╣реБ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕рдорд░реНрдерди рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЕрдзрд┐рдХ рдЪрд░реНрдЪрд╛/рдЕрдиреБрд░реЛрдз рдирд╣реАрдВ рд╣реБрдП рд╣реИрдВред
multi_db=True
рдХреЛ рдкрд╛рд╕ рдХрд░рдирд╛ рдмрд╣реБрдд рдЖрд╕рд╛рди рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рдХреБрдЫ рдкреНрд░рдХрд╛рд░ рдХреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рджреНрд╡рд┐рддреАрдпрдХ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗрдЯ рдЕрдк рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЕрдЧрд░ рдХреЛрдИ рдЗрд╕ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рдХреЛ рддреИрдпрд╛рд░ рд╣реИ, рддреЛ рдпрд╣ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ :)
рдореИрдВ рд╢реБрд░реБрдЖрддреА рдкреЛрд╕реНрдЯ рдореЗрдВ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб @ftobia рдЙрд▓реНрд▓реЗрдЦреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди 1.7 рд╕реЗ Django 1.8.4 рдореЗрдВ рдЕрдкрдЧреНрд░реЗрдб рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдЗрд╕рдиреЗ рдХрд╛рдо рдХрд░рдирд╛ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ред
рдПрдХ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рдмрдЬрд╛рдп multi_db
рд╡рд░реНрдЧ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд▓рд┐рдП рдХреЛрдб рд╣реИрдВрдбрд▓рд┐рдВрдЧ рд╕реЗрдЯрдЕрдк/рдЯрд┐рдпрд░рдбрд╛рдЙрди рд▓реБрдХ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП Django рдкрд░рд┐рд╡рд░реНрддрди рдерд╛ред
@ftobia рдХреЗ рдХрд╛рд░реНрдп-рдЖрд╕рдкрд╛рд╕ рдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдореЗрдВ рдмрджрд▓рдирд╛ рдореЗрд░реЗ рд▓рд┐рдП
case = TestCase(methodName='__init__')
case.__class__.multi_db = True
case._pre_setup()
request.addfinalizer(case._post_teardown)
request.addfinalizer(_django_cursor_wrapper.disable)
+1:+1:
рдпрд╣ рд╣рдореЗрдВ Django рдЯреЗрд╕реНрдЯ рд░рдирд░ рд╕реЗ pytest рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рд╕реЗ рд░реЛрдХ рд░рд╣рд╛ рд╣реИред
рдпрд╣рд╛рдБ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ django_case.multi_db = True
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреНрдпреЛрдВ рди рдХрд░реЗрдВ https://github.com/pytest-dev/pytest-django/blob/master/pytest_django/fixtures.py#L107 ?
+1
+1
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ django_db рдорд╛рд░реНрдХрд░ рдкрд░ рдорд╛рд░реНрдХрд░ рд╣реЛрдиреЗ рд╕реЗ рдореИрдВ рдЕрдЪреНрдЫрд╛ рдПрдкреАрдЖрдИ рдкрд╕рдВрдж рдХрд░реВрдВрдЧрд╛:
@pytest.mark.django_db(transactional=True, multi_db=True)
def test_a():
pass
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд reset_sequences
(рдкреАрдЖрд░ #308) рдпрд╛ serialized_rollback
(рдкреАрдЖрд░ #353) рдХреЗ рд╕рдорд╛рди рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
"рдореБрд╢реНрдХрд┐рд▓" рднрд╛рдЧ рдХрдИ рдбреЗрдЯрд╛рдмреЗрд╕ рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП pytest-django рдХреЗ рдЖрдВрддрд░рд┐рдХ рдкрд░реАрдХреНрд╖рдг рд╕реВрдЯ рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
рдЕрдЧрд░ рдХреЛрдИ рдЗрд╕рдореЗрдВ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ рддреЛ рдореИрдВ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЗрд╕рдХреА рд╕рдореАрдХреНрд╖рд╛ рдХрд░реВрдВрдЧрд╛ рдФрд░ рдЗрд╕реЗ рдорд░реНрдЬ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реВрдВрдЧрд╛ред рдкреАрдЖрд░ рдкрд░ рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рдорд╣рд╕реВрд╕ рдХрд░реЗрдВ рдпрджрд┐ рдпрд╣ рдРрд╕рд╛ рдХреБрдЫ рд╣реИ рдЬреЛ рдЖрдкрдХреЗ рд▓рд┐рдП рджрд┐рд▓рдЪрд╕реНрдк рд╣реЛрдЧрд╛!
https://github.com/pytest-dev/pytest-django/pull/397#issuecomment -261987751 рдкрд░ рдХреБрдЫ рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдВ рдЫреЛрдбрд╝ рджреАрдВ, рдФрд░ рдПрдХ рдкреАрдЖрд░ рдмрдирд╛рдпрд╛, рдЬреЛ рдЗрд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХреЗ рд╕реЗ рдмрджрд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛: https://githubред com/pytest-dev/pytest-django/pull/431.
рдЕрд╕реНрдерд╛рдпреА рд╕рдорд╛рдзрд╛рди рдХреА рддрд▓рд╛рд╢ рдХрд░рдиреЗ рд╡рд╛рд▓реЛрдВ рдХреЗ рд▓рд┐рдП multi_db рд╕рдХреНрд╖рдо рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЕрдиреНрдп рд╡рд┐рдХрд▓реНрдкред рдЗрд╕реЗ conftest.py . рдореЗрдВ рдбрд╛рд▓реЗрдВ
def pytest_sessionstart(session):
from django.test import TransactionTestCase
TransactionTestCase.multi_db = True
рдХрд╛рдордХрд╛рдЬ рдХреА рддрд▓рд╛рд╢ рдореЗрдВ рдХрд┐рд╕реА рдФрд░ рдХреЗ рд▓рд┐рдП, рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ multi_db
Django 2.2 рдореЗрдВ рдмрд╣рд┐рд╖реНрдХреГрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рд╣реИ:
TransactionTestCase.databases = set(settings.DATABASES.keys())
@jcushman рдХреНрдпрд╛ рдЖрдк рдЕрдкрдиреЗ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдкреВрд░реНрдг рд╕реНрдерд┐рд░рддрд╛ рдпрд╛ рдХреЛрдб рд╕реНрдирд┐рдкреЗрдЯ рдХреЛ рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ?
рдЬреЛ рднреА рдХрд╛рд░рдг рдХреЗ рд▓рд┐рдП, pytest_sessionstart()
рд╣рдорд╛рд░реЗ рдЖрдзрд╛рд░ рдореЗрдВ conftest.py
рдХреБрдЫ рднреА рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рдерд╛ред рдорд╛рдирдХ рдкрд╛рдЗрдЯреЗрд╕реНрдЯ monkeypatch
рд╕рд╛рдорд╛рди рдХреЗ рд╕рд╛рде #342 рд╕реЗ рдПрдХ рдкреГрд╖реНрда рд▓рд┐рдпрд╛ рдФрд░ рд╣рдорд╛рд░реЗ рдмрд╣реБ-рдбреЗрдЯрд╛рдмреЗрд╕ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрд░ рдкрд╣реБрдВрдЪреЗ:
# OPTION 1: Function fixture; must be included with tests
@pytest.fixture
def django_db_multiple(monkeypatch, request, settings):
"""
Ensure all test functions using Django test cases have multiple database
support. This is mostly/only so that Django will wrap ALL database use with
atomic blocks like it does for DEFAULT_DB_ALIAS.
https://github.com/django/django/blob/master/django/test/testcases.py#L903
https://github.com/pytest-dev/pytest-django/issues/76
"""
from django.test import TestCase
from django.test import TransactionTestCase
db_keys = set(settings.DATABASES.keys())
monkeypatch.setattr(TestCase, 'databases', db_keys)
monkeypatch.setattr(TransactionTestCase, 'databases', db_keys)
@pytest.mark.django_db
def test_some_test(django_db_multiple):
pass
# OPTION 2: Session fixture
@pytest.fixture(autouse=True, scope='session')
def django_db_multiple():
"""
Ensure all test functions using Django test cases have multiple database
support. This is mostly/only so that Django will wrap ALL database use with
atomic blocks like it does for DEFAULT_DB_ALIAS.
https://github.com/django/django/blob/master/django/test/testcases.py#L903
https://github.com/pytest-dev/pytest-django/issues/76
https://github.com/pytest-dev/pytest/issues/1872
"""
from _pytest.monkeypatch import MonkeyPatch
from django.test import TestCase
from django.test import TransactionTestCase
from django.conf import settings
db_keys = set(settings.DATABASES.keys())
monkeypatch = MonkeyPatch()
monkeypatch.setattr(TestCase, 'databases', db_keys)
monkeypatch.setattr(TransactionTestCase, 'databases', db_keys)
yield monkeypatch
monkeypatch.undo()
_рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рд╣рдо рдПрдХ рд╕рддреНрд░ рд╕реНрдерд┐рд░рддрд╛ рдореЗрдВ рдЪрд▓реЗ рдЧрдПред_
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ Django рдкрд░реАрдХреНрд╖рдг рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд╕реНрд╡рд┐рдЪ рдХрд░рдХреЗ pytest рдорд╣рд╛рд╢рдХреНрддрд┐рдпреЛрдВ рдХреЛ рдвреАрд▓рд╛ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдЗрд╕ рдмрджрд╕реВрд░рдд (рдЕрднреА рддрдХ рдХрд╛рдо рдХрд░ рд░рд╣реЗ!) рд╣реИрдХ рдХреЗ рд▓рд┐рдП pytest-django рдЖрдВрддрд░рд┐рдХ рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдИ рдФрд░ рдкреИрдЪ рдХрд┐рдпрд╛:
from typing import Optional, Type, TypeVar
import pytest
from django.test import TransactionTestCase
from pytest_django.django_compat import is_django_unittest
TestCase = TypeVar('TestCase', bound=TransactionTestCase)
def _django_db_fixture_helper(
request, django_db_blocker, transactional: bool = False, reset_sequences: bool = False,
) -> Optional[Type[TestCase]]:
if is_django_unittest(request):
return None
if not transactional and 'live_server' in request.fixturenames:
# Do nothing, we get called with transactional=True, too.
return None
django_db_blocker.unblock()
request.addfinalizer(django_db_blocker.restore)
if transactional:
from django.test import TransactionTestCase as DjangoTestCase # noqa: WPS433
if reset_sequences:
class ResetSequenceTestCase(DjangoTestCase): # noqa: WPS431
reset_sequences = True
DjangoTestCase = ResetSequenceTestCase # type: ignore[misc] # noqa: N806
else:
from django.test import TestCase as DjangoTestCase # type: ignore[no-redef] # noqa: WPS433
return DjangoTestCase # type: ignore[return-value]
@pytest.fixture()
def db_case(request, django_db_setup, django_db_blocker):
"""Require a django test database.
This database will be setup with the default fixtures and will have
the transaction management disabled. At the end of the test the outer
transaction that wraps the test itself will be rolled back to undo any
changes to the database (in case the backend supports transactions).
This is more limited than the ``transactional_db`` resource but
faster.
If multiple database fixtures are requested, they take precedence
over each other in the following order (the last one wins): ``db``,
``transactional_db``, ``django_db_reset_sequences``.
"""
if 'django_db_reset_sequences' in request.fixturenames:
request.getfixturevalue('django_db_reset_sequences')
if (
'transactional_db' in request.fixturenames
or 'live_server' in request.fixturenames
):
request.getfixturevalue('transactional_db')
else:
django_case: Optional[Type[TransactionTestCase]] = _django_db_fixture_helper(
request, django_db_blocker, transactional=False,
)
def factory(dbs=None): # noqa: WPS430
if django_case is None:
return
CaseType: Type[TransactionTestCase] = django_case # noqa: N806
if dbs is not None:
class DatabasesSetTestCase( # noqa: WPS431
CaseType, # type: ignore[valid-type, misc]
):
databases = dbs
CaseType = DatabasesSetTestCase # noqa: N806
test_case: TransactionTestCase = CaseType(methodName='__init__')
test_case._pre_setup() # type: ignore[attr-defined] # noqa: WPS437
request.addfinalizer(
test_case._post_teardown, # type: ignore[attr-defined] # noqa: WPS437
)
return factory
рдЗрд╕рдХреЗ рд╕рд╛рде рдХреЛрдИ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реИ:
class TestCase(object):
def test_ok(
self,
db_case,
...
):
db_case(dbs=('non_default_db_alias',))
рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ db
рд╕реНрдерд┐рд░рддрд╛ рдпрд╛ pytest.mark.django_db
рдЪрд┐рд╣реНрди рдХреЗ рдмрдЬрд╛рдп рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
@jcushman рдХреНрдпрд╛ рдЖрдк рдЕрдкрдиреЗ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдкреВрд░реНрдг рд╕реНрдерд┐рд░рддрд╛ рдпрд╛ рдХреЛрдб рд╕реНрдирд┐рдкреЗрдЯ рдХреЛ рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ?
рдЕрдЧрд░ рдХреЛрдИ рдФрд░ рдЗрд╕рдореЗрдВ рдЯрдХрд░рд╛рдПрдЧрд╛ рддреЛ рдЬрд╡рд╛рдм рдЬреЛрдбрд╝рдирд╛ред
рдЖрдкрдХреЛ рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдХреЛрдб рдХреЛ conftest.py
рдореЗрдВ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ред рдпрд╣ рд╕реНрдерд┐рд░рддрд╛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЙрдард╛рдИ рдЬрд╛рддреА рд╣реИ рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рдХрд┐рд╕реА рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред
`` `рдкреАрдИ
def pytest_sessionstart (рд╕рддреНрд░):
django.test рдЖрдпрд╛рдд рд╕реЗ TransactionTestCase
TransactionTestCase.databases = set(settings.DATABASES.keys())
````
рдЗрд╕рд▓рд┐рдП рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдпрд╣ рдореБрджреНрджрд╛ рдЙрдЪрд┐рдд рдмрд╣реБ-рдбреАрдмреА рд╕рдорд░реНрдерди рдХреЗ рд▓рд┐рдП рдиреАрдЪреЗ рдЖрддрд╛ рд╣реИред рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдЙрд╕рдХреЗ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдмрдВрдж рдХрд░ рджреВрдВрдЧрд╛ред
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рдЕрд╕реНрдерд╛рдпреА рд╕рдорд╛рдзрд╛рди рдХреА рддрд▓рд╛рд╢ рдХрд░рдиреЗ рд╡рд╛рд▓реЛрдВ рдХреЗ рд▓рд┐рдП multi_db рд╕рдХреНрд╖рдо рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЕрдиреНрдп рд╡рд┐рдХрд▓реНрдкред рдЗрд╕реЗ conftest.py . рдореЗрдВ рдбрд╛рд▓реЗрдВ