Docker中Pytest与Selenium测试套件数据库不一致问题
修复步骤
1. 统一测试环境的数据库配置
确保Django测试时连接到Docker Compose中的Postgres服务,而非本地数据库:
- 在
settings.py的测试环境配置中,将数据库HOST设为Postgres服务名(即你compose里的postgres):# settings.py import os if os.environ.get('TEST_ENV') == 'docker': DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.environ.get('POSTGRES_NAME'), 'USER': os.environ.get('POSTGRES_USER'), 'PASSWORD': os.environ.get('POSTGRES_PASSWORD'), 'HOST': 'postgres', # 必须用compose服务名,不能是localhost 'PORT': '5432', 'TEST': { 'NAME': 'test_tutorial', # 明确指定测试数据库名 } } } - 执行测试时通过环境变量指定测试环境:
docker compose run --rm web TEST_ENV=docker pytest
2. 修正Splinter的服务访问配置
让Selenium容器正确访问Web容器的测试服务,修改conftest.py中的fixture:
# conftest.py import pytest from pytest_django.live_server_helper import LiveServer @pytest.fixture(scope='session') def test_server(): # 让Web测试服务监听所有网络接口,允许Docker内部访问 server = LiveServer(host='0.0.0.0', port=8000) yield server server.stop() @pytest.fixture(scope='function') def splinter_webdriver(): return 'remote' @pytest.fixture(scope='function') def splinter_remote_url(): # Selenium服务的Docker内部地址 return 'http://selenium:4444/wd/hub' @pytest.fixture(scope='function') def splinter_site_url(test_server): # 让Selenium通过Web容器服务名访问测试服务,而非localhost return 'http://web:8000'
这里的关键是splinter_site_url使用Docker Compose中Web服务的名称(web),而非localhost——因为Selenium容器在独立的网络空间,localhost指向自身而非Web容器。
3. 解决测试数据库占用问题
- 添加自动关闭数据库连接的fixture,确保测试结束后释放连接:
@pytest.fixture(scope='function', autouse=True) def close_db_connections(): yield from django.db import connections for conn in connections.all(): conn.close() - 避免使用
--forked等会创建子进程的pytest参数,防止多个进程同时持有数据库连接。 - 确保测试用例使用默认的事务隔离模式(pytest-django的
django_dbfixture默认会在测试后回滚事务),不要手动提交事务除非必要。
4. 验证数据一致性
- 在测试用例中,创建数据后无需手动提交事务,pytest-django会自动处理隔离:
def test_profile_list(splinter_browser): # 使用factoryboy创建测试数据 ProfileFactory(name='Test Profile') # 访问列表页面 splinter_browser.visit('/profiles/') # 验证数据是否存在 assert 'Test Profile' in splinter_browser.html - 如果仍看不到数据,可在测试中添加断点,在Web容器内执行
docker compose exec web python manage.py shell查询数据库,确认数据是否真的写入;同时查看Selenium获取的页面源码,排除前端渲染问题。
内容的提问来源于stack exchange,提问作者Ruff9
相关产品推荐
相关产品推荐

