ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Selenium自动化测试入门与实战指南

Selenium自动化测试入门与实战指南

1. Selenium自动化测试入门指南概述

作为一名在测试领域摸爬滚打多年的老手,我深知自动化测试对于现代软件开发的重要性。Selenium作为最主流的Web自动化测试工具,几乎成为了测试工程师的标配技能。但很多新手在学习过程中常常会遇到各种坑,比如环境配置失败、元素定位不准、脚本运行不稳定等问题。这篇文章将带你从零开始,系统性地掌握Selenium自动化测试的核心要点。

Selenium本质上是一个浏览器自动化工具,它通过WebDriver协议控制浏览器执行各种操作,模拟真实用户行为。相比手动测试,它能显著提高测试效率,特别适合回归测试、跨浏览器测试等重复性工作场景。根据我的经验,一个合格的自动化测试工程师至少需要掌握以下核心技能:环境搭建、元素定位、等待机制、测试框架集成以及异常处理。

2. 环境准备与基础配置

2.1 开发环境搭建

首先需要准备Python环境(推荐3.7+版本),这是目前Selenium最常用的编程语言。安装完成后,通过pip安装selenium包:

pip install selenium

接下来需要下载浏览器驱动。以Chrome为例,需要下载对应版本的chromedriver。这里有个关键点:驱动版本必须与本地安装的浏览器版本完全匹配,否则会报错。可以通过chrome://version/查看浏览器版本号,然后到ChromeDriver官网下载对应版本。

将下载的驱动文件放在系统PATH路径下,或者直接在代码中指定驱动路径。我建议后者,因为更可控:

from selenium import webdriver driver = webdriver.Chrome(executable_path='/path/to/chromedriver')

2.2 基础脚本编写

一个最简单的测试脚本如下:

from selenium import webdriver driver = webdriver.Chrome() driver.get("https://www.example.com") print(driver.title) driver.quit()

这个脚本会打开Chrome浏览器,访问example.com,打印页面标题后退出。注意最后一定要调用quit()方法,否则浏览器进程会残留在后台。

提示:在IDE中开发时,建议使用try-finally确保无论测试是否通过都会关闭浏览器:

try: # 测试代码 finally: driver.quit()

3. 核心技能详解

3.1 元素定位策略

元素定位是自动化测试的基础,Selenium提供了8种定位方式:

  1. ID定位:find_element_by_id("elementId")
  2. Name定位:find_element_by_name("elementName")
  3. Class定位:find_element_by_class_name("className")
  4. Tag定位:find_element_by_tag_name("tagName")
  5. Link Text定位:find_element_by_link_text("linkText")
  6. Partial Link Text定位:find_element_by_partial_link_text("partialLinkText")
  7. CSS选择器:find_element_by_css_selector("cssSelector")
  8. XPath:find_element_by_xpath("xpathExpression")

实际项目中,我推荐优先使用ID和CSS选择器。ID定位最快速可靠,但现代前端框架生成的ID常常是动态的。这时CSS选择器就是更好的选择,它语法简洁,性能也不错。XPath虽然强大,但执行效率较低,且容易受页面结构调整影响。

# 好的实践 search_input = driver.find_element_by_css_selector("#searchForm .search-input") # 不好的实践 search_input = driver.find_element_by_xpath("//*[@id='searchForm']/div[3]/input")

3.2 等待机制详解

页面加载需要时间,元素可能不会立即出现。处理这类异步问题是自动化测试中最常见的挑战之一。Selenium提供了三种等待方式:

  1. 强制等待:time.sleep(5)- 简单但低效,不推荐
  2. 隐式等待:driver.implicitly_wait(10)- 设置全局等待时间
  3. 显式等待:使用WebDriverWait和expected_conditions

显式等待是最佳实践,它针对特定条件进行等待,效率最高:

from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "dynamicElement")) )

常用的expected_conditions包括:

  • presence_of_element_located(元素存在)
  • element_to_be_clickable(元素可点击)
  • visibility_of_element_located(元素可见)
  • title_contains(标题包含)

3.3 常用操作封装

除了基本的点击和输入,Selenium还能执行很多复杂操作:

# 鼠标悬停 from selenium.webdriver.common.action_chains import ActionChains element = driver.find_element_by_id("menu") ActionChains(driver).move_to_element(element).perform() # 文件上传 driver.find_element_by_id("fileInput").send_keys("/path/to/file") # 下拉框选择 from selenium.webdriver.support.ui import Select select = Select(driver.find_element_by_id("dropdown")) select.select_by_visible_text("Option Text") # 执行JavaScript driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 截图保存 driver.save_screenshot("screenshot.png")

