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种定位方式:
- ID定位:
find_element_by_id("elementId") - Name定位:
find_element_by_name("elementName") - Class定位:
find_element_by_class_name("className") - Tag定位:
find_element_by_tag_name("tagName") - Link Text定位:
find_element_by_link_text("linkText") - Partial Link Text定位:
find_element_by_partial_link_text("partialLinkText") - CSS选择器:
find_element_by_css_selector("cssSelector") - 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提供了三种等待方式:
- 强制等待:
time.sleep(5)- 简单但低效,不推荐 - 隐式等待:
driver.implicitly_wait(10)- 设置全局等待时间 - 显式等待:使用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.titlepytest的优势:
- 更简洁的断言语法(不用写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 常见问题解决方案
元素找不到:
- 检查定位表达式是否正确
- 添加适当的等待
- 确认没有iframe嵌套
- 使用JavaScript直接操作元素
跨域问题:
- 使用
driver.switch_to.window切换窗口 - 对于iframe,使用
driver.switch_to.frame
- 使用
证书错误:
options = webdriver.ChromeOptions() options.add_argument('--ignore-certificate-errors') driver = webdriver.Chrome(options=options)弹窗处理:
alert = driver.switch_to.alert alert.accept() # 确认 alert.dismiss() # 取消
5.2 性能优化建议
- 复用浏览器会话:避免每个测试都启动/关闭浏览器
- 使用headless模式:
options = webdriver.ChromeOptions() options.add_argument('--headless') driver = webdriver.Chrome(options=options) - 禁用图片加载:
prefs = {"profile.managed_default_content_settings.images": 2} options.add_experimental_option("prefs", prefs) - 并行执行测试:使用pytest-xdist插件
5.3 最佳实践总结
页面对象模式:将页面封装成类,提高代码复用性
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()数据驱动测试:将测试数据与逻辑分离
@pytest.mark.parametrize("username,password", [ ("user1", "pass1"), ("user2", "pass2") ]) def test_login(browser, username, password): login_page = LoginPage(browser) login_page.login(username, password)日志记录:添加详细的日志帮助调试
import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) logger.info("Starting test...")
6. 进阶主题
6.1 分布式测试Selenium Grid
对于大规模测试,可以使用Selenium Grid实现分布式执行:
- 启动Hub:
java -jar selenium-server-standalone.jar -role hub - 注册Node:
java -jar selenium-server-standalone.jar -role node -hub http://hub-ip:4444/grid/register - 测试代码:
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示例配置:
- 安装Python插件
- 创建自由风格项目
- 添加构建步骤:"Execute shell"
pip install -r requirements.txt pytest --html=report.html - 添加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: - pytest7. 项目结构与代码组织
一个良好的项目结构能大大提高维护效率:
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共享fixturebase_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()这个测试案例涵盖了:
- 页面导航
- 元素定位与交互
- 显式等待
- 断言验证
- 测试生命周期管理
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-tests11. 测试报告与结果分析
11.1 Allure报告
Allure能生成非常专业的测试报告:
- 安装:
pip install allure-pytest- 运行测试:
pytest --alluredir=./allure-results- 生成报告:
allure serve ./allure-results11.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_source13.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=firefox14.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.wait18. 测试数据清理
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 测试用例设计原则
- 原子性:每个测试只验证一个功能点
- 独立性:测试之间不依赖执行顺序
- 可重复性:每次执行结果一致
- 自描述性:测试名称清晰表达意图
好的测试示例:
def test_user_can_login_with_valid_credentials(browser): # 测试代码不好的测试示例:
def test_login(browser): # 过于笼统20. 团队协作实践
20.1 代码审查要点
审查自动化测试代码时关注:
- 定位策略是否健壮
- 是否有足够的等待机制
- 测试数据管理是否合理
- 断言是否充分
- 是否有适当的清理逻辑
20.2 文档规范
良好的测试文档应包含:
- 环境要求
- 安装步骤
- 运行命令
- 测试范围说明
- 已知问题
使用pytest docstring生成文档:
def test_checkout_process(browser): """测试完整的结账流程 步骤: 1. 添加商品到购物车 2. 进入结账页面 3. 填写配送信息 4. 选择支付方式 5. 确认订单 预期结果: - 订单创建成功 - 收到订单确认邮件 """21. 测试覆盖率提升
21.1 关键路径覆盖
优先覆盖:
- 核心业务流程
- 支付流程
- 用户注册/登录
- 关键数据操作
21.2 边界条件测试
特别注意:
- 表单输入边界值
- 分页边界
- 空数据情况
- 超长文本处理
示例:
@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_source22. 测试结果分析与反馈
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 e23. 测试环境治理
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=production26. 测试性能监控
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 # MB27. 测试安全实践
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 smoke29.2 失败重试机制
使用pytest-rerunfailures插件:
pip install pytest-rerunfailures运行:
pytest --reruns 3 --reruns-delay 130. 测试文化建设
30.1 团队知识共享
建立:
- 测试代码评审机制
- 定期技术分享会
- 内部wiki文档
- 测试用例评审流程
30.2 质量指标可视化
监控:
- 自动化测试通过率
- 缺陷发现率
- 测试覆盖率趋势
- 测试执行时间
使用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 None31.2 无代码测试工具集成
与Selenium IDE配合使用:
- 录制基本流程
- 导出为Python脚本
- 在脚本基础上增强