目录

UI 自动化测试中的链式调用设计

UI 自动化测试中的链式调用设计

一、问题

传统的 UI 自动化测试代码往往是这样写的:

def test_login_and_create_report():
    driver.get("/login")
    driver.find_element(By.ID, "username").send_keys("admin")
    driver.find_element(By.ID, "password").send_keys("admin123")
    driver.find_element(By.ID, "login-btn").click()

    driver.get("/reports")
    driver.find_element(By.ID, "new-report").click()
    driver.find_element(By.ID, "report-name").send_keys("测试报表")
    driver.find_element(By.ID, "save-btn").click()

    assert "创建成功" in driver.page_source

问题很明显:测试逻辑被一大堆底层操作淹没了,看不出主线流程。

二、链式调用

结合 POM 模式,让每个操作方法返回页面对象本身或下一个页面对象:

class LoginPage:
    def enter_username(self, username):
        self.driver.find_element(By.ID, "username").send_keys(username)
        return self

    def enter_password(self, password):
        self.driver.find_element(By.ID, "password").send_keys(password)
        return self

    def click_login(self):
        self.driver.find_element(By.ID, "login-btn").click()
        return HomePage(self.driver)  # 返回新页面对象


class HomePage:
    def goto_reports(self):
        self.driver.find_element(By.LINK_TEXT, "报表").click()
        return ReportsPage(self.driver)


class ReportsPage:
    def click_new_report(self):
        self.driver.find_element(By.ID, "new-report").click()
        return ReportFormPage(self.driver)


class ReportFormPage:
    def set_name(self, name):
        self.driver.find_element(By.ID, "report-name").send_keys(name)
        return self

    def save(self):
        self.driver.find_element(By.ID, "save-btn").click()
        return ReportsPage(self.driver)

测试代码变成这样:

def test_login_and_create_report():
    reports_page = (LoginPage(driver)
        .enter_username("admin")
        .enter_password("admin123")
        .click_login()
        .goto_reports()
        .click_new_report()
        .set_name("测试报表")
        .save())

    assert reports_page.has_success_message()

三、优势

  1. 语义清晰:测试代码读起来像业务文档
  2. 减少中间变量:不需要为每个页面对象单独定义变量,代码更简洁。
  3. 维护成本低:页面元素变化时,只需改 Page Object 内部,测试流程代码不用动。