4. 测试框架集成

4.1 unittest框架整合

Python自带的unittest框架可以和Selenium完美配合:

import unittest from selenium import webdriver class TestWebsite(unittest.TestCase): @classmethod def setUpClass(cls): cls.driver = webdriver.Chrome() def test_homepage_title(self): self.driver.get("https://www.example.com") self.assertIn("Example", self.driver.title) @classmethod def tearDownClass(cls): cls.driver.quit() if __name__ == "__main__": unittest.main()

setUpClass和tearDownClass会在整个测试类前后执行一次,适合浏览器初始化。如果想每个测试方法都使用全新的浏览器实例,可以使用setUp和tearDown。

4.2 pytest高级用法

pytest是更强大的测试框架,提供了很多实用功能:

import pytest from selenium import webdriver @pytest.fixture(scope="module") def browser(): driver = webdriver.Chrome() yield driver driver.quit() def test_search_functionality(browser): browser.get("https://www.example.com") assert "Example" in browser.title

pytest的优势:

  • 更简洁的断言语法(不用写self.assertXXX)
  • 丰富的插件生态(html报告、并行测试等)
  • 参数化测试支持

4.3 生成测试报告

使用pytest-html插件可以生成漂亮的HTML报告:

pytest --html=report.html

对于unittest,可以使用HTMLTestRunner:

import unittest from HTMLTestRunner import HTMLTestRunner suite = unittest.defaultTestLoader.discover(".", pattern="test_*.py") with open("report.html", "wb") as f: runner = HTMLTestRunner(stream=f, title="Test Report") runner.run(suite)

5. 实战技巧与问题排查

5.1 常见问题解决方案

  1. 元素找不到:

    • 检查定位表达式是否正确
    • 添加适当的等待
    • 确认没有iframe嵌套
    • 使用JavaScript直接操作元素
  2. 跨域问题:

    • 使用driver.switch_to.window切换窗口
    • 对于iframe,使用driver.switch_to.frame
  3. 证书错误:

    options = webdriver.ChromeOptions() options.add_argument('--ignore-certificate-errors') driver = webdriver.Chrome(options=options)
  4. 弹窗处理:

    alert = driver.switch_to.alert alert.accept() # 确认 alert.dismiss() # 取消

5.2 性能优化建议

  1. 复用浏览器会话:避免每个测试都启动/关闭浏览器
  2. 使用headless模式:
    options = webdriver.ChromeOptions() options.add_argument('--headless') driver = webdriver.Chrome(options=options)
  3. 禁用图片加载:
    prefs = {"profile.managed_default_content_settings.images": 2} options.add_experimental_option("prefs", prefs)
  4. 并行执行测试:使用pytest-xdist插件

5.3 最佳实践总结

  1. 页面对象模式:将页面封装成类,提高代码复用性

    class LoginPage: def __init__(self, driver): self.driver = driver self.username = driver.find_element_by_id("username") self.password = driver.find_element_by_id("password") def login(self, username, password): self.username.send_keys(username) self.password.send_keys(password) self.password.submit()
  2. 数据驱动测试:将测试数据与逻辑分离

    @pytest.mark.parametrize("username,password", [ ("user1", "pass1"), ("user2", "pass2") ]) def test_login(browser, username, password): login_page = LoginPage(browser) login_page.login(username, password)
  3. 日志记录:添加详细的日志帮助调试

    import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) logger.info("Starting test...")

6. 进阶主题

6.1 分布式测试Selenium Grid

对于大规模测试,可以使用Selenium Grid实现分布式执行:

  1. 启动Hub:
    java -jar selenium-server-standalone.jar -role hub
  2. 注册Node:
    java -jar selenium-server-standalone.jar -role node -hub http://hub-ip:4444/grid/register
  3. 测试代码:
    from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities driver = webdriver.Remote( command_executor='http://hub-ip:4444/wd/hub', desired_capabilities=DesiredCapabilities.CHROME )

6.2 移动端测试Appium

Appium基于Selenium协议,可以测试移动应用:

from appium import webdriver desired_caps = { 'platformName': 'Android', 'deviceName': 'emulator-5554', 'app': '/path/to/app.apk' } driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

6.3 持续集成集成

将Selenium测试集成到CI/CD流程中:

