我正在使用具有以下数据库设置的测试数据库运行pytests。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres',
'USER': 'something',
'PASSWORD': 'password',
},
}
使用@ pytest.mark.django_db,我的测试函数访问一个名为' test_postgres'的数据库。为测试而创建。
@pytest.mark.django_db
def test_example():
from django.db import connection
cur_ = connection.cursor()
print cur_.db.settings_dict
输出:
{'ENGINE': 'django.db.backends.postgresql_psycopg2', 'AUTOCOMMIT': True, 'ATOMIC_REQUESTS': False, 'NAME': 'test_postgres', 'TEST_MIRROR': None,...
但如果我在test_example中运行一个线程:
def function_to_run():
from django.db import connection
cur_ = connection.cursor
logger.error(cur_.db.settings_dict)
@pytest.mark.django_db
def test_example():
p = multiprocessing.Process(target=function_to_run)
p.start()
我可以看到,在该线程中,光标正在使用名为' postgres'这是非测试数据库。输出:
{'ENGINE': 'django.db.backends.postgresql_psycopg2', 'AUTOCOMMIT': True, 'ATOMIC_REQUESTS': False, 'NAME': 'postgres', 'TEST_MIRROR': None,...
有没有办法将数据库连接参数从原始测试函数传递给我的线程,并告诉我的线程例程使用相同的数据库名称(' test_postgres')作为我的测试函数?
答案 0 :(得分:2)
我找到了解决问题的方法。
首先,您准备一个单独的Django设置文件进行测试(settings_pytest.py),并使用以下DATABASES设置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'test_database',
'TEST_NAME': 'test_database',
'USER': 'something',
'PASSWORD': 'password',
},
}
请注意,我们定义了TEST_NAME,它与NAME相同,因此无论是否运行测试运行,我们都将访问相同的数据库。
现在您需要创建此数据库,然后运行' syncdb'并且'迁移'首先:
sql> CREATE DATABASE test_database;
manage.py syncdb --settings=settings_pytest
manage.py migrate --settings=settings_pytest
最后,您可以使用以下命令运行测试:
py.test --reuse-db
您需要指定--reuse-db,因为默认数据库与测试数据库相同,所以数据库重新创建永远不会有效。如果数据库发生更改,则需要使用上述命令手动重新创建数据库。
对于测试本身,如果要向生成的子进程需要访问的数据库添加记录,请记住将事务= True添加到pytest装饰器。
def function_to_run():
Model.objects.count() == 1
@pytest.mark.django_db(transaction=True)
def test_example():
obj_ = Model()
obj_.save()
p = multiprocessing.Process(target=function_to_run)
p.start()
答案 1 :(得分:0)
在function_to_run()
声明中,您正在进行from django.db import connection
。您确定将使用正确的测试数据库设置吗?我怀疑你正在使用的装饰器修改connection
导入以使用test_postgres
而不是postgres
但是因为你在装饰器范围之外导入它没有使用正确的导入器。如果你把它放在装饰器包装的函数中会发生什么呢......
@pytest.mark.django_db
def test_example():
def function_to_run():
from django.db import connection
cur_ = connection.cursor
logger.error(cur_.db.settings_dict)
p = multiprocessing.Process(target=function_to_run)
p.start()
编辑:
我对pytest_django并不熟悉所以我此时在黑暗中拍摄,我想象标记功能也允许你装饰一个类,所以你试过把所有想要使用它的测试共享函数和db在一个TestCase类中?像这样:
from django.test import TestCase
@pytest.mark.django_db
class ThreadDBTests(TestCase):
# The function we want to share among tests
def function_to_run():
from django.db import connection
cur_ = connection.cursor
logger.error(cur_.db.settings_dict)
# One of our tests taht needs the db
def test_example1():
p = multiprocessing.Process(target=function_to_run)
p.start()
# Another test that needs the DB
def test_example2():
p = multiprocessing.Process(target=function_to_run)
p.start()