自动化测试框架构建指南:从需求分析到分层架构设计

什么是自动化测试框架?

框架并非仅仅是引入一些依赖库、合并几个类。它是一个综合的解决方案,涉及设计模式、模块化、可重用性等方面。

自动化测试框架的目的是提供一套标准和规则、从而使自动化测试的开发和维护更高效、更易于扩展

构建合适的框架至关重要,使用结构良好的框架可以提高团队效率,提高测试准确性,最大限度地提高测试覆盖率,降低成本和维护费用——最终带来更高的投资回报率 (ROI)。


如何从零开始构建自动化测试框架

简单的说,构建自动化测试框架需要将框架视作一个应用或产品一样去对待,构建自动化测试框架分为以下步骤:

  • 需求分析和调研
  • 框架选型和决策
  • 框架设计

Step1 - 需求分析和调研

在需求分析和调研阶段,除了明确测试对象和框架的使用场景,还需要深入了解和评估框架的潜在用户(如开发人员、测试人员以及CI/CD工具)的需求。以下是一些关键问题,可以帮助更全面地定义框架的需求:

  1. 框架的适用性和覆盖范围

    1. 框架是否需要支持跨平台测试(如Web、移动端、桌面端)?
    2. 框架主要覆盖哪些测试用例和测试场景(功能测试、性能测试、回归测试等)?
    3. 哪些用例是业务价值较高、需要优先自动化的?
  2. 技术依赖与交互

    • 测试时是否需要与数据库或外部接口交互?这些交互是否需要模拟环境或使用真实数据?
    • 框架是否需要支持特定的技术栈或与现有工具(如Jenkins、GitLab CI等)集成?
  3. 可扩展性与灵活性

    • 框架未来可能面临哪些变化和扩展需求(如支持新的测试场景、新技术或更高的并发量)?
    • 需要支持的测试用例数量是多少?框架是否需要设计为可扩展以满足未来增长需求?
  4. 使用者分析

    • 框架的主要使用和维护人员是谁?他们的技术背景和能力如何(如开发人员是否擅长编程,测试人员是否熟悉框架工具)?
    • 是否需要提供友好的界面或详细的文档以降低框架的使用门槛?
  5. 测试驱动类型

    在不同项目中,测试框架可能需要支持不同的测试驱动方式,选择合适的驱动方式可以提高测试的可维护性、可读性和可扩展性。以下是几种常见的测试驱动类型,后面将在选型决策部分详细介绍其适用场景和工具选择:

    • 数据驱动测试(DDT - Data-Driven Testing)
    • 行为驱动测试(BDD - Behavior-Driven Development)
    • 关键字驱动测试(KDT - Keyword-Driven Testing)
    • 混合驱动测试(Hybrid-Driven Testing)
    • 无驱动类型 一般不推荐,测试用例规模很小或短期使用可以

Step2 - 选型决策

经过初步需求分析后,我们对测试框架或工具的构思和目标有了较为清晰的方向。接下来,需要围绕框架的功能和技术实现进行具体的决策,包括以下几个方面:

框架功能定义

测试框架需要包括哪些功能 ,比如

  • 测试数据管理:支持多种测试数据的管理与生成方式,如静态数据、动态生成数据,或从数据库提取的数据。
  • Mock 功能:通过模拟外部服务或接口的响应,提升测试效率,减少对真实环境的依赖。
  • 日志记录:在测试失败时,生成详细日志,包含步骤、数据输入和错误堆栈等信息,便于排查问题。
  • 测试环境可配置: 框架应能轻松切换测试环境(开发、测试、生产),通过配置文件实现灵活的环境管理。
  • 报告生成:通过工具(如Allure、ExtentReports)自动生成结构化、直观的测试报告,包括统计分析、趋势图和失败详情。
  • 记录和存储测试结果:这里可以讨论如何使用报告生成工具(如Allure, ExtentReports)生成美观的测试报告,如何存储历史测试结果供以后分析。