Jenkins示例配置:

  1. 安装Python插件
  2. 创建自由风格项目
  3. 添加构建步骤:"Execute shell"
    pip install -r requirements.txt pytest --html=report.html
  4. 添加HTML报告发布配置

GitLab CI示例:

test: image: python:3.8 before_script: - apt-get update && apt-get install -y chromium-driver - pip install -r requirements.txt script: - pytest

7. 项目结构与代码组织

一个良好的项目结构能大大提高维护效率:

project/ ├── tests/ │ ├── __init__.py │ ├── test_login.py │ └── test_search.py ├── pages/ │ ├── __init__.py │ ├── base_page.py │ ├── login_page.py │ └── home_page.py ├── utils/ │ ├── __init__.py │ ├── config.py │ └── logger.py ├── conftest.py └── requirements.txt

关键文件说明:

  • conftest.py: pytest共享fixture
  • base_page.py: 所有页面类的基类,封装公共方法
  • config.py: 统一管理配置项
  • requirements.txt: 依赖清单

8. 实际案例演示

以一个电商网站测试为例:

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class TestEcommerce: def setup_method(self): self.driver = webdriver.Chrome() self.wait = WebDriverWait(self.driver, 10) def test_add_to_cart(self): # 打开网站 self.driver.get("https://demo.ecommerce.com") # 搜索商品 search = self.wait.until(EC.presence_of_element_located((By.ID, "search"))) search.send_keys("智能手机") search.submit() # 选择第一个商品 first_item = self.wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".product-item:first-child"))) first_item.click() # 添加到购物车 add_to_cart = self.wait.until(EC.element_to_be_clickable((By.ID, "add-to-cart"))) add_to_cart.click() # 验证购物车数量 cart_count = self.wait.until(EC.text_to_be_present_in_element((By.CLASS_NAME, "cart-count"), "1")) assert cart_count def teardown_method(self): self.driver.quit()

这个测试案例涵盖了:

  1. 页面导航
  2. 元素定位与交互
  3. 显式等待
  4. 断言验证
  5. 测试生命周期管理

9. 测试数据管理

有效的测试数据管理是自动化测试成功的关键:

9.1 外部数据文件

使用JSON文件管理测试数据:

// test_data.json { "valid_login": { "username": "testuser", "password": "Pass123" }, "invalid_login": { "username": "wrong", "password": "wrong" } }

在测试中读取:

import json with open("test_data.json") as f: test_data = json.load(f) def test_login(browser): login_page = LoginPage(browser) login_page.login(test_data["valid_login"]["username"], test_data["valid_login"]["password"])

9.2 数据库集成

对于需要动态生成的数据,可以连接数据库:

import pymysql def get_test_user(): connection = pymysql.connect(host='localhost', user='test', password='test', database='test_db') try: with connection.cursor() as cursor: sql = "SELECT username, password FROM users WHERE role='tester'" cursor.execute(sql) return cursor.fetchone() finally: connection.close()

9.3 数据工厂模式

使用工厂模式动态生成测试数据:

from faker import Faker fake = Faker() def generate_user(): return { "name": fake.name(), "email": fake.email(), "address": fake.address() }

10. 测试环境配置

10.1 多环境支持

通过配置文件支持不同环境:

# config.py import os ENV = os.getenv("TEST_ENV", "dev") configs = { "dev": { "base_url": "http://dev.example.com", "username": "dev_user" }, "staging": { "base_url": "http://staging.example.com", "username": "stage_user" }, "prod": { "base_url": "http://example.com", "username": "prod_user" } } CONFIG = configs[ENV]

使用方式:

from config import CONFIG def test_homepage(browser): browser.get(CONFIG["base_url"])

10.2 Docker集成

使用Docker简化环境搭建:

# Dockerfile FROM python:3.8 RUN apt-get update && apt-get install -y \ chromium \ chromium-driver WORKDIR /app COPY . . RUN pip install -r requirements.txt CMD ["pytest"]

启动命令:

docker build -t selenium-tests . docker run -e TEST_ENV=staging selenium-tests

11. 测试报告与结果分析

11.1 Allure报告

Allure能生成非常专业的测试报告:

  1. 安装:
pip install allure-pytest
  1. 运行测试:
pytest --alluredir=./allure-results
  1. 生成报告:
allure serve ./allure-results

11.2 失败截图与日志

自动保存失败用例的截图和日志:

# conftest.py import logging import pytest from selenium import webdriver @pytest.hookimpl(hookwrapper=True) def pytest_runtest_makereport(item, call): outcome = yield report = outcome.get_result() if report.when == "call" and report.failed: driver = item.funcargs["browser"] driver.save_screenshot(f"screenshots/{item.name}.png") logger = logging.getLogger(item.name) logger.error(f"Test failed: {report.longrepr}")

