提问人:Ruff9 提问时间:11/16/2023 最后编辑:Ruff9 更新时间:11/22/2023 访问量:53
Docker 中的 Pytest 和 Selenium:测试套件使用的数据库错误?
Pytest and Selenium in Docker : wrong database used for the test suite?
问:
我正在努力为一个新的 Django 项目设置我的测试运行程序。我想使用这些库:
- 姜戈 4.2
- pytest-django 4.6.0
- pytest-分裂 3.3.2
我希望它能与 Docker 一起使用。我的答案是:https://stackoverflow.com/a/58447497/3219759,但我不能让它工作。
这是我的:docker-compose.yml
version: '3.3'
services:
web:
build: jam
restart: always
command: python manage.py runserver 0.0.0.0:8000
environment:
- USE_DOCKER=True
env_file:
- .env
ports:
- "127.0.0.1:8000:8000"
volumes:
- .:/code
links:
- db
depends_on:
- db
- selenium
db:
image: postgres
environment:
- POSTGRES_USER=xxx
- POSTGRES_PASSWORD=xxx
- POSTGRES_DB=xxx
ports:
- "127.0.0.1:5432:5432"
volumes:
- pg_data:/var/lib/postgresql/data
selenium:
image: selenium/standalone-firefox:4.9.1
ports:
- "4444:4444" # Selenium
- "5900:5900" # VNC
volumes:
pg_data:
为了完成设置,我在文件中有这些夹具:conftest.py
@pytest.fixture(scope='session')
def test_server() -> LiveServer:
addr = socket.gethostbyname(socket.gethostname())
server = LiveServer(addr)
yield server
server.stop()
@pytest.fixture(scope='session')
def splinter_webdriver():
return 'remote'
@pytest.fixture(scope='session')
def splinter_remote_url():
return 'http://selenium:4444/wd/hub'
这在:settings.py
if env('USE_DOCKER') == 'yes':
import socket
ALLOWED_HOSTS = [socket.gethostbyname(socket.gethostname())]
我有一个列出所有配置文件的基本视图,以及一个要匹配的模板。此功能在我的本地服务器上工作。
相应的测试:
@pytest.mark.django_db
class TestIndexPage:
def test_profile_list(self, browser, test_server):
profile = ProfileFactory(description='first description')
browser.visit(test_server.url + reverse('index', current_app='Profiles'))
assert browser.is_text_present('first description') is True
ProfileFactory 是用 factoryboy 设置的,它似乎工作正常。
我用
$ docker compose run --rm web pytest
测试失败:
_______________________ TestIndexPage.test_profile_list ________________________
self = <profiles.tests.test_index.TestIndexPage object at 0x7fd3a15141a0>
browser = <splinter.driver.webdriver.remote.WebDriver object at 0x7fd3a0034680>
test_server = <LiveServer listening at http://172.31.0.4:49073>
def test_profile_list(self, browser, test_server):
profile1 = ProfileFactory(description='first description')
browser.visit(test_server.url + reverse('index', current_app='Profiles'))
> assert browser.is_text_present('first description') is True
E AssertionError: assert False is True
E + where False = <bound method BaseWebDriver.is_text_present of <splinter.driver.webdriver.remote.WebDriver object at 0x7fd3a0034680>>('first description')
E + where <bound method BaseWebDriver.is_text_present of <splinter.driver.webdriver.remote.WebDriver object at 0x7fd3a0034680>> = <splinter.driver.webdriver.remote.WebDriver object at 0x7fd3a0034680>.is_text_present
profiles/tests/test_index.py:13: AssertionError
基本上测试在浏览器中找不到配置文件,屏幕截图正在确认页面上的“尚无配置文件”消息。
但是当我在那里设置断点时:
@pytest.mark.django_db
class TestIndexPage:
def test_profile_list(self, browser, test_server):
profile = ProfileFactory(description='first description')
breakpoint()
browser.visit(test_server.url + reverse('index', current_app='Profiles'))
assert browser.is_text_present('first description') is True
我可以很容易地找到个人资料:
>>>>>>>>>>>>>>>>>>> PDB set_trace (IO-capturing turned off) >>>>>>>>>>>>>>>>>>>>
> /code/profiles/tests/test_index.py(11)test_profile_list()
-> browser.visit(test_server.url + reverse('index', current_app='Profiles'))
(Pdb) from profiles.models import Profile
(Pdb) Profile.objects.count()
1
(Pdb) Profile.objects.all()
<QuerySet [<Profile: george36>]>
因此,factoryboy 正在生成一个配置文件,我可以通过断点看到它。但是这个数据没有显示在selenium生成的浏览器中,测试失败。
Docker 设置中一定有问题,感觉有两个测试数据库,一个由 selenium 使用,另一个由 pytest 使用。某处连接不良。
编辑
刚刚在失败后显示的pytest警告中发现了此消息:
profiles/tests/test_index.py::TestIndexPage::test_profile_list
/code:0: PytestWarning: Error when trying to teardown test databases:
OperationalError('database "test_tutorial" is being accessed by other users\nDETAIL: There is 1 other session using the database.\n')
答:
1赞
Ruff9
11/22/2023
#1
多亏了@mariodev评论,我找到了一种让它工作的方法。
我在测试中使用了这个基本标记:
@pytest.mark.django_db
我终于让它与事务选项一起工作:
@pytest.mark.django_db(transaction=True)
评论
@pytest.fixture(scope='session')
create_db
DJANGO_SETTINGS_MODULE
create_db
pytest.ini
DJANGO_SETTINGS_MODULE
@pytest.mark.django_db
@pytest.mark.django_db(transaction=True)