☰
Selenium+Python实现OJ-Club Web自动化测试实践
2026/10/31 3:25:44 网站建设 项目流程

1. OJ-Club Web UI自动化测试项目概述

OJ-Club作为在线判题系统的典型代表,其Web界面的稳定性和功能完整性直接影响用户体验。传统手工测试在面对频繁迭代的Web应用时效率低下,这正是我们引入自动化测试的关键原因。这个项目主要针对OJ-Club的前端功能模块进行自动化验证,包括题目浏览、竞赛参与、提交记录等核心场景。

我在实际项目中采用Selenium+Python技术栈,配合Pytest测试框架搭建了一套可回归的自动化测试体系。相比手工测试,这套方案能将原本需要2小时的完整测试流程压缩到15分钟内完成,且能精准捕捉到页面元素变更、交互逻辑错误等常见问题。特别适合在每日构建后快速验证主干功能,为持续集成提供质量保障。

2. 测试框架设计与技术选型

2.1 主流Web自动化测试工具对比

在技术选型阶段,我们重点评估了三种主流方案:

  • Selenium WebDriver:最成熟的浏览器自动化方案,支持多语言和多浏览器
  • Playwright:微软开源的现代测试工具,自带强大的自动等待机制
  • Cypress:专注于前端测试的框架,但浏览器兼容性有限

最终选择Selenium的主要考虑是:

  1. 社区资源丰富,遇到问题容易找到解决方案
  2. Python绑定成熟,与团队现有技术栈匹配
  3. 支持远程Grid执行,便于后续扩展

提示:新手建议从Selenium开始,其显式等待机制能帮助理解Web自动化测试的核心原理

2.2 测试框架分层设计

采用经典的三层架构:

├── base/ │ ├── webdriver.py # 浏览器驱动封装 │ └── page.py # 页面基类 ├── pages/ │ ├── login_page.py # 登录页面对象 │ └── problem_page.py # 题目页面对象 ├── tests/ │ ├── test_login.py # 登录测试用例 │ └── test_problem.py # 题目测试用例 └── conftest.py # Pytest配置

这种结构的关键优势在于:

  • 页面对象模式(POM)实现业务逻辑与测试脚本分离
  • 公共方法在基类中统一维护,减少代码重复
  • 测试用例保持简洁,只关注业务验证

3. 核心测试场景实现

3.1 用户登录模块测试

登录作为系统入口,需要覆盖多种边界情况:

# tests/test_login.py @pytest.mark.parametrize("username,password,expected", [ ("valid_user", "valid_pass", "Dashboard"), # 正常登录 ("", "valid_pass", "Username required"), # 空用户名 ("valid_user", "", "Password required"), # 空密码 ("wrong_user", "valid_pass", "Invalid credentials") # 错误凭证 ]) def test_login_validation(driver, username, password, expected): login_page = LoginPage(driver) login_page.enter_credentials(username, password) login_page.submit() assert expected in login_page.get_page_title()

实现要点:

  1. 使用parametrize实现数据驱动测试
  2. 页面对象封装所有元素定位和操作
  3. 断言包含在测试方法中,保持用例完整

3.2 题目提交功能测试

题目页面涉及富文本编辑和文件上传等复杂交互:

# pages/problem_page.py class ProblemPage(BasePage): CODE_EDITOR = (By.CSS_SELECTOR, ".monaco-editor") SUBMIT_BTN = (By.ID, "submit-btn") def submit_solution(self, code=None, file_path=None): if code: self._enter_code(code) if file_path: self._upload_file(file_path) self.click(self.SUBMIT_BTN) def _enter_code(self, code): self.driver.execute_script( f"editor.setValue(`{code}`)") def _upload_file(self, path): self.find_element(By.CSS_SELECTOR, "input[type=file]").send_keys(path)

特殊处理包括:

  • 使用JavaScript直接操作Monaco编辑器
  • 文件上传通过send_keys实现
  • 分离代码输入和文件上传两种提交方式

4. 测试执行与报告生成

4.1 并发测试配置

通过Selenium Grid实现多浏览器并行测试:

# conftest.py @pytest.fixture(params=["chrome", "firefox"], scope="session") def driver(request): if request.param == "chrome": options = webdriver.ChromeOptions() elif request.param == "firefox": options = webdriver.FirefoxOptions() driver = webdriver.Remote( command_executor='http://grid-hub:4444/wd/hub', options=options ) yield driver driver.quit()

关键配置项:

  • 使用pytest参数化实现多浏览器测试
  • 通过yield实现测试后资源清理
  • Grid节点需提前部署好对应浏览器驱动

4.2 可视化报告集成

结合Allure生成丰富测试报告:

# 安装依赖 pip install allure-pytest # 执行测试 pytest --alluredir=./report allure serve ./report

报告优势:

  • 展示用例执行时序图
  • 自动捕获失败截图
  • 支持添加测试步骤描述
  • 可集成到Jenkins等CI工具

5. 常见问题与优化策略

5.1 元素定位失效问题

典型报错:NoSuchElementException解决方案:

  1. 优先使用相对稳定的CSS选择器
  2. 添加显式等待:
WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "dynamic-element")) )
  1. 对频繁变动的元素添加备用定位策略

5.2 测试稳定性提升技巧

通过实践总结的黄金法则:

  1. 为每个操作添加合理的等待时间
  2. 使用独立的测试账号避免数据冲突
  3. 定期清理浏览器缓存和Cookies
  4. 关键操作添加重试机制:
@retry(stop_max_attempt_number=3) def submit_with_retry(page): page.submit_solution(code="print('hello')")

5.3 测试数据管理

推荐两种模式:

  • 实时生成:使用Faker库创建测试数据
from faker import Faker fake = Faker() def test_create_contest(): contest_name = f"Test_{fake.word()}" # 使用生成的名称创建竞赛
  • 固定数据集:维护JSON/YAML测试数据文件
# test_data/login.yaml valid_credentials: username: "test_user" password: "Pass1234"

6. 项目进阶方向

6.1 视觉回归测试集成

使用Applitools等工具检测UI变化:

from applitools.selenium import Eyes def test_ui_snapshot(driver): eyes = Eyes() eyes.open(driver, "OJ-Club", "Homepage Test") eyes.check_window("Homepage") eyes.close()

6.2 结合AI的元素定位

利用CV技术辅助元素识别:

# 使用SikuliX实现图像识别 def click_element_by_image(driver, image_path): screen = Screen() match = screen.find(image_path) driver.execute_script( "arguments[0].click()", driver.find_element_at(match.getTarget()) )

6.3 性能监控集成

在测试中收集关键指标:

from selenium.webdriver.remote.command import Command def get_page_metrics(driver): timings = driver.execute(Command.GET_LOG, {"type": "performance"})["value"] return { "load_time": timings["loadEventEnd"] - timings["navigationStart"], "dom_ready": timings["domComplete"] - timings["domLoading"] }

这套自动化测试体系在实际项目中显著提升了OJ-Club的测试效率。特别是在每次迭代前的回归测试中,能够快速验证200+核心用例,使团队能够更专注于新功能的测试。对于刚接触Web自动化的测试人员,建议从简单的用户旅程测试开始,逐步扩展到更复杂的场景验证。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询