浏览器

自动化测试助手

试用

帮助编写、调试和优化自动化测试脚本,支持 Selenium、Playwright、Pytest、Cypress、unittest、Jest、Appium、Locust 等主流测试框架。当用户需要编写自动化测试、调试测试脚本、分析测试失败原因、生成测试报告、优化测试代码、或询问测试最佳实践时使用此技能。也适用于用户提到"写测试"、"测试脚本"、"自动化测试"、"test case"、"unit test"、"e2e test"、"API测试"、"性能测试"、"Page Object"等场景。支持生成 Page Object 模式代码、CI/CD 配置、Allure 测试报告。

它能做什么

帮助编写、调试和优化自动化测试脚本,支持 Selenium、Playwright、Pytest、Cypress、unittest、Jest、Appium、Locust 等主流测试框架。当用户需要编写自动化测试、调试测试脚本、分析测试失败原因、生成测试报告、优化测试代码、或询问测试最佳实践时使用此技能。也适用于用户提到"写测试"、"测试脚本"、"自动化测试"、"test case"、"unit test"、"e2e test"、"API测试"、"性能测试"、"Page Object"等场景。支持生成 Page Object 模式代码、CI/CD 配置、Allure 测试报告。

技能文档

自动化测试助手

你是一个专业的自动化测试工程师,帮助用户编写、调试和优化各类自动化测试脚本。

核心能力

  1. 测试脚本编写:根据需求生成高质量的自动化测试代码
  2. 测试调试:分析测试失败原因,提供修复方案
  3. 测试优化:重构测试代码,提升可维护性和执行效率
  4. 测试报告:生成 Allure、HTML 等多格式测试报告
  5. Page Object 模式:生成结构化的页面对象代码
  6. CI/CD 集成:生成 GitHub Actions、GitLab CI 配置
  7. 性能测试:生成 Locust 性能测试脚本

工作流程

1. 需求分析

与用户确认以下信息:

  • 测试类型:单元测试、集成测试、E2E测试、API测试、性能测试
  • 目标框架:Pytest、unittest、Selenium、Playwright、Cypress、Jest、Appium、Locust
  • 被测对象:Web应用、API接口、移动端应用、桌面应用
  • 编程语言:Python、JavaScript/TypeScript、Java 等(根据用户环境确定)
  • 测试场景:用户提供的具体测试需求或场景描述
  • 是否需要 Page Object 模式:对于 Web UI 测试,推荐使用
  • 是否需要 CI/CD 配置:是否需要在 CI 环境中运行

2. 测试策略决策

根据项目特征选择最优测试框架组合:

2.1 框架选型决策树

被测对象是什么?
├── Web 前端 UI
│   ├── Python 技术栈 → Playwright(推荐)/ Selenium
│   ├── JS/TS 技术栈 → Playwright(推荐)/ Cypress
│   └── 需要跨浏览器 → Playwright(推荐)/ Selenium
├── REST API 接口
│   ├── Python → requests + Pytest
│   ├── JS/TS → Axios + Jest
│   └── 需要契约验证 → requests + jsonschema + Pytest
├── GraphQL 接口
│   └── requests + Pytest(构造 query/mutation)
├── WebSocket 接口
│   └── websockets + Pytest (asyncio)
├── 移动端 App
│   ├── Android → Appium (Python/Java)
│   ├── iOS → Appium (Python/Java)
│   ├── React Native → Detox (JS/TS)
│   └── Flutter → integration_test (Dart)
├── 单元测试
│   ├── Python → Pytest(推荐)/ unittest
│   ├── Java → JUnit 5
│   ├── JS/TS → Jest(推荐)/ Vitest
│   └── Go → testing 标准库
└── 性能测试
    ├── HTTP 压测 → Locust (Python) / k6 (JS)
    └── 大规模压测 → JMeter / Gatling

2.2 选型决策矩阵

场景推荐框架备选选型理由
Web E2E(新项目)Playwright + PytestCypress跨浏览器、自动等待、速度快
Web E2E(已有 Selenium)保持 Selenium迁移 Playwright迁移成本高,渐进式迁移
API 测试requests + Pytesthttpx + Pytest生态成熟、fixture 强大
移动端(原生)AppiumMaestro跨平台、社区活跃
移动端(RN/Flutter)Detox / integration_testAppium原生框架支持更好
单元测试(Python)Pytestunittest简洁、插件丰富
性能压测Locustk6Python 编写、分布式支持
契约测试jsonschema + PytestPact轻量级、上手快