12. 性能测试结合

12.1 执行时间统计

使用pytest插件测量测试执行时间:

pip install pytest-timeout

标记超时时间:

@pytest.mark.timeout(30) # 30秒超时 def test_slow_operation(browser): # 测试代码

12.2 浏览器性能指标

获取浏览器性能数据:

# 启用性能日志 capabilities = { "goog:loggingPrefs": {"performance": "ALL"} } driver = webdriver.Chrome(desired_capabilities=capabilities) # 获取性能日志 logs = driver.get_log("performance")

13. 安全测试应用

13.1 XSS检测

自动化检测XSS漏洞:

xss_payloads = [ "<script>alert('XSS')</script>", "<img src=x onerror=alert('XSS')>" ] def test_xss_vulnerabilities(browser): search_page = SearchPage(browser) for payload in xss_payloads: search_page.search(payload) assert "alert" not in browser.page_source

13.2 HTTPS验证

检查全站HTTPS:

def test_https_links(browser): browser.get("https://example.com") links = browser.find_elements_by_tag_name("a") for link in links: href = link.get_attribute("href") if href and href.startswith("http:"): pytest.fail(f"Insecure link found: {href}")

14. 跨浏览器测试

14.1 多浏览器支持

使用pytest参数化测试不同浏览器:

# conftest.py import pytest def pytest_addoption(parser): parser.addoption("--browser", action="store", default="chrome") @pytest.fixture def browser(request): browser_name = request.config.getoption("--browser") if browser_name == "chrome": driver = webdriver.Chrome() elif browser_name == "firefox": driver = webdriver.Firefox() elif browser_name == "safari": driver = webdriver.Safari() else: raise ValueError(f"Unsupported browser: {browser_name}") yield driver driver.quit()

运行特定浏览器测试:

pytest --browser=firefox

14.2 浏览器兼容性矩阵

使用pytest.mark.parametrize测试多浏览器组合:

import pytest @pytest.mark.parametrize("browser_name", ["chrome", "firefox"]) def test_cross_browser(browser_name, request): if browser_name == "chrome": driver = webdriver.Chrome() elif browser_name == "firefox": driver = webdriver.Firefox() try: driver.get("https://example.com") assert "Example" in driver.title finally: driver.quit()

15. 无头浏览器测试

15.1 Chrome无头模式

options = webdriver.ChromeOptions() options.add_argument('--headless') options.add_argument('--disable-gpu') driver = webdriver.Chrome(options=options)

15.2 无头浏览器截图

即使是无头模式也可以截图:

driver.get("https://example.com") driver.set_window_size(1920, 1080) # 设置窗口大小 driver.save_screenshot("fullpage.png")

16. 移动端响应式测试

测试响应式布局:

mobile_emulation = { "deviceMetrics": {"width": 375, "height": 812, "pixelRatio": 3.0}, "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1" } options = webdriver.ChromeOptions() options.add_experimental_option("mobileEmulation", mobile_emulation) driver = webdriver.Chrome(options=options)

17. 测试代码优化技巧

17.1 使用装饰器减少重复代码

