测试自动化分层设计思路:让脚本更稳定、更易维护

自动测试的人大多都遇到过这种情况:改了一个登录流程,结果几十个用例全挂了;或者换个浏览器,整个脚本跑不起来。问题往往不是出在代码写得差,而是结构没搭好。就像盖房子,地基和框架没理清楚,装修再漂亮也扛不住风雨。

为什么需要分层?

想象你家的厨房。如果所有东西——锅碗瓢盆、调料、食材——全堆在一个抽屉里,每次做饭都得翻半天。测试自动化也一样。把所有逻辑塞进一个脚本里,短期能跑通,长期维护成本极高。

分层的核心思想是“各司其职”。把不同职责的代码拆开,比如操作页面的归一类,写断言的归一类,准备数据的另放一边。这样改登录逻辑时,只动对应的一层,不影响其他用例。

常见的三层结构

最实用的分法是三层:基础操作层、业务封装层、用例层。

基础操作层负责和工具打交道。比如点击、输入、等待这些动作,统一封装成方法。以后换 Selenium 到 Playwright,只需要改这一层,上层几乎不用动。

def click_element(driver, locator):
element = driver.find_element(*locator)
element.click()

def input_text(driver, locator, text):
element = driver.find_element(*locator)
element.clear()
element.send_keys(text)

业务封装层对应具体功能。比如“用户登录”这件事,不管在哪个用例里出现,都调这个方法。参数可以是用户名密码,内部处理跳转、填表、提交。

class LoginPage:
def __init__(self, driver):
self.driver = driver

def login(self, username, password):
input_text(self.driver, ("id", "username"), username)
input_text(self.driver, ("id", "password"), password)
click_element(self.driver, ("id", "login-btn"))

用例层就干净多了。只关心“我要测什么”,不关心“怎么点”“怎么输”。读起来像自然语言,新来的同事也能看懂。

def test_user_login_success():
driver = webdriver.Chrome()
login_page = LoginPage(driver)
login_page.login("testuser", "123456")
assert "dashboard" in driver.current_url
driver.quit()

数据与配置分离

别把测试数据写死在代码里。用户名密码、URL、超时时间这些,统统放到配置文件或环境变量中。本地调试用一套地址,上线前切换到预发环境,改配置就行,不用碰代码。

比如建个 config.yaml:

base_url: https://staging.example.com
timeout: 10
users:
admin: "admin/abcd1234"
guest: "guest/987654"

这样换环境时,连 Jenkins 的构建参数改一下就能跑,不用重新打包代码。

实际场景中的好处

有个团队之前每个用例都自己写登录逻辑,后来项目加了验证码,光改登录就花了三天。后来改成分层,只改了 LoginPage 里的 login 方法,加了个图像识别跳过的逻辑,其他用例一行不动,当天就恢复了运行。

还有个例子,前端把“提交订单”按钮的 class 名从 btn-submit 改成 submit-btn,没分层的脚本全崩了。而用了元素定位集中管理的项目,只改了一个 locators.py 文件就解决了。

分层不是为了炫技,是为了让自动化真正可持续。脚本写一次,能用三个月和能用三年,背后的结构差别就在这儿。