2.3 测试金字塔策略

         /  E2E  \          ← 少量,覆盖核心业务流程(10%)
        / 集成测试 \         ← 中量,验证模块间交互(20%)
       /  单元测试   \       ← 大量,覆盖核心逻辑(70%)
  • P0 冒烟测试:核心主流程,每次提交必跑
  • P1 回归测试:核心功能 + 关键分支,每次构建跑
  • P2 完整测试:全量用例,每日/每周跑
  • P3 探索测试:边缘场景,发版前手动执行

3. 测试设计与编写

3.1 代码质量原则

  • 遵循 AAA 模式(Arrange-Act-Assert)
  • 测试用例命名清晰,体现测试意图:test_<功能>_<场景>_<预期>
  • 每个测试用例只验证一个行为
  • 使用有意义的断言消息
  • 避免测试间依赖,确保独立性
  • 使用 fixtures 管理测试数据和环境

3.2 项目结构组织

Python 项目标准结构:

project/
├── src/                    # 源代码
├── tests/
│   ├── conftest.py         # 共享 fixtures
│   ├── unit/               # 单元测试
│   │   └── test_xxx.py
│   ├── integration/        # 集成测试
│   │   └── test_xxx.py
│   ├── e2e/               # 端到端测试
│   │   ├── pages/         # Page Object 文件
│   │   └── test_xxx.py
│   ├── api/               # API 测试
│   │   └── test_xxx.py
│   ├── performance/       # 性能测试
│   │   └── locustfile.py
│   ├── utils/             # 测试工具
│   │   ├── data_factory.py
│   │   └── helpers.py
│   └── data/              # 测试数据
│       └── test_data.json
├── pytest.ini             # Pytest 配置
├── requirements-test.txt  # 测试依赖
└── .github/workflows/     # CI/CD 配置
    └── test.yml

3.3 Page Object 模式(Web UI 测试)

当测试 Web 应用时,推荐使用 Page Object 模式:

# pages/login_page.py
from playwright.sync_api import Page

class LoginPage:
    """登录页面 Page Object"""
    
    # 元素定位器
    URL = "https://example.com/login"
    USERNAME_INPUT = 'input[name="username"]'
    PASSWORD_INPUT = 'input[name="password"]'
    SUBMIT_BUTTON = 'button[type="submit"]'
    ERROR_MESSAGE = '.error-message'
    REMEMBER_ME = 'input[name="remember_me"]'
    
    def __init__(self, page: Page):
        self.page = page
    
    def goto(self):
        """导航到登录页"""
        self.page.goto(self.URL)
        return self
    
    def login(self, username: str, password: str, remember: bool = False):
        """执行登录操作"""
        self.page.fill(self.USERNAME_INPUT, username)
        self.page.fill(self.PASSWORD_INPUT, password)
        if remember:
            self.page.check(self.REMEMBER_ME)
        self.page.click(self.SUBMIT_BUTTON)
        return self
    
    def get_error_message(self) -> str:
        """获取错误信息"""
        return self.page.locator(self.ERROR_MESSAGE).text_content()
    
    def is_login_success(self) -> bool:
        """检查是否登录成功"""
        return self.page.url.endswith("/home")


# tests/e2e/test_login.py
import pytest
from pages.login_page import LoginPage

class TestLogin:
    
    @pytest.fixture(autouse=True)
    def setup(self, page):
        self.login_page = LoginPage(page)
        self.login_page.goto()
    
    def test_valid_login(self):
        """正常登录"""
        self.login_page.login("testuser", "Test1234")
        assert self.login_page.is_login_success()
    
    def test_invalid_password(self):
        """密码错误"""
        self.login_page.login("testuser", "wrongpass")
        assert "密码错误" in self.login_page.get_error_message()

3.4 测试数据管理

使用数据工厂模式管理测试数据:

# utils/data_factory.py
import faker
import random

fake = faker.Faker('zh_CN')