框架选型

根据框架的功能、需求、使用人员的技术背景等综合考量选择适合的编程语言、主要开发策略、测试驱动类型和依赖和集成的库或框架。

切记不要对某种技术或框架工具执迷不悟,尽管一些工具或框架可能更现代化、更先进,但如果与项目需求和实际背景不符,其价值将大打折扣。

以下是选型时的关键考量因素:

编程语言 优先选择团队技术背景内熟悉的语言,如Python、Java、JavaScript等。

开发策略 根据项目需求和资源状况决定开发策略:

  • 使用成熟的开源框架:充分利用已有工具(如 Selenium、Cypress、Appium 等)的功能,快速实现核心测试需求。
  • 适度自研或二次开发:在开源框架基础上定制化开发,填补特定场景的功能空白,提高框架的适配性和灵活性。

选择合适的测试驱动类型

测试框架的核心在于如何驱动测试,不同的测试驱动方式适用于不同的业务需求。以下是几种常见的测试驱动类型及其特点:

  • 数据驱动测试(DDT - Data-Driven Testin)

    适用于使用不同的数据集运行相同的测试用例,通常用于API 测试、回归测试、边界测试等。例如,验证一个登录功能时,可以使用不同的用户名/密码组合来执行相同的测试逻辑。

    📌 典型场景:API 测试、表单输入验证、支付流程测试。

  • 行为驱动测试(BDD - Behavior-Driven Development)

    适用于测试、开发、产品经理协同编写测试用例,采用Gherkin 语法(Given-When-Then)来增强可读性。BDD 强调业务逻辑驱动,而非技术实现,使非技术人员也能理解测试用例。

    📌 典型场景:敏捷开发团队、跨职能协作、需求自动化验证。

  • 关键字驱动测试(KDT - Keyword-Driven Testing)

    适用于低代码/无代码测试,测试用例由预定义的**关键字(Keywords)**组成,例如 “Login”, “Click Button” 等,使非技术人员可以编写自动化测试。

    📌 典型场景:企业内部测试团队、测试人员不具备编程能力的场景、UI 自动化测试。

  • 混合驱动测试(Hybrid-Driven Testing)

    结合数据驱动测试(DDT)和关键字驱动测试(KDT),或者结合BDD等方法,实现灵活性和扩展性。例如,在 BDD 框架中嵌入数据驱动,让业务人员能用 Gherkin 语法编写测试场景,同时测试数据可以参数化。

    📌 典型场景:大规模 UI 自动化测试、API 自动化测试、支持多数据集的业务流程测试。

基础测试框架和工具选择

基础测试框架

  • Web 测试:如 Selenium(跨浏览器支持)、Cypress(现代 Web 应用)和 Playwright(高性能多浏览器支持)。
  • 移动测试:如 Appium,用于跨平台的移动应用测试。
  • API 测试:如 RestAssured、Postman 或 Karate,满足接口测试需求。

测试驱动库

  • JUnit/TestNG(Java):单元测试框架,支持断言与数据驱动。
  • Pytest(Python):灵活且强大,支持插件与参数化测试。
  • Mocha/Jest(JavaScript):适合前端,支持异步测试。

报告生成库

  • Allure:生成详细 HTML 报告,兼容多框架。
  • ExtentReports:高级自定义报告,适用于 Java 和 C# 项目。

接着我们举个例子

背景

一家技术团队正在开发一个多平台的电子商务应用,包含Web端和移动端。团队的目标是通过自动化测试框架覆盖核心功能(如用户登录、商品搜索、下单支付等),并与现有的CI/CD流程集成。

团队情况

  1. 开发语言主要是 Python JavaScript
  2. 团队中测试人员对自动化测试的经验不一,其中一部分成员熟悉 Selenium,对Cypress 和 Playwright接触较少
  3. 项目时间紧张,需要快速迭代和测试反馈。

