如何让Selenium与Django测试套件共用同一数据库
嘿,我完全懂你遇到的困扰——Django测试套件默认会创建一个独立的测试数据库来隔离测试,但Selenium是直接访问你本地运行的真实服务器,自然就连接到了真实数据库,这就导致你的测试断言和实际数据库状态完全不匹配,测试肯定通不过。我给你详细讲讲两种方案的解决办法,优先推荐第二种哦:
方案一:让Django测试使用真实数据库(不推荐)
这个方案虽然能解决问题,但会直接污染你的真实数据,除非你有特殊需求,否则不建议用。实现方式很简单,只需要在测试类里指定使用默认数据库即可:
class VisitCreationTestCase(TestCase): databases = ['default'] # 指定测试使用真实数据库 def setUp(self) -> None: # 记得在这里清理可能影响测试的旧数据,或者用事务包裹 Visit.objects.all().delete() service = ChromeService(executable_path=ChromeDriverManager().install()) self.driver = webdriver.Chrome(service=service) test_connect(self.driver) # ... 其他测试代码不变
⚠️ 注意:测试结束后一定要清理创建的数据,不然你的真实数据库会被测试数据塞满。
方案二:让Selenium使用测试数据库(推荐)
这才是符合测试隔离原则的正确做法,核心是让Selenium访问Django测试套件启动的临时测试服务器,而不是你本地的真实服务器。Django提供了LiveServerTestCase来帮我们做这件事:
具体修改步骤:
- 导入
LiveServerTestCase替代普通的TestCase - 测试类继承
LiveServerTestCase - 把硬编码的服务器地址换成测试服务器的动态地址
self.live_server_url - 在
setUp里创建测试需要的用户(因为测试数据库是全新的,没有真实数据库里的demo用户)
修改后的完整测试代码如下:
from django.test import LiveServerTestCase # 替换成LiveServerTestCase from .models import Visit # SELENIUM from selenium import webdriver from selenium.webdriver.common.by import By from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service as ChromeService # Faker from faker import Faker # 导入User模型用于创建测试用户 from django.contrib.auth.models import User fake = Faker(['fr']) def test_connect(driver, live_server_url): # 用测试服务器地址替代硬编码的真实地址 driver.get(live_server_url) title = driver.title username = driver.find_element(by=By.NAME, value="login") password = driver.find_element(by=By.NAME, value="password") submit_button = driver.find_element(by=By.CSS_SELECTOR, value="button[type='submit']") username.send_keys("demo") password.send_keys("demo") submit_button.click() driver.implicitly_wait(1) driver.find_element(by=By.XPATH, value="//p[contains(text(),'Aucun dossier ou fichier')]") class VisitCreationTestCase(LiveServerTestCase): # 继承LiveServerTestCase def setUp(self) -> None: # 在测试数据库里创建登录需要的demo用户 User.objects.create_user(username='demo', password='demo') # 启动浏览器 service = ChromeService(executable_path=ChromeDriverManager().install()) self.driver = webdriver.Chrome(service=service) # 传入测试服务器地址 test_connect(self.driver, self.live_server_url) def tearDown(self) -> None: self.driver.quit() def test_login(self): self.driver.find_element(by=By.PARTIAL_LINK_TEXT, value="Créer une visite").click() form = self.driver.find_element(by=By.ID, value="createVisitForm") name = form.find_element(by=By.NAME, value="name") description = form.find_element(by=By.NAME, value="description") company_name = fake.company() name.send_keys(company_name) company_description = fake.text() description.send_keys(company_description) submit = form.find_element(by=By.CSS_SELECTOR, value="input[type='submit']") submit.click() # 现在断言就能匹配测试数据库里的数据了 assert Visit.objects.filter(name=company_name, description=company_description).exists()
为什么这个方案有效?
LiveServerTestCase会自动启动一个临时的Django服务器,这个服务器会连接测试数据库,所有Selenium的操作都会作用在测试数据库上,测试结束后Django会自动销毁测试数据库,完全不会影响你的真实数据。
内容的提问来源于stack exchange,提问作者Pollo9
相关产品推荐
相关产品推荐