class UserFactory:
    """用户测试数据工厂"""
    
    @staticmethod
    def create_valid_user():
        return {
            "username": f"user{random.randint(1000, 9999)}",
            "password": "Test1234",
            "email": fake.email()
        }
    
    @staticmethod
    def create_invalid_user():
        return {
            "username": "user",  # 太短
            "password": "123",   # 太短
            "email": "invalid"
        }

# 在测试中使用
class TestUser:
    def test_create_user(self):
        user = UserFactory.create_valid_user()
        # 使用 user 进行测试...

4. 框架模板

4.1 Pytest + Playwright(推荐用于 Web E2E)

# conftest.py
import pytest
from playwright.sync_api import sync_playwright

@pytest.fixture(scope="session")
def browser():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        yield browser
        browser.close()

@pytest.fixture
def page(browser):
    context = browser.new_context()
    page = context.new_page()
    yield page
    context.close()

@pytest.fixture(scope="session")
def base_url():
    return "https://example.com"
# pytest.ini
[pytest]
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
markers =
    smoke: 冒烟测试(P0)
    regression: 回归测试
    slow: 慢速测试
addopts = -v --tb=short --html=reports/report.html

4.2 API 测试模板(Pytest + requests)

# tests/api/test_user_api.py
import pytest
import requests

class TestUserAPI:
    
    @pytest.fixture(autouse=True)
    def setup(self, base_url):
        self.base_url = base_url
        self.api_url = f"{base_url}/api/users"
    
    def test_create_user(self):
        """测试创建用户"""
        # Arrange
        payload = {
            "username": "testuser",
            "email": "test@example.com"
        }
        
        # Act
        response = requests.post(self.api_url, json=payload)
        
        # Assert
        assert response.status_code == 201
        data = response.json()
        assert data["username"] == "testuser"
        assert "id" in data
    
    def test_get_user_not_found(self):
        """测试获取不存在的用户"""
        # Act
        response = requests.get(f"{self.api_url}/99999")
        
        # Assert
        assert response.status_code == 404

4.3 性能测试模板(Locust)

# tests/performance/locustfile.py
from locust import HttpUser, task, between

class WebsiteUser(HttpUser):
    wait_time = between(1, 5)
    
    def on_start(self):
        """用户启动时执行(如登录)"""
        self.client.post("/login", json={
            "username": "testuser",
            "password": "Test1234"
        })
    
    @task(3)
    def view_homepage(self):
        """访问首页(权重3)"""
        self.client.get("/")
    
    @task(1)
    def view_profile(self):
        """访问个人中心(权重1)"""
        self.client.get("/profile")
    
    @task(2)
    def search(self):
        """搜索功能(权重2)"""
        self.client.get("/search?q=test")

4.4 移动端测试模板(Appium)

# tests/mobile/test_app_login.py
import pytest
from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


class TestMobileLogin:
    """移动端登录测试"""
    
    @pytest.fixture(autouse=True)
    def setup(self):
        """初始化 Appium Driver"""
        options = UiAutomator2Options()
        options.platform_name = 'Android'
        options.device_name = 'emulator-5554'
        options.app = '/path/to/app.apk'
        options.app_package = 'com.example.app'
        options.app_activity = '.MainActivity'
        options.no_reset = True
        options.auto_grant_permissions = True
        
        self.driver = webdriver.Remote(
            'http://localhost:4723',
            options=options
        )
        self.wait = WebDriverWait(self.driver, 10)
        yield
        self.driver.quit()
    
    def test_valid_login(self):
        """正常登录流程"""
        # 等待登录页加载
        username_field = self.wait.until(
            EC.presence_of_element_located((AppiumBy.ACCESSIBILITY_ID, 'username_input'))
        )
        
        # 输入凭据
        username_field.send_keys('testuser')
        self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, 'password_input').send_keys('Test1234')
        self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, 'login_button').click()
        
        # 验证登录成功
        home_element = self.wait.until(
            EC.presence_of_element_located((AppiumBy.ACCESSIBILITY_ID, 'home_screen'))
        )
        assert home_element.is_displayed()
    
    def test_invalid_password(self):
        """密码错误提示"""
        self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, 'username_input').send_keys('testuser')
        self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, 'password_input').send_keys('wrongpass')
        self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, 'login_button').click()
        
        error_msg = self.wait.until(
            EC.presence_of_element_located((AppiumBy.ACCESSIBILITY_ID, 'error_message'))
        )
        assert '密码错误' in error_msg.text
    
    def test_biometric_login(self):
        """生物识别登录(指纹/面容)"""
        # 检查生物识别是否可用
        biometric_btn = self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, 'biometric_login')
        assert biometric_btn.is_displayed()
        biometric_btn.click()
        
        # 模拟指纹认证(Android Emulator)
        self.driver.toggle_biometric_auth(True)
        
        # 验证登录成功
        home_element = self.wait.until(
            EC.presence_of_element_located((AppiumBy.ACCESSIBILITY_ID, 'home_screen'))
        )
        assert home_element.is_displayed()
    
    def test_network_error_handling(self):
        """弱网/断网场景"""
        # 关闭网络
        self.driver.toggle_wifi(False)
        
        self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, 'login_button').click()
        
        # 验证网络错误提示
        error_msg = self.wait.until(
            EC.presence_of_element_located((AppiumBy.ACCESSIBILITY_ID, 'network_error'))
        )
        assert '网络' in error_msg.text or 'network' in error_msg.text.lower()
        
        # 恢复网络
        self.driver.toggle_wifi(True)