需求分析

  • 浏览器支持:需要覆盖 Chrome 和 Firefox,同时考虑移动端的 WebView 测试。
  • 测试类型:主要是功能测试, 主流程的回归为主
  • 集成需求:需要与 Jenkins 的 CI 流程无缝集成。
  • 扩展性:测试用例未来可能从几十增长到上百或更多,框架需要具备可扩展可复用性, 易于维护。

综合考量与决策

团队在选择测试框架时,充分考虑了工具的优缺点、团队熟悉程度、项目的短期与长期需求,决定采用 混合驱动测试(Hybrid-Driven Testing)行为驱动测试BDD结合**数据驱动DDT,**以提升测试的可维护性和扩展性,并分两个阶段逐步落地测试框架。

第一阶段

  • 快速搭建自动化测试框架,满足核心功能的回归测试需求。利用团队熟悉的Selenium 作为 Web 测试框架,并结合Pytest进行测试驱动执行。
  • 实现数据驱动测试(DDT),使登录、搜索、支付等测试支持不同的数据输入,提高覆盖率。

第二阶段

  • 逐步引入Playwright作为主力测试工具,取代Selenium提升测试执行速度和维护性。
  • 逐步引入BDD(如 Cucumber)来增强业务可读性,并使测试更贴近产品需求。

附上Selenium Playwright优缺点分析

