测试模型

自动化测试框架架构设计与常用模型模式

本页说明 —— 自动化测试模型

自动化测试框架的架构选型直接决定项目可维护性。本页从 最基础的线性脚本 起步,逐步演进到 模块化 / 数据驱动 / 关键字驱动 四大核心模型,帮助理解不同场景下的取舍。

💡 演进路线:线性脚本 → 模块化(封装复用)→ 数据驱动(逻辑/数据分离)→ 关键字驱动(业务/技术分离)→ 最终通常组合 POM + DDT 使用

⚠️ 实际项目中很少"纯用一种模型",而是混合:如 POM(模块化)+ pytest parametrize(数据驱动)+ Robot Framework(关键字)

1. 线性脚本 2. 模块化驱动 3. 数据驱动 DDT 4. 关键字驱动 KDT 对比表
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,跟手工测试一一对应
写完即跑
不需要目录结构、不需要框架、不需要配置
一次性冒烟
快速验证"这个页面能不能点通"

缺点(为什么会被淘汰)

重复代码爆炸
同一操作 N 条用例就要写 N 遍
定位器散落
页面改版改 ID,全项目搜着改
数据硬编码
admin / 123456 写死在代码里
无法参数化
想跑 100 组账号就得写 100 份
无结构
几百行堆一起,谁都不敢改
→ 下一节怎么解决?把重复的"启动 + 打开页 + 定位登录框"抽成一个 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 # def login() / logout() ├── utils/ # 工具类(与业务无关) │ ├── __init__.py │ └── driver.py # Chrome / Firefox 启动封装 ├── tests/ # 测试用例 │ └── test_login.py └── data/ # 测试数据(配合 DDT) └── 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 次
职责清晰
公共模块 vs 测试用例,各管各的
多人协作友好
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

usernamepasswordexpected
admin123456登录成功
admin(空)请输入密码
(空)123456请输入用户名
adminwrong密码错误
guestguest登录成功
… 再加 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 化
数据文件会膨胀
上万行 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输入文本usernameadmin
3输入文本password123456
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 就能定义测试
技术 / 业务分离
技术封装关键字,业务专注测试设计
用例可视化
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% 自动化测试场景。

关于我们

Python 自动化测试学习平台是一个面向软件测试工程师、开发人员及在校学生的交互式在线学习平台,专注于 Selenium WebDriver 与 Python unittest 自动化测试技能的教学与实践。

我们以"理论 + 实战 + 可交互演示"为核心特色,将八种常规元素定位和Javascript定位、元素操作、自动化测试工具、单元测试、测试模型等知识体系拆分为模块化课程,每个模块都配有可点击、可输入、可运行的模拟练习页面。

平台致力于降低自动化测试的入门门槛,让学习者从"看懂代码"到"动手实操",逐步掌握企业级自动化测试框架的设计与落地能力。

联系方式

📧邮箱:lq@selenium-auto-test.com

📞电话:0755-12345678

📍地址:深圳

💬微信公众号:Selenium自动化测试

🐙GitHub:github.com/selenium-auto-test

免责声明

1. 本平台所有示例代码、演示页面及教程内容均仅供学习交流使用,不构成任何商业推广或技术服务承诺。

2. 平台中的 Selenium API 描述、Python 语法说明均以官方文档为准,如有版本差异请以对应官方文档为准。

3. 学习者在实际项目中应用平台所学内容时,应结合自身项目环境进行充分测试,本平台不对因直接使用示例代码而产生的任何直接或间接损失承担责任。

4. 本平台所引用的第三方库(Selenium、ChromeDriver、unittest 等)版权归其各自作者及维护者所有。

5. 如涉及版权问题或内容建议,请及时通过联系方式与我们沟通,我们将第一时间处理。