def screenshot_on_failure(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: driver = args[0].driver driver.save_screenshot(f"error_{func.__name__}.png") raise e return wrapper class TestCases: @screenshot_on_failure def test_example(self): # 测试代码

17.2 使用基类封装公共方法

class BaseTest: @classmethod def setup_class(cls): cls.driver = webdriver.Chrome() cls.wait = WebDriverWait(cls.driver, 10) @classmethod def teardown_class(cls): cls.driver.quit() def take_screenshot(self, name): self.driver.save_screenshot(f"{name}.png") class TestLogin(BaseTest): def test_valid_login(self): # 可以直接使用self.driver和self.wait

18. 测试数据清理

18.1 自动化清理测试数据

import requests def cleanup_test_user(username): response = requests.delete( f"https://api.example.com/users/{username}", headers={"Authorization": "Bearer testtoken"} ) assert response.status_code == 204 @pytest.fixture def test_user(): user = create_test_user() yield user cleanup_test_user(user["username"])

18.2 数据库回滚

使用事务回滚保持测试隔离:

import psycopg2 @pytest.fixture def db_connection(): conn = psycopg2.connect("dbname=test user=test") conn.autocommit = False yield conn conn.rollback() conn.close()

19. 测试策略设计

19.1 测试金字塔实践

合理的自动化测试比例:

  • 单元测试:70%
  • 集成测试:20%
  • UI测试:10%

19.2 测试用例设计原则

  1. 原子性:每个测试只验证一个功能点
  2. 独立性:测试之间不依赖执行顺序
  3. 可重复性:每次执行结果一致
  4. 自描述性:测试名称清晰表达意图

好的测试示例:

def test_user_can_login_with_valid_credentials(browser): # 测试代码

不好的测试示例:

def test_login(browser): # 过于笼统

20. 团队协作实践

20.1 代码审查要点

审查自动化测试代码时关注:

  1. 定位策略是否健壮
  2. 是否有足够的等待机制
  3. 测试数据管理是否合理
  4. 断言是否充分
  5. 是否有适当的清理逻辑

20.2 文档规范

良好的测试文档应包含:

  1. 环境要求
  2. 安装步骤
  3. 运行命令
  4. 测试范围说明
  5. 已知问题

使用pytest docstring生成文档:

def test_checkout_process(browser): """测试完整的结账流程 步骤: 1. 添加商品到购物车 2. 进入结账页面 3. 填写配送信息 4. 选择支付方式 5. 确认订单 预期结果: - 订单创建成功 - 收到订单确认邮件 """

21. 测试覆盖率提升

21.1 关键路径覆盖

优先覆盖:

  1. 核心业务流程
  2. 支付流程
  3. 用户注册/登录
  4. 关键数据操作

21.2 边界条件测试

特别注意:

  1. 表单输入边界值
  2. 分页边界
  3. 空数据情况
  4. 超长文本处理

示例:

@pytest.mark.parametrize("quantity", [0, 1, 99, 100]) def test_add_to_cart_quantity(browser, quantity): product_page = ProductPage(browser) product_page.add_to_cart(quantity) if quantity == 0: assert "Quantity must be at least 1" in browser.page_source else: assert f"{quantity} items in cart" in browser.page_source

22. 测试结果分析与反馈

22.1 缺陷分类统计

使用pytest分类标记:

@pytest.mark.bug def test_broken_feature(browser): # 已知问题的测试 pytest.xfail("Known issue: JIRA-1234")

运行指定分类:

pytest -m "not bug"

22.2 与问题跟踪系统集成

自动创建JIRA问题:

import jira def test_failed_feature(browser): try: # 测试代码 except AssertionError as e: jira_client = jira.JIRA("https://jira.example.com", basic_auth=("user", "pass")) issue_dict = { 'project': {'key': 'PROJ'}, 'summary': f'Test failed: {e}', 'description': 'Automatically created by test failure', 'issuetype': {'name': 'Bug'} } jira_client.create_issue(fields=issue_dict) raise e

23. 测试环境治理

23.1 环境健康检查

在测试前验证环境可用性:

@pytest.fixture(scope="session", autouse=True) def check_test_environment(): response = requests.get("https://api.example.com/health") assert response.status_code == 200 assert response.json()["status"] == "UP"

23.2 测试数据隔离

使用随机数据避免冲突:

import uuid @pytest.fixture def unique_email(): return f"test_{uuid.uuid4().hex[:8]}@example.com"

24. 测试代码重构

24.1 页面对象模式进阶

使用基类减少重复代码:

class BasePage: def __init__(self, driver): self.driver = driver self.wait = WebDriverWait(driver, 10) def find(self, locator): return self.wait.until(EC.presence_of_element_located(locator)) def click(self, locator): self.wait.until(EC.element_to_be_clickable(locator)).click() class LoginPage(BasePage): USERNAME = (By.ID, "username") PASSWORD = (By.ID, "password") SUBMIT = (By.ID, "submit") def login(self, username, password): self.find(self.USERNAME).send_keys(username) self.find(self.PASSWORD).send_keys(password) self.click(self.SUBMIT)

24.2 组件模式

对于重复出现的UI组件:

class DropdownComponent: def __init__(self, driver, container_locator): self.driver = driver self.container = driver.find_element(*container_locator) def select_option(self, text): self.container.find_element(By.XPATH, f".//option[.='{text}']").click() class AddressForm: def __init__(self, driver): self.country = DropdownComponent(driver, (By.NAME, "country")) self.state = DropdownComponent(driver, (By.NAME, "state"))

25. 测试框架扩展

25.1 自定义pytest插件

创建conftest.py添加自定义功能:

def pytest_configure(config): config.addinivalue_line( "markers", "flaky: mark test as flaky" ) @pytest.hookimpl(hookwrapper=True) def pytest_runtest_makereport(item, call): outcome = yield report = outcome.get_result() if report.failed and "flaky" in item.keywords: report.outcome = "skipped" report.wasxfail = "known flaky test"

使用方式:

@pytest.mark.flaky def test_unstable_feature(browser): # 测试代码

25.2 命令行参数扩展

添加自定义命令行选项:

# conftest.py def pytest_addoption(parser): parser.addoption("--env", action="store", default="staging", help="Environment to test against") @pytest.fixture def base_url(request): env = request.config.getoption("--env") return f"https://{env}.example.com"

运行:

pytest --env=production

26. 测试性能监控

26.1 网络请求分析

使用Chrome DevTools Protocol:

from selenium.webdriver.common.desired_capabilities import DesiredCapabilities caps = DesiredCapabilities.CHROME caps['goog:loggingPrefs'] = {'performance': 'ALL'} driver = webdriver.Chrome(desired_capabilities=caps) driver.get("https://example.com") for entry in driver.get_log('performance'): print(entry['message'])

26.2 资源使用监控

获取浏览器进程资源使用:

import psutil def get_browser_memory_usage(driver): pid = driver.service.process.pid process = psutil.Process(pid) return process.memory_info().rss / 1024 / 1024 # MB

27. 测试安全实践

27.1 凭证管理

使用环境变量管理敏感信息:

export TEST_USERNAME="admin" export TEST_PASSWORD="secret"

在测试中读取:

import os username = os.getenv("TEST_USERNAME") password = os.getenv("TEST_PASSWORD")

27.2 测试数据脱敏

from faker import Faker fake = Faker() def generate_test_user(): return { "name": fake.name(), "email": fake.email(), "phone": fake.phone_number() }

28. 测试报告定制

28.1 自定义HTML报告

使用pytest-html的钩子定制报告:

# conftest.py def pytest_html_report_title(report): report.title = "自动化测试报告" def pytest_html_results_summary(prefix, summary, postfix): prefix.extend([html.p("环境: 测试环境")])

28.2 添加截图到报告

@pytest.hookimpl(hookwrapper=True) def pytest_runtest_makereport(item, call): outcome = yield report = outcome.get_result() if report.when == "call" and report.failed: screenshot = driver.get_screenshot_as_base64() html = f'<div><img src="data:image/png;base64,{screenshot}"></div>' report.extra = [pytest_html.extras.html(html)]

29. 测试执行优化

29.1 测试分组执行

使用pytest标记分组:

@pytest.mark.smoke def test_login(browser): # 冒烟测试 @pytest.mark.regression def test_checkout(browser): # 回归测试

运行指定组:

pytest -m smoke

29.2 失败重试机制

使用pytest-rerunfailures插件:

pip install pytest-rerunfailures

运行:

pytest --reruns 3 --reruns-delay 1

30. 测试文化建设

30.1 团队知识共享

建立:

  1. 测试代码评审机制
  2. 定期技术分享会
  3. 内部wiki文档
  4. 测试用例评审流程

30.2 质量指标可视化

监控:

  1. 自动化测试通过率
  2. 缺陷发现率
  3. 测试覆盖率趋势
  4. 测试执行时间

使用Grafana展示:

import requests def report_metrics(passed, failed, duration): requests.post("http://grafana.example.com/api/metrics", json={ "passed": passed, "failed": failed, "duration": duration })

31. 测试新技术探索

31.1 AI在测试中的应用

使用计算机视觉辅助定位:

from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import cv2 import numpy as np def find_element_by_image(driver, image_path): driver.save_screenshot("current.png") # 使用OpenCV模板匹配 img_rgb = cv2.imread("current.png") template = cv2.imread(image_path) res = cv2.matchTemplate(img_rgb, template, cv2.TM_CCOEFF_NORMED) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) if max_val > 0.8: # 匹配阈值 x, y = max_loc w, h = template.shape[1], template.shape[0] # 将坐标转换为元素 elements = driver.find_elements(By.XPATH, "//*") for element in elements: location = element.location size = element.size if (x >= location['x'] and x <= location['x'] + size['width'] and y >= location['y'] and y <= location['y'] + size['height']): return element return None

31.2 无代码测试工具集成

与Selenium IDE配合使用:

  1. 录制基本流程
  2. 导出为Python脚本
  3. 在脚本基础上增强

32. 测试资产治理

32.1 测试用例版本控制

返回列表