01 别把“自动化工具”当“自动化框架”
95% 的测试新手,都会犯这个错:装个 Selenium,写几个脚本,就说自己“搭建了自动化框架”。
真相是——你在用砖头盖房子,却以为自己是建筑师。
什么是测试自动化框架?
不是工具,不是脚本,不是录制回放。它是一个可复用的、结构化的、有规则的测试解决方案。它定义了:怎么组织测试用例、怎么管理测试数据、怎么处理错误、怎么生成报告。
举个例子:
text
# 这是脚本,不是框架
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://www.example.com")
element = driver.find_element_by_id("username")
element.send_keys("admin")
driver.quit()
这段代码能跑,能测试。但换个项目,全得重写。换个人维护,找不到头绪。这叫“一次性脚本”。
真正的框架长这样:
text
# 这是框架的一部分
class BasePage:
def __init__(self, driver):
self.driver = driver
def find_element(self, locator):
return WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located(locator)
)
def click(self, locator):
self.find_element(locator).click()
def input_text(self, locator, text):
self.find_element(locator).send_keys(text)
class LoginPage(BasePage):
def __init__(self, driver):
super().__init__(driver)
self.username_input = ("id", "username")
self.password_input = ("id", "password")
self.login_button = ("id", "login-btn")
def login(self, username, password):
self.input_text(self.username_input, username)
self.input_text(self.password_input, password)
self.click(self.login_button)
看到区别了吗?框架封装了重复操作,定义了清晰的层级关系。换项目?改配置文件就行。换人?看接口名就知道怎么用。
框架不是代码的堆砌,是规则的固化。
02 框架的 5 根支柱:少一根,就塌
一个成熟的测试自动化框架,必须同时满足 5 个条件。缺一个,就是“伪框架”。
支柱 1:用例组织
不是把脚本扔到文件夹。是定义清晰的层级:测试套件 → 测试类 → 测试用例。每个用例独立、可重复执行。
text
# pytest 框架的标准结构
test_suite/
├── test_login.py
├── test_register.py
└── test_checkout.py
# test_login.py 内容
import pytest
class TestLogin:
def test_valid_login(self):
# 测试有效登录
pass
def test_invalid_password(self):
# 测试无效密码
pass
def test_empty_username(self):
# 测试空用户名
pass
支柱 2:数据驱动
测试数据不硬编码在脚本里。存在外部文件(Excel、CSV、JSON、YAML)。
text
# data/test_login_data.json
[
{"username": "admin", "password": "123456", "expected": "登录成功"},
{"username": "test", "password": "wrong", "expected": "密码错误"},
{"username": "", "password": "123456", "expected": "用户名不能为空"}
]
# 框架自动读取数据,批量执行
@pytest.mark.parametrize("data", load_test_data("test_login_data.json"))
def test_login(data):
assert login(data["username"], data["password"]) == data["expected"]
支柱 3:关键字驱动
把操作抽象成“关键字”。登录是一个关键字,搜索是一个关键字,下单是一个关键字。业务人员也能写测试。
text
# 关键字定义
class Keywords:
def open_browser(self, browser_type):
return webdriver.Chrome() if browser_type == "chrome" else webdriver.Firefox()
def navigate_to(self, driver, url):
driver.get(url)
def input_text(self, driver, locator, text):
driver.find_element(*locator).send_keys(text)
def click_element(self, driver, locator):
driver.find_element(*locator).click()
# 测试用例直接用关键字组合
def test_user_login():
driver = Keywords.open_browser("chrome")
Keywords.navigate_to(driver, "https://example.com/login")
Keywords.input_text(driver, ("id", "username"), "admin")
Keywords.input_text(driver, ("id", "password"), "123456")
Keywords.click_element(driver, ("id", "login-btn"))
支柱 4:断言与报告
不是 print("测试通过")。是自动对比预期结果和实际结果,生成 HTML 报告,标记失败截图。
text
def assert_and_report(driver, actual, expected, screenshot_name):
try:
assert actual == expected, f"期望: {expected}, 实际: {actual}"
TestReport.add_pass(screenshot_name)
except AssertionError as e:
driver.save_screenshot(f"failures/{screenshot_name}.png")
TestReport.add_fail(screenshot_name, str(e))
raise
支柱 5:错误处理与重试
不是脚本报错就崩。是优雅捕获、记录日志、自动重试。
text
from tenacity import retry, stop_after_attempt
@retry(stop=stop_after_attempt(3))
def click_with_retry(driver, locator):
try:
element = WebDriverWait(driver, 5).until(
EC.element_to_be_clickable(locator)
)
element.click()
except Exception as e:
logging.error(f"点击失败: {locator}, 错误: {e}")
raise
没有数据驱动的框架,是手工活;没有错误处理的框架,是定时炸弹。
03 3 天搭框架:从零到能用的实操路线
别被“框架”两个字吓住。用 Python + pytest + Selenium,3 天就能搭出可用框架。
第 1 天:搭骨架
text
project/
├── config/ # 配置文件
│ ├── config.ini
│ └── config.py
├── data/ # 测试数据
│ └── test_data.json
├── pages/ # 页面对象
│ ├── base_page.py
│ ├── login_page.py
│ └── home_page.py
├── tests/ # 测试用例
│ ├── test_login.py
│ └── test_home.py
├── utils/ # 工具类
│ ├── driver.py
│ └── report.py
├── conftest.py # pytest 配置
└── pytest.ini # pytest 设置
第 2 天:加血肉
实现核心功能:
- ►浏览器启动与关闭(conftest.py 的 fixture)
- ►页面对象封装(base_page.py)
- ►测试数据读取(data 模块)
- ►失败截图(report.py)
text
# conftest.py
import pytest
from selenium import webdriver
@pytest.fixture(scope="function")
def driver():
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)
yield driver
driver.quit()
@pytest.fixture(scope="session")
def test_data():
import json
with open("data/test_data.json", "r") as f:
return json.load(f)
第 3 天:上报告与日志
text
# 生成 Allure 报告
# 安装:pip install allure-pytest
# 运行:pytest --alluredir=./allure-results
# 查看:allure serve ./allure-results
# 日志配置
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('test.log'),
logging.StreamHandler()
]
)
3 天后,你拥有的不是一个脚本集合,而是一个可扩展、可维护、可复用的自动化测试框架。新项目?改配置文件和页面对象。新需求?加测试数据和测试用例。新成员?看页面对象接口就知道怎么用。
3 天搭框架,不是神话,是方法论。
04 框架选型:不是越重越好,是越合适越好
市面上有 3 类框架,选错一个,团队效率降 50%。
靠前类:数据驱动框架
适合:业务逻辑稳定,测试数据频繁变化
代表:pytest + ddt
优点:用例复用度高,新增用例只需加数据
缺点:复杂场景难处理
第二类:关键字驱动框架
适合:业务人员参与测试,非技术人员写用例
代表:Robot Framework
优点:自然语言描述,门槛低
缺点:执行效率低,维护成本高
第三类:混合框架
适合:大型项目,多团队协作
代表:pytest + Selenium + Allure + Jenkins
优点:灵活性最高,扩展性优秀
缺点:搭建成本高,需要专业维护
怎么选?
看 3 个指标:
1. 团队技术能力:全是开发?选混合框架。有业务人员?关键字驱动。
2. 项目复杂度:单页面应用?数据驱动足够。微服务架构?混合框架。
3. 维护周期:短期项目?轻量框架。长期迭代?投资混合框架。
选框架不是选工具,是选团队未来 1 年的工作方式。
05 框架的核心:不是技术,是规范
90% 的框架失败,不是技术不行,是规范没立住。
规范 1:命名规范
text
# 好命名
test_login_valid_user.py
test_login_invalid_password.py
# 坏命名
test1.py
abc.py
规范 2:目录规范
text
# 好结构
pages/ # 页面对象
tests/ # 测试用例
data/ # 测试数据
config/ # 配置文件
utils/ # 工具类
reports/ # 测试报告
# 坏结构
all_in_one.py
规范 3:代码规范
text
# 好代码
class LoginPage:
def login(self, username, password):
self.input_username(username)
self.input_password(password)
self.click_login_button()
def input_username(self, username):
self.driver.find_element(By.ID, "username").send_keys(username)
# 坏代码
def login(u, p):
d.find_element(By.ID, "u").send_keys(u)
d.find_element(By.ID, "p").send_keys(p)
d.find_element(By.ID, "b").click()
规范 4:提交规范
- ►每次提交只改一个功能
- ►提交信息写清楚:fix: 修复登录超时处理
- ►不提交测试数据文件
规范 5:评审规范
- ►代码必须评审
- ►评审标准:可读性 > 性能 > 代码量
- ►不通过不合并
规范不是束缚,是让团队跑得更快的轨道。
---
框架是自动化测试的骨架,规范是肌肉,数据是血液,报告是心跳。没有框架的自动化,是散沙;没有规范的框架,是危楼。