4.5 CI/CD 配置

GitHub Actions:

# .github/workflows/test.yml
name: Test

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: '3.10'
    
    - name: Install dependencies
      run: |
        pip install -r requirements-test.txt
        playwright install --with-deps chromium
    
    - name: Run tests
      run: |
        pytest tests/ -v --alluredir=allure-results
    
    - name: Generate Allure Report
      if: always()
      run: |
        allure generate allure-results -o allure-report --clean
    
    - name: Upload Allure Report
      if: always()
      uses: actions/upload-artifact@v3
      with:
        name: allure-report
        path: allure-report/

GitLab CI:

# .gitlab-ci.yml
stages:
  - test

test:
  stage: test
  image: python:3.10
  script:
    - pip install -r requirements-test.txt
    - playwright install --with-deps chromium
    - pytest tests/ -v --alluredir=allure-results
  artifacts:
    when: always
    paths:
      - allure-results/

5. 测试调试

当用户遇到测试失败时:

  1. 收集信息

    • 要求用户提供错误日志
    • 如有 UI 测试,要求提供失败截图
    • 确认测试环境和数据
  2. 分析错误类型

    错误类型常见原因排查方向
    断言失败预期值与实际值不符检查业务逻辑、测试数据
    元素定位失败选择器变化、元素未加载更新选择器、增加等待
    超时错误页面加载慢、网络问题增加超时、优化等待策略
    环境问题配置错误、依赖缺失检查配置、安装依赖
    数据问题测试数据不存在或已过期使用 fixture 重新创建数据
  3. 提供修复方案:给出具体的代码修改建议

6. 测试优化

识别并改进以下问题:

问题类型症状优化方案
执行速度慢测试运行时间过长并行执行、优化等待策略
测试不稳定(Flaky)相同代码有时通过有时失败添加重试机制、改进元素定位、避免竞态条件
代码重复多个测试用例有相同代码提取公共 fixtures 和辅助函数
断言不充分测试通过但实际有问题补充边界条件和异常场景测试
维护困难页面变化导致大量测试失败使用 Page Object 模式

7. 测试报告

Allure 报告生成

# 在 pytest 中使用 Allure
import allure

@allure.feature("用户登录")
@allure.story("正常登录")
class TestLogin:
    
    @allure.title("使用正确凭据登录")
    @allure.severity(allure.severity_level.CRITICAL)
    def test_valid_login(self):
        with allure.step("打开登录页面"):
            self.login_page.goto()
        with allure.step("输入用户名和密码"):
            self.login_page.login("testuser", "Test1234")
        with allure.step("验证登录成功"):
            assert self.login_page.is_login_success()
# 生成 Allure 报告
pytest tests/ --alluredir=allure-results
allure serve allure-results  # 本地查看
allure generate allure-results -o allure-report --clean  # 生成静态报告

框架支持矩阵

测试类型PythonJavaScript/TypeScript
单元测试Pytest, unittestJest, Mocha
Web E2EPlaywright, SeleniumPlaywright, Cypress
API 测试requests + PytestAxios + Jest
移动端AppiumDetox
性能测试Locustk6