特性SeleniumPlaywright
优点
成熟性与兼容性支持多语言(Python、Java、JavaScript)和多种浏览器(Chrome、Firefox、Safari)。支持多语言(JavaScript、Python、C#)和多浏览器(Chromium、Firefox、WebKit)。
社区与生态拥有广泛的社区支持,丰富的文档、教程和插件。社区和生态尚在发展中,但逐步增加支持和文档。
灵活性能处理复杂场景,如多窗口操作、iframe 切换、文件上传等。内置功能强大,支持截图、PDF 生成、地理位置模拟、网络拦截等功能。
动态内容支持需要显式处理异步操作(手动等待)。原生支持动态内容等待,无需显式处理异步操作。
性能与并行测试性能较慢,分布式并行测试需依赖 Selenium Grid。高性能,原生支持高效的并行测试。
缺点
设置和调试依赖 WebDriver,配置和维护复杂。简化了设置和调试流程,学习曲线尚可。
现代化支持对单页应用(SPA)的支持较弱。对现代 Web 技术支持优秀,适合动态页面。
学习成本团队成员通常熟悉,学习成本低。相对较新,需要时间适应 API 和用法。

Step3 框架具体设计

在构建测试自动化框架时,良好的设计模式和架构规划至关重要。如果一开始没有架构设计,就会导致循环依赖和紧密耦合的代码,会使框架难以理解和维护。

自动化测试框架中常用的架构风格是分层架构设计,每一层有特定的职责。一般自动化框架层将按如下方式分离:

  • 展示层

    展示层是分层架构中的顶级层。在测试自动化中,测试层将成为我们的展示层,它将充当用户接口。

  • 业务层

    将业务逻辑放在业务层,在WebUI的测试自动化中,我们可以在页面类中编写业务逻辑,因此页面对象(POM)可以归入该业务层。或者单独抽象出业务层以进一步解耦。

  • 页面层

    页面层是WebUI自动化测试框架中的关键部分,它主要负责和被测试的页面交互,包括页面元素定位、页面交互等。

  • 持久层

    持久层负责存储数据和文件,但在测试自动化中,我们可以将此层用作辅助层,其中将包含各种组件类,例如 Selenium 辅助类、数据辅助类、API 辅助类、日志记录器等。

结合Step2框架选型中的例子,继续介绍混合驱动测试(Hybrid-Driven Testing)构建四层自动化测试框架

四层架构

层级作用相关技术 / 工具
测试用例层(Test Layer)编写测试用例,调用业务逻辑层,使用Gherkin(BDD)+ PytestPytest / Cucumber / Behave
业务层(Service Layer)封装业务操作(如登录、下单),提供高层 API,处理数据驱动(DDT)Python Service Classes
页面对象层(Page Object Layer)封装 Web UI 交互逻辑,隔离 UI 变化Selenium / Playwright / Cypress
持久层(Persistence Layer)处理 WebDriver 初始化、API 交互、数据库操作、日志Requests / DBUtil / Logging

测试用例层(Test Layer - BDD + Pytest)

作用:

  • 采用 行为驱动测试(BDD),让测试、开发、产品经理协同编写测试。
  • 使用 数据驱动测试(DDT),支持不同数据集的自动化执行。

目录结构示例

tests/
    features/
        login.feature
        checkout.feature
    step_definitions/
        test_login.py
        test_checkout.py
    conftest.py  # Pytest 配置

示例:BDD 测试用例(Gherkin 语法)

Feature: User Login
  Scenario Outline: Login with multiple user credentials
    Given the user is on the login page
    When the user enters "<username>" and "<password>"
    Then the user should be redirected to the dashboard

  Examples:
    | username  | password    |
    | user1     | pass123     |
    | user2     | pass456     |

业务层(Service Layer - 业务逻辑封装)

作用:

  • 业务层提供高层 API,封装用户操作(如 "用户登录"、"下单")。
  • 通过 数据驱动(DDT) 获取测试数据,避免测试用例代码重复。

示例:LoginService.py


from pages.login_page import LoginPage
from utilities.data_provider import DataProvider

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

    def login_with_credentials(self, username, password):
        self.login_page.enter_username(username)
        self.login_page.enter_password(password)
        self.login_page.click_login_button()

    def login_with_test_data(self):
        for user in DataProvider.get_test_data("login"):
            self.login_with_credentials(user["username"], user["password"])

页面对象层(Page Object Layer - POM 设计)

作用:

  • 封装 UI 交互逻辑,确保页面结构变化不会影响测试用例。
  • 使用 POM 设计模式,让 UI 自动化测试可复用、易维护。

示例:LoginPage.py(Selenium)

from selenium.webdriver.common.by import By

class LoginPage:
    def __init__(self, driver):
        self.driver = driver
        self.username_field = (By.ID, "username")
        self.password_field = (By.ID, "password")
        self.login_button = (By.ID, "loginBtn")

    def enter_username(self, username):
        self.driver.find_element(*self.username_field).send_keys(username)

    def enter_password(self, password):
        self.driver.find_element(*self.password_field).send_keys(password)

    def click_login_button(self):
        self.driver.find_element(*self.login_button).click()

持久层或底层(Persistence Layer - 数据库 / API / WebDriver)

作用:

  • 数据驱动管理(DataProvider):从 JSON / Excel / DB 获取或生成测试数据。
  • WebDriver管理(BrowserFactory):提供不同浏览器的实例化逻辑。

示例:数据驱动(DbUtil)

import sqlite3

class DBUtil:
    def __init__(self):
        self.connection = sqlite3.connect("test_data.db")
        self.cursor = self.connection.cursor()

    def get_login_data(self):
        self.cursor.execute("SELECT username, password FROM users")
        return self.cursor.fetchall()

示例:WebDriver 工厂类

from selenium import webdriver

class WebDriverFactory:
    @staticmethod
    def get_driver(browser="chrome", headless=False):
        options = None
        if browser.lower() == "chrome":
            options = webdriver.ChromeOptions()
        elif browser.lower() == "firefox":
            options = webdriver.FirefoxOptions()
        else:
            raise ValueError("Unsupported browser type")

        if headless:
            options.add_argument("--headless")

        if browser.lower() == "chrome":
            return webdriver.Chrome(options=options)
        elif browser.lower() == "firefox":
            return webdriver.Firefox(options=options)

测试用例调用

def test_open_browser():
    driver = WebDriverFactory.get_driver("chrome", headless=True)
    driver.get("<https://example.com>")
    assert "Example" in driver.title
    driver.quit()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值