本页说明 —— 自动化测试模型
自动化测试框架的架构选型直接决定项目可维护性。本页从 最基础的线性脚本 起步,逐步演进到 模块化 / 数据驱动 / 关键字驱动 四大核心模型,帮助理解不同场景下的取舍。
💡 演进路线:线性脚本 → 模块化(封装复用)→ 数据驱动(逻辑/数据分离)→ 关键字驱动(业务/技术分离)→ 最终通常组合 POM + DDT 使用
⚠️ 实际项目中很少"纯用一种模型",而是混合:如 POM(模块化)+ pytest parametrize(数据驱动)+ Robot Framework(关键字)
01 · 线性脚本
线性脚本模型(最基础)
初学者的第一行 Selenium
典型场景:假设要实现"自动化登录测试"这个需求,从 import webdriver 开始顺着往下写,所有操作从头到尾顺序写在一个文件里,不做任何封装——这就是线性脚本模型。它是接触 Selenium 的第一个模型,也是所有其他模型的地基。
🧪 场景:测试登录页面
测试页面http://demo.site/login
页面元素用户名输入框 · 密码输入框 · 登录按钮
测试数据admin / 123456
断言目标登录后页面包含"首页"
📝 线性脚本写法(逐行对照 6 个步骤)
from selenium import webdriver
from selenium.webdriver.common.by import By
# ── 步骤 1/6:启动浏览器 ──
driver = webdriver.Chrome()
# ── 步骤 2/6:打开测试页面 ──
driver.get("http://demo.site/login")
# ── 步骤 3/6:定位用户名框并输入 ──
driver.find_element(By.ID, "username").send_keys("admin")
# ── 步骤 4/6:定位密码框并输入 ──
driver.find_element(By.ID, "password").send_keys("123456")
# ── 步骤 5/6:点击登录按钮 ──
driver.find_element(By.ID, "loginBtn").click()
# ── 步骤 6/6:断言 + 收尾 ──
assert "首页" in driver.title # 判断登录成功了吗?
driver.quit() # 关掉浏览器
🔄 代码执行流程(6 步顺序执行)
① 启动
→
② 打开页
→
③ 输入用户
→
④ 输入密码
→
⑤ 点击
→
⑥ 断言
⚠️ 扩展需求:现在要覆盖多条登录测试用例……
还需要覆盖 空密码、错误密码、空用户名、超长用户名、SQL 注入 等边界场景。如果沿用线性脚本的写法——
# ❌ 线性脚本的典型灾难:复制粘贴 × 5
driver = webdriver.Chrome()
driver.get("http://demo.site/login")
driver.find_element(By.ID, "username").send_keys("admin")
driver.find_element(By.ID, "password").send_keys("") # 改了密码
driver.find_element(By.ID, "loginBtn").click()
assert "请输入密码" in driver.page_source
driver.quit()
# 再复制一遍……
driver = webdriver.Chrome()
driver.get("http://demo.site/login")
driver.find_element(By.ID, "username").send_keys("") # 改了用户名
driver.find_element(By.ID, "password").send_keys("123456")
driver.find_element(By.ID, "loginBtn").click()
assert "请输入用户名" in driver.page_source
driver.quit()
# 复制第 3 遍、第 4 遍、第 5 遍……😫
5 条测试用例 → 同一段"打开页 + 定位元素"复制了 5 遍。登录元素的 ID 如果从 username 改成 user_name,你得改 5 处。这就是线性脚本的天花板。
优点(适合什么场景)
零学习成本
import → get → find → click,跟手工测试一一对应
缺点(为什么会被淘汰)
数据硬编码
admin / 123456 写死在代码里
→ 下一节怎么解决?把重复的"启动 + 打开页 + 定位登录框"抽成一个
def login(driver, u, p): 函数,测试用例只要调函数就行。这就是
02 · 模块化驱动。
02 · 模块化驱动
模块化驱动测试模型
封装公共流程 → 复用
特点:把重复的操作封装成独立函数(如 login / logout / add_cart),测试用例只需调用函数。
之前:线性脚本
driver.get("http://demo.site/login")
driver.find_element(By.ID,
"username").send_keys("admin")
driver.find_element(By.ID,
"password").send_keys("123456")
driver.find_element(By.ID,
"loginBtn").click()
# 换一个账号?
# 复制粘贴再改一遍参数……
# 5 条用例 = 复制 5 遍
➡
现在:模块化驱动
from common.login import login, logout
login(driver, "admin", "123456")
# 一行搞定 ✓
login(driver, "alice", "abc@123")
# 换账号?改参数就行 ✓
# 5 条用例 = 5 行调用
项目目录结构(模块化驱动)
project/
├── requirements.txt
├── common/
│ ├── __init__.py
│ └── login.py
├── utils/
│ ├── __init__.py
│ └── driver.py
├── tests/
│ └── test_login.py
└── data/
└── login_cases.csv
工具类 utils/driver.py
from selenium import webdriver
def create_driver(browser="chrome"):
# 统一浏览器初始化 —— 所有用例共用
if browser == "chrome":
return webdriver.Chrome()
elif browser == "firefox":
return webdriver.Firefox()
else:
raise ValueError("browser must be 'chrome' or 'firefox'")
公共模块 common/login.py
from selenium.webdriver.common.by import By
def login(driver, username, password):
driver.get("http://demo.site/login")
driver.find_element(By.ID, "username").send_keys(username)
driver.find_element(By.ID, "password").send_keys(password)
driver.find_element(By.ID, "loginBtn").click()
def logout(driver):
driver.find_element(By.LINK_TEXT, "退出").click()
测试用例 tests/test_login.py
from common.login import login, logout
from utils.driver import create_driver
def test_login_success():
driver = create_driver("chrome") # 用工具类创建浏览器
login(driver, "admin", "123456") # 一行调用公共函数
assert "首页" in driver.title
logout(driver)
driver.quit()
if __name__ == "__main__":
test_login_success()
优点(适合什么场景)
重复代码归零
公共流程写一次,N 条用例调用 N 次
多人协作友好
A 写公共模块,B 写测试用例,互不干扰
缺点(局限在哪)
参数还在代码里
admin / 123456 还是硬编码(DDT 来解决)
→ 下一节解决什么?参数还在代码里写死 → 把测试数据抽出去,放到 Excel / CSV / JSON,测试脚本只写一遍。这就是
03 · 数据驱动 DDT。
03 · 数据驱动 DDT
数据驱动测试模型(Data-Driven Testing)
逻辑 ← 数据(Excel / CSV / JSON)
核心思想:测试逻辑只写一次,测试数据从 外部文件 读取。同一套登录脚本,喂 100 组账号密码就能跑 100 个测试用例。
之前:模块化(数据硬编码)
def test_login_success():
driver = create_driver("chrome")
login(driver, "admin", "123456") # 硬编码
login(driver, "admin", "") # 硬编码
login(driver, "", "123456") # 硬编码
login(driver, "admin", "wrong") # 硬编码
# 5 条用例 = 改 5 次参数
➡
现在:数据驱动(逻辑只写一次)
def test_login(row):
driver = create_driver("chrome")
login(driver, row["username"], row["password"])
# 数据放 CSV,加 100 行 = 跑 100 条 ✓
外部数据文件 login_data.csv
| username | password | expected |
| admin | 123456 | 登录成功 |
| admin | (空) | 请输入密码 |
| (空) | 123456 | 请输入用户名 |
| admin | wrong | 密码错误 |
| guest | guest | 登录成功 |
| … 再加 95 行就是 100 条用例 |
Python 测试脚本(纯 Python,无框架依赖)
import csv
from common.login import login, logout
from utils.driver import create_driver
def load_data(path):
with open(path, encoding="utf-8") as f:
return list(csv.DictReader(f))
def test_login_ddt(row):
# 测试逻辑只写一次,row 从 CSV 传入
driver = create_driver("chrome")
login(driver, row["username"], row["password"])
assert row["expected"] in driver.page_source
logout(driver)
driver.quit()
if __name__ == "__main__":
# 纯 Python 循环:CSV 一行 = 跑一次 test_login_ddt
for row in load_data("login_data.csv"):
test_login_ddt(row)
执行流程
login_data.csv
→
读取 5 行数据
→
同一 login() 脚本
→
自动跑 5 条用例
优点(为什么好用)
数据量零成本扩展
加 100 条用例 = CSV 加 100 行
数据可读可维护
CSV / Excel 表格,一眼看清覆盖了啥
缺点(局限在哪)
异常场景难表达
验证码、动态 token、时间依赖不好 CSV 化
→ 下一节解决什么?数据驱动解决了"数据和逻辑分离",但测试用例还是要懂 Python 才能写。能不能让
不懂代码的人也能写测试用例?这就是
04 · 关键字驱动 KDT。
04 · 关键字驱动 KDT
关键字驱动测试模型(Keyword-Driven Testing)
业务人员也能写测试用例
核心思想:把 Selenium 操作封装成 "业务级关键字"(如 打开登录页、输入用户名、点击登录),非技术人员用 Excel 写关键字表格即可定义测试用例。
角色分工
技术人员(一次性)
定义关键字 → Python 实现
打开页面 → driver.get(...)
输入文本 → el.send_keys(...)
点击元素 → el.click()
断言文本 → assert ...
# 写一次,永久复用
➡
业务人员(随时写用例)
用 Excel 填表:
步骤 | 关键字 | 参数1 | 参数2
1 | 打开页面 | /login | —
2 | 输入文本 | username | admin
3 | 输入文本 | password | 123456
4 | 点击元素 | loginBtn | —
# 不懂代码也能写 ✓
关键字定义表(技术人员编写)
| 关键字 | Python 实现 |
打开页面 | driver.get(BASE_URL + path) |
输入文本 | driver.find_element(By.ID, id).send_keys(text) |
点击元素 | driver.find_element(By.ID, id).click() |
断言文本 | assert text in driver.page_source |
测试用例表(业务人员填写)
| 步骤 | 关键字 | 参数1 | 参数2 |
| 1 | 打开页面 | /login | — |
| 2 | 输入文本 | username | admin |
| 3 | 输入文本 | password | 123456 |
| 4 | 点击元素 | loginBtn | — |
| 5 | 断言文本 | 登录成功 | — |
执行流程
Excel 表格
→
读取每行
→
查 KEYWORDS dict
→
执行对应 Python
Python 解释器(关键字 → Selenium 调用)
from selenium.webdriver.common.by import By
# ① 技术人员定义关键字
def kw_open(driver, p1, p2):
driver.get("http://demo.site" + p1)
def kw_input(driver, p1, p2):
driver.find_element(By.ID, p1).send_keys(p2)
def kw_click(driver, p1, p2):
driver.find_element(By.ID, p1).click()
KEYWORDS = {
"打开页面": kw_open,
"输入文本": kw_input,
"点击元素": kw_click,
}
# ② 解释器:读表格 → 按步骤调用
def run_case(driver, rows):
for kw, p1, p2 in rows:
KEYWORDS[kw](driver, p1, p2) # 一行解释执行
优点(为什么好用)
非技术人员可写用例
业务 / 测试人员用 Excel 就能定义测试
技术 / 业务分离
技术封装关键字,业务专注测试设计
缺点(局限在哪)
额外维护成本
每加一个关键字 = 改 Python 代码 + 改 Excel
不适合做主力框架
通常作为冒烟 / 回归测试的补充方案
行业落地:Robot Framework
Robot Framework 是 Python 生态中最成熟的关键字驱动测试框架(2005 年 Nokia 贡献开源)。它把我们前面手写的 KEYWORDS dict + run_case() 解释器**做成了现成产品**,内置 HTML 报告、日志、变量系统、标签筛选、并行执行等企业级能力。
① 快速安装
# Robot Framework 本体 + Selenium 关键字库
pip install robotframework
pip install robotframework-seleniumlibrary
# 运行 .robot 文件(自动生成 report.html / log.html)
robot login_test.robot
② .robot 文件四大 Section
# login_test.robot —— 完整示例
*** Settings *** # ① 引入库 / 资源 / 变量文件
Library SeleniumLibrary
Variables config.yaml
Test Setup 打开浏览器 ${url}
Test Teardown 关闭浏览器
*** Variables *** # ② 全局变量(URL、账号等)
${url} http://demo.site/login
${username} admin
${password} 123456
*** Keywords *** # ③ 自定义关键字(Python 函数等价物)
打开浏览器
[Arguments] ${u}
Open Browser ${u} chrome
Maximize Browser Window
关闭浏览器
Close Browser
登录成功
输入文本 username ${username}
输入文本 password ${password}
点击元素 loginBtn
断言文本 登录成功
*** Test Cases *** # ④ 测试用例(业务人员写的部分)
正常账号登录
登录成功
错误密码登录
打开浏览器 ${url}
输入文本 username admin
输入文本 password wrong
点击元素 loginBtn
断言文本 密码错误
③ 和手写 KDT 解释器的对比
| 能力 | 手写 Python 解释器 | Robot Framework |
| 关键字调用 | KEYWORDS[kw]() | 自动解析 *** Keywords *** |
| 变量系统 | 自己实现 | 内置 ${var} / @{list} |
| 数据驱动 | for 循环 | 内置 [Template] + 测试表 |
| 测试报告 | 自己写 | 自动生成 report.html / log.html |
| Setup / Teardown | 手动调用 | Test Setup / Test Teardown |
| 标签筛选 | 无 | robot --include smoke |
| 并行执行 | 无 | pabot --processes 4 |
| 学习成本 | 低(纯 Python) | 中(需学 RF 语法) |
什么时候用 Robot Framework?
团队有非技术成员
测试 / 业务人员能直接写 .robot 用例
快速搭建自动化
不用写解释器、报告、变量系统,开箱即用
企业级 E2E / 回归
成熟稳定,全球 60%+ KDT 项目在用
复杂逻辑受限
循环 / 条件 / 异常处理需用 Python 关键字绕路
→ 4 大模型讲完了!从线性脚本 → 模块化 → DDT → KDT(Robot Framework),是
"从刚性脚本到弹性框架"的演进路线。实际项目中往往
组合使用:模块化 + DDT + POM 是企业主流方案;如果团队有非技术成员参与,Robot Framework 是现成选择。
点击查看综合对比表 →
综合对比
四大模型 vs POM / BDD
选型参考
| 模型 | 学习门槛 | 维护成本 | 数据分离 | 业务分离 | 推荐场景 |
| 线性脚本 | ★☆☆☆☆ | 高 | ❌ | ❌ | 一次性冒烟 |
| 模块化 | ★★☆☆☆ | 中 | ❌ | ❌ | 小团队起步 |
| 数据驱动 DDT | ★★☆☆☆ | 低 | ✅ | ❌ | 大量组合数据 |
| 关键字驱动 KDT | ★★★☆☆ | 中 | ✅ | ✅ | 非技术人员参与 |
| Robot Framework | ★★★☆☆ | 中 | ✅ | ✅ | KDT 现成框架(.robot 文件) |
| POM 页面对象 | ★★★☆☆ | 低 | 可选 | ❌ | 中大型 Web 项目 |
| BDD 行为驱动 | ★★★★☆ | 中 | 可选 | ✅ | 敏捷团队 / TDD |
企业级推荐组合:POM(模块化封装)+ pytest parametrize(数据驱动)+ yaml / excel(测试数据),三者结合覆盖 90% 自动化测试场景。
学习完成
恭喜完成全部课程,回到首页继续探索
返回首页