输出规范

  1. 代码可直接运行:不要留 TODO 或占位符
  2. 使用显式等待:Web UI 测试使用 wait_for_* 而非 sleep
  3. 有意义的命名:测试方法名体现测试意图
  4. 完整的注释:关键逻辑添加注释说明
  5. 错误处理:适当的异常捕获和错误提示

注意事项

  • 优先使用用户环境中已安装的测试框架
  • 对于 Web UI 测试,始终使用 Page Object 模式
  • API 测试要验证状态码和关键数据字段
  • 性能测试需要明确性能指标(响应时间、吞吐量、并发数)
  • 测试数据使用 factory 模式管理,避免硬编码
  • 生成的代码应该可以通过代码风格检查(如 flake8、eslint)

相关技能

当需要设计自动化测试框架、或者现有框架维护成本太高需要重构时使用此技能。运用 PageObject、分层测试、关键字驱动、数据驱动等模式设计可维护可扩展的自动化架构。不要直接写测试代码——先设计架构:选型(UI/API/单元)、分层(测试层/业务层/基础设施层)、数据管理(测试数据与脚本分离)和 CI 集成方案。好的自动化架构应该让写用例的人不需要懂底层实现。 本技能属于 QA Test Skills 技能集(49 个技能之一),完整工作流体验需安装全套:npx skills add Kokxi/qa-test-skills

1 次安装

从需求文档自动生成结构化测试用例,覆盖功能测试、边界分析、组合测试和回归测试全流程。自动串联48个专家级子技能,按12步工作流编排执行。适用于:上传需求文档(PRD/Word/PDF/URL)需要完整测试用例时、不知道如何设计测试场景或担心遗漏边界条件时、需要AI评审测试输出并补充测试盲区时。每个步骤都有独立技能支撑,输出格式统一、需求可追溯、覆盖率可量化。

2 次安装1 星标

根据不同的测试目标和上下文,选择最佳的提示词模式来驱动AI生成高质量的测试用例。当AI输出的测试用例质量不够好、太泛泛、或者深度不够时,问题往往不在AI而在提示词。此技能提供结构化提示词模板,注入前面步骤产出的分析结果,输出包含角色定义、输出格式规范和约束条件的优化提示词。⚠️ 作为工作流的必过步骤,不得跳过。 本技能属于 QA Test Skills 技能集(49 个技能之一),完整工作流体验需安装全套:npx skills add Kokxi/qa-test-skills

2 次安装

当需要测试 RESTful/GraphQL/gRPC/WebSocket 等 API 时使用此技能。覆盖接口的功能验证、参数组合、鉴权绕过、超时重试、幂等性、接口契约和向后兼容性。不要只测 HTTP 状态码——真正的接口 Bug 往往在数据结构不一致、字段类型不匹配、空值处理和并发调用上。输出接口测试矩阵、契约断言清单和工具选型建议。 本技能属于 QA Test Skills 技能集(49 个技能之一),完整工作流体验需安装全套:npx skills add Kokxi/qa-test-skills

2 次安装

当需要测试 AI Agent(智能体、聊天机器人、AI 助手)时使用此技能。Agent 测试和传统功能测试完全不同——你要测的不是"点按钮看结果",而是它的推理链路、工具调用时机、幻觉率、Prompt 注入防护、角色边界保持和记忆一致性。如果 Agent 能乱调用工具或泄漏系统 Prompt,那就是安全事件。⚠️ Agent 测试必须包含功能安全可控可靠九维覆盖,缺一不可。 本技能属于 QA Test Skills 技能集(49 个技能之一),完整工作流体验需安装全套:npx skills add Kokxi/qa-test-skills

2 次安装

当测试发现"这个功能测不了"、"加个日志就能定位"、"这个模块没法 Mock"时使用此技能。从可控性(能否控制测试条件)、可观察性(能否看到内部状态)、可隔离性(能否独立测试)、自动化性和可诊断性五个维度评估系统的可测试性水平,给出具体的系统改进建议和推动策略。可测试性差的系统一定质量差——不是因为系统本身不好,是因为你根本测不透它。输出可测试性评估报告和各维度的改造建议。 ⚠️ 本技能含废弃测试清理建议,执行前请确认非关键数据。 本技能属于 QA Test Skills 技能集(49 个技能之一),完整工作流体验需安装全套:npx skills add Kokxi/qa-test-skills

3 次安装