Open-AutoGLM自动化测试进阶:复杂流程断言验证教程

1. 引言

想象一下,你正在测试一个手机应用的新功能。你需要模拟用户从打开应用、搜索内容、浏览列表、点击详情、执行操作,再到最后验证结果这一整套流程。手动测试一遍可能需要十几分钟,而且容易出错。如果这个流程需要测试上百遍呢?这简直是测试工程师的噩梦。

今天,我们就来解决这个痛点。我将带你深入探索Open-AutoGLM框架在自动化测试中的高级应用——复杂流程的断言验证。这不是简单的“点击-检查”测试,而是模拟真实用户行为,并智能验证每个关键节点的完整流程测试。

Open-AutoGLM,或者说Phone Agent,本质上是一个能“看懂”手机屏幕并“动手”操作的AI助手。它通过视觉语言模型理解界面元素,通过ADB执行操作指令。在测试领域,这意味着我们可以用自然语言描述测试场景,让AI自动执行并验证结果。

本教程将聚焦于如何利用这个框架,构建可靠的、可重复的复杂流程自动化测试。你将学会:

  • 如何设计多步骤的自动化测试流程
  • 如何在关键节点设置智能断言
  • 如何处理测试中的异常和分支
  • 如何验证动态变化的界面内容

无论你是测试工程师、开发人员,还是对自动化感兴趣的技术爱好者,这篇教程都将为你打开一扇新的大门。让我们开始吧。

2. 环境准备与快速回顾

在深入复杂测试之前,确保你的基础环境已经就绪。如果你已经完成过基础部署,可以快速浏览本节;如果是新手,请按步骤操作。

2.1 基础环境检查

首先确认你的环境符合以下要求:

硬件要求:

  • 测试设备:Android 7.0+ 手机或模拟器(推荐真机,兼容性更好)
  • 控制端电脑:Windows / macOS / Linux均可
  • 网络环境:设备与控制端需要在同一网络,或通过USB连接

软件要求:

  • Python 3.10+(这是框架的推荐版本)
  • ADB工具(Android调试桥)
  • Git(用于克隆代码库)

2.2 快速部署控制端

如果你还没有部署控制端,按以下步骤操作:

# 1. 克隆Open-AutoGLM仓库
git clone https://github.com/zai-org/Open-AutoGLM
cd Open-AutoGLM

# 2. 安装Python依赖
pip install -r requirements.txt
pip install -e .

# 3. 验证安装
python -c "import phone_agent; print('安装成功')"

2.3 设备连接确认

确保你的手机已经正确连接:

# 查看已连接的设备
adb devices

# 预期输出类似:
# List of devices attached
# 1234567890ABCDEF    device

如果设备列表为空,检查:

  1. 手机是否开启USB调试(设置 -> 开发者选项 -> USB调试)
  2. USB线是否连接正常
  3. 是否需要安装手机驱动(Windows系统常见问题)

2.4 服务端连接配置

复杂测试通常需要稳定的AI模型服务。确保你的服务端正常运行:

# 测试服务端连接
import requests

def test_server_connection(base_url):
    try:
        response = requests.get(f"{base_url}/health")
        if response.status_code == 200:
            print("✅ 服务端连接正常")
            return True
        else:
            print(f"❌ 服务端异常,状态码:{response.status_code}")
            return False
    except Exception as e:
        print(f"❌ 连接失败:{e}")
        return False

# 替换为你的服务端地址
BASE_URL = "http://你的服务器IP:端口/v1"
test_server_connection(BASE_URL)

环境准备就绪后,我们就可以开始设计复杂的测试流程了。

3. 复杂测试流程设计思路

传统的自动化测试脚本往往是线性的:执行操作A,检查结果B。但在真实场景中,用户行为要复杂得多。用户可能会:

  • 在多个应用间切换
  • 遇到弹窗提示需要处理
  • 根据界面内容做出不同决策
  • 执行一系列关联操作

Open-AutoGLM的优势在于,它不仅能执行操作,还能理解界面内容,并根据理解做出决策。这让我们可以设计更接近真实用户行为的测试流程。

3.1 测试场景分析

让我们以一个具体的电商应用测试场景为例:

测试目标:验证用户从搜索商品到成功下单的完整流程

主要步骤

  1. 打开电商应用
  2. 在搜索框输入关键词
  3. 从搜索结果列表中选择商品
  4. 进入商品详情页
  5. 选择规格(如颜色、尺寸)
  6. 加入购物车
  7. 进入购物车结算
  8. 填写收货地址
  9. 选择支付方式
  10. 提交订单
  11. 验证订单创建成功

挑战点

  • 每个页面的元素定位可能不同
  • 网络加载可能导致等待时间
  • 商品库存状态可能变化
  • 可能有弹窗干扰(如登录提示、优惠券弹窗)

3.2 测试流程设计原则

基于Open-AutoGLM的特性,我们设计测试流程时应遵循以下原则:

原则一:模块化设计 将大流程拆分为小模块,每个模块负责一个明确的子任务。这样便于调试和维护。

原则二:智能等待与重试 网络应用常有加载时间,AI需要能够识别“加载中”状态,并适当等待。

原则三:异常处理 设计流程时就要考虑可能出现的异常,并制定处理策略。

原则四:验证点明确 在每个关键步骤后设置清晰的验证点,确保流程按预期进行。

3.3 流程状态管理

复杂流程需要状态管理。我们可以定义一个简单的状态机:

class TestState:
    def __init__(self):
        self.current_step = "start"
        self.results = {}
        self.errors = []
        self.screenshots = []
    
    def record_step(self, step_name, success, details=None):
        """记录步骤执行结果"""
        self.results[step_name] = {
            "success": success,
            "timestamp": time.time(),
            "details": details
        }
        if success:
            print(f"✅ 步骤 [{step_name}] 执行成功")
        else:
            print(f"❌ 步骤 [{step_name}] 执行失败")
            self.errors.append(f"{step_name}: {details}")
    
    def take_screenshot(self, agent, step_name):
        """保存当前屏幕截图,用于后续分析"""
        screenshot_path = f"screenshots/{step_name}_{int(time.time())}.png"
        agent.take_screenshot(screenshot_path)
        self.screenshots.append({
            "step": step_name,
            "path": screenshot_path,
            "timestamp": time.time()
        })
    
    def generate_report(self):
        """生成测试报告"""
        total_steps = len(self.results)
        successful_steps = sum(1 for r in self.results.values() if r["success"])
        
        report = {
            "summary": {
                "total_steps": total_steps,
                "successful_steps": successful_steps,
                "success_rate": successful_steps / total_steps if total_steps > 0 else 0,
                "has_errors": len(self.errors) > 0
            },
            "details": self.results,
            "errors": self.errors,
            "screenshots": self.screenshots
        }
        return report

这个状态管理器会跟踪整个测试流程的执行情况,为后续的断言验证提供数据支持。

4. 关键节点的断言验证实现

断言是自动化测试的核心。在Open-AutoGLM中,我们不仅要验证操作是否执行,还要验证界面状态是否符合预期。

4.1 基础断言方法

让我们从最简单的断言开始——验证界面是否包含特定文本:

def assert_screen_contains(agent, expected_text, step_name, state):
    """
    断言当前屏幕包含指定文本
    
    参数:
    - agent: PhoneAgent实例
    - expected_text: 期望出现的文本
    - step_name: 步骤名称,用于记录
    - state: 测试状态管理器
    """
    # 获取当前屏幕的文本内容
    screen_text = agent.get_screen_text()
    
    # 判断是否包含期望文本
    if expected_text in screen_text:
        state.record_step(step_name, True, 
                         f"找到文本: {expected_text}")
        return True
    else:
        # 保存截图用于调试
        state.take_screenshot(agent, f"assert_failed_{step_name}")
        state.record_step(step_name, False,
                         f"未找到文本: {expected_text}")
        return False

4.2 复杂断言:验证动态内容

在实际应用中,我们经常需要验证动态生成的内容。比如验证搜索结果是否正确:

def assert_search_results(agent, search_keyword, min_results=1, step_name="验证搜索结果", state=None):
    """
    验证搜索结果是否符合预期
    
    参数:
    - agent: PhoneAgent实例
    - search_keyword: 搜索关键词
    - min_results: 期望的最小结果数
    - step_name: 步骤名称
    - state: 测试状态管理器
    """
    # 获取屏幕文本
    screen_text = agent.get_screen_text()
    
    # 简单的关键词匹配(实际应用中可能需要更复杂的逻辑)
    results_found = screen_text.count(search_keyword)
    
    # 验证结果数量
    if results_found >= min_results:
        success = True
        details = f"找到 {results_found} 个相关结果"
    else:
        success = False
        details = f"只找到 {results_found} 个结果,期望至少 {min_results} 个"
    
    # 记录结果
    if state:
        state.record_step(step_name, success, details)
        if not success:
            state.take_screenshot(agent, step_name)
    
    return success, details

4.3 视觉断言:验证界面元素

有时我们需要验证特定的界面元素是否存在,而不仅仅是文本:

def assert_ui_element_exists(agent, element_description, max_attempts=3, step_name="验证界面元素", state=None):
    """
    验证指定的UI元素是否存在
    
    参数:
    - agent: PhoneAgent实例
    - element_description: 元素的自然语言描述
    - max_attempts: 最大尝试次数
    - step_name: 步骤名称
    - state: 测试状态管理器
    """
    attempts = 0
    while attempts < max_attempts:
        # 让AI识别指定元素
        response = agent.analyze_screen(
            f"请识别屏幕上是否有这样的元素:{element_description}。"
            "如果存在,请描述它的位置和状态。"
        )
        
        # 解析AI的响应
        if "存在" in response or "有" in response or "找到" in response:
            if state:
                state.record_step(step_name, True, 
                                 f"找到元素: {element_description}")
            return True
        
        attempts += 1
        if attempts < max_attempts:
            print(f"第 {attempts} 次尝试未找到元素,等待1秒后重试...")
            time.sleep(1)
    
    # 所有尝试都失败
    if state:
        state.take_screenshot(agent, step_name)
        state.record_step(step_name, False,
                         f"未找到元素: {element_description}")
    return False

4.4 流程断言:验证操作序列

对于复杂流程,我们需要验证一系列操作的最终结果:

def assert_complete_flow(agent, flow_steps, state):
    """
    验证完整流程的执行结果
    
    参数:
    - agent: PhoneAgent实例
    - flow_steps: 流程步骤列表,每个步骤是(操作, 验证)元组
    - state: 测试状态管理器
    """
    all_success = True
    failure_details = []
    
    for i, (action, verification) in enumerate(flow_steps, 1):
        step_name = f"步骤{i}_{action[:20]}..."  # 截取操作描述前20字符
        
        # 执行操作
        print(f"执行: {action}")
        try:
            agent.execute_action(action)
            time.sleep(2)  # 等待操作完成
        except Exception as e:
            state.record_step(step_name, False, f"执行失败: {str(e)}")
            all_success = False
            failure_details.append(f"步骤{i}执行失败: {str(e)}")
            continue
        
        # 执行验证
        if verification:
            print(f"验证: {verification}")
            verification_func = verification.get("func")
            verification_args = verification.get("args", {})
            
            try:
                success, details = verification_func(agent, **verification_args)
                state.record_step(f"验证{i}", success, details)
                
                if not success:
                    all_success = False
                    failure_details.append(f"步骤{i}验证失败: {details}")
            except Exception as e:
                state.record_step(f"验证{i}", False, f"验证异常: {str(e)}")
                all_success = False
                failure_details.append(f"步骤{i}验证异常: {str(e)}")
    
    return all_success, failure_details

5. 完整测试案例:电商下单流程

现在,让我们把这些技术组合起来,实现一个完整的电商下单流程测试。

5.1 测试用例定义

class EcommerceOrderTest:
    def __init__(self, agent, base_url, device_id):
        self.agent = agent
        self.state = TestState()
        self.test_config = {
            "search_keyword": "智能手机",
            "expected_product": "小米",
            "shipping_address": "北京市海淀区中关村大街1号",
            "payment_method": "微信支付"
        }
    
    def run_full_test(self):
        """执行完整的电商下单测试"""
        print("🚀 开始电商下单流程测试")
        
        # 定义测试步骤
        flow_steps = [
            # (操作描述, 验证配置)
            ("打开淘宝应用", {
                "func": assert_screen_contains,
                "args": {"expected_text": "淘宝", "step_name": "验证淘宝首页"}
            }),
            
            ("点击搜索框", {
                "func": assert_ui_element_exists,
                "args": {"element_description": "搜索输入框", "step_name": "验证搜索框"}
            }),
            
            (f"输入搜索关键词: {self.test_config['search_keyword']}", {
                "func": assert_screen_contains,
                "args": {"expected_text": self.test_config['search_keyword'], 
                        "step_name": "验证搜索关键词"}
            }),
            
            ("点击搜索按钮", {
                "func": assert_search_results,
                "args": {"search_keyword": self.test_config['search_keyword'],
                        "min_results": 3,
                        "step_name": "验证搜索结果"}
            }),
            
            (f"选择包含'{self.test_config['expected_product']}'的商品", {
                "func": assert_screen_contains,
                "args": {"expected_text": self.test_config['expected_product'],
                        "step_name": "验证商品详情"}
            }),
            
            ("点击加入购物车按钮", {
                "func": assert_screen_contains,
                "args": {"expected_text": "加入购物车成功",
                        "step_name": "验证加入购物车"}
            }),
            
            ("进入购物车页面", {
                "func": assert_screen_contains,
                "args": {"expected_text": "购物车",
                        "step_name": "验证购物车页面"}
            }),
            
            ("点击结算按钮", {
                "func": assert_screen_contains,
                "args": {"expected_text": "确认订单",
                        "step_name": "验证订单确认页面"}
            }),
            
            (f"填写收货地址: {self.test_config['shipping_address']}", {
                "func": assert_screen_contains,
                "args": {"expected_text": self.test_config['shipping_address'],
                        "step_name": "验证收货地址"}
            }),
            
            (f"选择支付方式: {self.test_config['payment_method']}", {
                "func": assert_screen_contains,
                "args": {"expected_text": self.test_config['payment_method'],
                        "step_name": "验证支付方式"}
            }),
            
            ("提交订单", {
                "func": assert_screen_contains,
                "args": {"expected_text": "订单提交成功",
                        "step_name": "验证订单提交"}
            })
        ]
        
        # 执行测试流程
        success, failures = assert_complete_flow(self.agent, flow_steps, self.state)
        
        # 生成测试报告
        report = self.state.generate_report()
        
        return success, report, failures

5.2 测试执行与监控

def run_ecommerce_test():
    """执行电商测试并监控进度"""
    
    # 初始化Agent
    from phone_agent.agent import PhoneAgent
    
    agent = PhoneAgent(
        device_id="你的设备ID",
        base_url="http://你的服务器:端口/v1",
        model="autoglm-phone-9b"
    )
    
    # 创建测试实例
    test = EcommerceOrderTest(agent, base_url, device_id)
    
    # 执行测试
    print("📱 开始执行电商下单流程测试...")
    start_time = time.time()
    
    success, report, failures = test.run_full_test()
    
    end_time = time.time()
    duration = end_time - start_time
    
    # 输出测试结果
    print("\n" + "="*50)
    print("测试完成!")
    print(f"总耗时: {duration:.2f}秒")
    print(f"测试结果: {'✅ 通过' if success else '❌ 失败'}")
    print(f"步骤总数: {report['summary']['total_steps']}")
    print(f"成功步骤: {report['summary']['successful_steps']}")
    print(f"成功率: {report['summary']['success_rate']*100:.1f}%")
    
    if failures:
        print("\n失败步骤详情:")
        for failure in failures:
            print(f"  - {failure}")
    
    # 保存详细报告
    import json
    with open("test_report.json", "w", encoding="utf-8") as f:
        json.dump(report, f, ensure_ascii=False, indent=2)
    
    print(f"\n详细报告已保存至: test_report.json")
    print(f"截图保存在: screenshots/ 目录")
    
    return success, report

# 执行测试
if __name__ == "__main__":
    success, report = run_ecommerce_test()

5.3 测试结果分析

测试完成后,我们可以对结果进行深入分析:

def analyze_test_report(report):
    """分析测试报告,找出问题模式"""
    
    print("\n📊 测试结果分析:")
    print("="*40)
    
    # 按步骤分析
    successful_steps = []
    failed_steps = []
    
    for step_name, result in report["details"].items():
        if result["success"]:
            successful_steps.append(step_name)
        else:
            failed_steps.append({
                "step": step_name,
                "details": result["details"],
                "timestamp": result["timestamp"]
            })
    
    # 输出成功步骤
    print(f"✅ 成功步骤 ({len(successful_steps)}个):")
    for step in successful_steps[:5]:  # 只显示前5个
        print(f"  - {step}")
    if len(successful_steps) > 5:
        print(f"  ... 还有{len(successful_steps)-5}个成功步骤")
    
    # 分析失败步骤
    if failed_steps:
        print(f"\n❌ 失败步骤 ({len(failed_steps)}个):")
        
        # 按失败原因分类
        failure_categories = {}
        for failure in failed_steps:
            reason = failure["details"]
            if reason not in failure_categories:
                failure_categories[reason] = []
            failure_categories[reason].append(failure["step"])
        
        # 输出分类结果
        for reason, steps in failure_categories.items():
            print(f"\n  失败原因: {reason}")
            print(f"  涉及步骤: {', '.join(steps)}")
        
        # 提供改进建议
        print("\n💡 改进建议:")
        if "未找到文本" in str(failure_categories):
            print("  - 检查预期文本是否准确,或考虑使用模糊匹配")
        if "未找到元素" in str(failure_categories):
            print("  - 优化元素描述,或增加重试次数")
        if "执行失败" in str(failure_categories):
            print("  - 检查操作指令是否明确,或增加操作后的等待时间")
    
    # 时间分析
    if len(report["details"]) > 1:
        timestamps = [r["timestamp"] for r in report["details"].values()]
        total_time = max(timestamps) - min(timestamps)
        avg_time_per_step = total_time / len(report["details"])
        
        print(f"\n⏱️ 性能分析:")
        print(f"  总测试时间: {total_time:.1f}秒")
        print(f"  平均每步耗时: {avg_time_per_step:.1f}秒")
        print(f"  截图数量: {len(report['screenshots'])}")

6. 高级技巧与最佳实践

掌握了基础测试流程后,让我们看看一些高级技巧,让你的自动化测试更加健壮和高效。

6.1 智能等待策略

网络应用常有加载时间,硬编码的等待时间既低效又不稳定。我们可以实现智能等待:

def smart_wait(agent, condition_func, timeout=30, interval=1, condition_desc=""):
    """
    智能等待,直到条件满足或超时
    
    参数:
    - agent: PhoneAgent实例
    - condition_func: 条件判断函数,返回(bool, 详细信息)
    - timeout: 超时时间(秒)
    - interval: 检查间隔(秒)
    - condition_desc: 条件描述,用于日志
    """
    start_time = time.time()
    attempts = 0
    
    print(f"⏳ 等待条件: {condition_desc}")
    
    while time.time() - start_time < timeout:
        attempts += 1
        
        # 检查条件
        condition_met, details = condition_func(agent)
        
        if condition_met:
            elapsed = time.time() - start_time
            print(f"✅ 条件满足 (尝试{attempts}次, 耗时{elapsed:.1f}秒): {details}")
            return True, details
        
        # 条件未满足,等待后重试
        if time.time() - start_time + interval < timeout:
            time.sleep(interval)
    
    # 超时
    elapsed = time.time() - start_time
    print(f"❌ 等待超时 ({elapsed:.1f}秒): {condition_desc}")
    return False, f"等待{condition_desc}超时"

# 使用示例:等待特定文本出现
def wait_for_text(agent, expected_text, timeout=30):
    """等待屏幕上出现指定文本"""
    
    def check_text(agent):
        screen_text = agent.get_screen_text()
        if expected_text in screen_text:
            return True, f"找到文本: {expected_text}"
        return False, f"未找到文本: {expected_text}"
    
    return smart_wait(agent, check_text, timeout, 
                     condition_desc=f"文本'{expected_text}'出现")

6.2 容错处理与重试机制

自动化测试中,失败是常态。好的测试框架应该有完善的容错机制:

def retry_on_failure(func, max_attempts=3, delay=2, *args, **kwargs):
    """
    失败重试装饰器/函数
    
    参数:
    - func: 要执行的函数
    - max_attempts: 最大尝试次数
    - delay: 重试间隔(秒)
    - *args, **kwargs: 函数参数
    """
    last_exception = None
    
    for attempt in range(1, max_attempts + 1):
        try:
            print(f"尝试第 {attempt}/{max_attempts} 次执行: {func.__name__}")
            result = func(*args, **kwargs)
            if attempt > 1:
                print(f"✅ 第{attempt}次尝试成功")
            return result
        except Exception as e:
            last_exception = e
            print(f"❌ 第{attempt}次尝试失败: {str(e)}")
            
            if attempt < max_attempts:
                print(f"等待{delay}秒后重试...")
                time.sleep(delay)
            else:
                print(f"⚠️ 所有{max_attempts}次尝试均失败")
    
    # 所有尝试都失败,抛出最后一个异常
    raise last_exception

# 使用示例
@retry_on_failure
def reliable_click(agent, element_description):
    """可靠的点击操作,失败会自动重试"""
    return agent.click_element(element_description)

# 或者直接使用
success = retry_on_failure(
    agent.click_element,
    max_attempts=3,
    delay=1,
    element_description="登录按钮"
)

6.3 数据驱动测试

对于需要测试多种场景的情况,我们可以使用数据驱动的方式:

import csv
import json

class DataDrivenTest:
    def __init__(self, agent, test_data_file):
        self.agent = agent
        self.test_cases = self.load_test_cases(test_data_file)
    
    def load_test_cases(self, file_path):
        """从文件加载测试用例"""
        test_cases = []
        
        if file_path.endswith('.csv'):
            with open(file_path, 'r', encoding='utf-8') as f:
                reader = csv.DictReader(f)
                for row in reader:
                    test_cases.append(row)
        
        elif file_path.endswith('.json'):
            with open(file_path, 'r', encoding='utf-8') as f:
                test_cases = json.load(f)
        
        print(f"📋 加载了 {len(test_cases)} 个测试用例")
        return test_cases
    
    def run_test_suite(self):
        """运行测试套件"""
        results = []
        
        for i, test_case in enumerate(self.test_cases, 1):
            print(f"\n{'='*50}")
            print(f"执行测试用例 {i}/{len(self.test_cases)}")
            print(f"用例描述: {test_case.get('description', '无描述')}")
            
            # 执行单个测试用例
            success, details = self.execute_test_case(test_case)
            
            # 记录结果
            result = {
                "case_id": i,
                "description": test_case.get('description'),
                "success": success,
                "details": details,
                "timestamp": time.time()
            }
            results.append(result)
            
            print(f"结果: {'✅ 通过' if success else '❌ 失败'}")
        
        # 生成汇总报告
        self.generate_summary(results)
        return results
    
    def execute_test_case(self, test_case):
        """执行单个测试用例"""
        # 这里根据具体的测试用例结构来执行
        # 示例:假设test_case包含操作步骤和验证条件
        steps = test_case.get('steps', [])
        state = TestState()
        
        for step in steps:
            action = step.get('action')
            verification = step.get('verification')
            
            if action:
                self.agent.execute_action(action)
                time.sleep(1)  # 操作后等待
            
            if verification:
                # 执行验证
                verification_func = getattr(self, verification['func'])
                success = verification_func(**verification.get('args', {}))
                
                if not success:
                    return False, f"验证失败: {verification['func']}"
        
        return True, "所有步骤执行成功"
    
    def generate_summary(self, results):
        """生成测试汇总报告"""
        total = len(results)
        passed = sum(1 for r in results if r['success'])
        failed = total - passed
        
        print(f"\n{'='*50}")
        print("测试套件执行完成!")
        print(f"总计: {total} 个用例")
        print(f"通过: {passed} 个 ({passed/total*100:.1f}%)")
        print(f"失败: {failed} 个 ({failed/total*100:.1f}%)")
        
        if failed > 0:
            print("\n失败用例:")
            for result in results:
                if not result['success']:
                    print(f"  - 用例{result['case_id']}: {result['description']}")
                    print(f"    失败原因: {result['details']}")

6.4 测试报告生成

最后,让我们创建一个美观的测试报告:

def generate_html_report(test_results, output_file="test_report.html"):
    """生成HTML格式的测试报告"""
    
    html_template = """
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>自动化测试报告</title>
        <style>
            body { font-family: Arial, sans-serif; margin: 40px; }
            .header { background: #f5f5f5; padding: 20px; border-radius: 5px; }
            .summary { margin: 20px 0; padding: 15px; border: 1px solid #ddd; }
            .success { color: #28a745; }
            .failure { color: #dc3545; }
            .test-case { margin: 10px 0; padding: 10px; border-left: 4px solid #007bff; }
            .passed { border-left-color: #28a745; background: #f8fff9; }
            .failed { border-left-color: #dc3545; background: #fff8f8; }
            .screenshot { max-width: 300px; margin: 10px; border: 1px solid #ddd; }
            .timestamp { color: #666; font-size: 0.9em; }
        </style>
    </head>
    <body>
        <div class="header">
            <h1>📊 自动化测试报告</h1>
            <p class="timestamp">生成时间: {generation_time}</p>
        </div>
        
        <div class="summary">
            <h2>测试概览</h2>
            <p>总用例数: {total_cases}</p>
            <p class="success">通过: {passed_cases} ({pass_rate}%)</p>
            <p class="failure">失败: {failed_cases} ({fail_rate}%)</p>
            <p>总耗时: {total_duration:.1f}秒</p>
        </div>
        
        <h2>详细结果</h2>
        {test_cases_html}
        
        <h2>截图</h2>
        {screenshots_html}
    </body>
    </html>
    """
    
    # 计算统计数据
    total_cases = len(test_results)
    passed_cases = sum(1 for r in test_results if r['success'])
    failed_cases = total_cases - passed_cases
    pass_rate = (passed_cases / total_cases * 100) if total_cases > 0 else 0
    fail_rate = 100 - pass_rate
    
    # 计算总耗时
    if test_results:
        timestamps = [r.get('timestamp', 0) for r in test_results]
        total_duration = max(timestamps) - min(timestamps)
    else:
        total_duration = 0
    
    # 生成测试用例HTML
    test_cases_html = ""
    for result in test_results:
        status_class = "passed" if result['success'] else "failed"
        status_icon = "✅" if result['success'] else "❌"
        
        test_cases_html += f"""
        <div class="test-case {status_class}">
            <h3>{status_icon} 用例 {result.get('case_id', 'N/A')}: {result.get('description', '无描述')}</h3>
            <p>状态: <strong>{'通过' if result['success'] else '失败'}</strong></p>
            <p>详情: {result.get('details', '无详情')}</p>
            <p class="timestamp">执行时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(result.get('timestamp', 0)))}</p>
        </div>
        """
    
    # 生成截图HTML(如果有)
    screenshots_html = ""
    # 这里可以添加截图显示逻辑
    
    # 填充模板
    html_content = html_template.format(
        generation_time=time.strftime("%Y-%m-%d %H:%M:%S"),
        total_cases=total_cases,
        passed_cases=passed_cases,
        failed_cases=failed_cases,
        pass_rate=f"{pass_rate:.1f}",
        fail_rate=f"{fail_rate:.1f}",
        total_duration=total_duration,
        test_cases_html=test_cases_html,
        screenshots_html=screenshots_html or "<p>无截图</p>"
    )
    
    # 保存HTML文件
    with open(output_file, 'w', encoding='utf-8') as f:
        f.write(html_content)
    
    print(f"📄 HTML报告已生成: {output_file}")
    return output_file

7. 总结

通过本教程,我们深入探索了Open-AutoGLM在复杂流程自动化测试中的应用。从基础的环境搭建,到复杂的断言验证,再到完整的测试案例实现,我们一步步构建了一个强大的自动化测试框架。

7.1 关键要点回顾

让我们回顾一下学到的核心内容:

测试设计方面:

  • 复杂测试流程需要模块化设计,每个模块负责明确的子任务
  • 智能等待策略比硬编码的sleep更可靠
  • 完善的容错机制能让测试更加健壮

断言验证方面:

  • 基础文本断言是验证的基础
  • 视觉断言可以验证界面元素的存在和状态
  • 流程断言确保整个操作序列的正确性

最佳实践方面:

  • 数据驱动测试让测试用例管理更加灵活
  • 详细的测试报告帮助快速定位问题
  • 截图和日志记录是调试的重要依据

7.2 实际应用建议

在实际项目中应用这些技术时,我有几点建议:

从小处开始:不要一开始就设计复杂的完整流程。从一个简单的操作-验证开始,逐步增加复杂度。

重视可维护性:测试代码也是代码,需要良好的结构和注释。定期重构,保持代码清晰。

持续集成:将自动化测试集成到CI/CD流程中,每次代码变更都自动运行测试。

监控与报警:测试失败时及时通知相关人员,快速响应问题。

7.3 下一步学习方向

如果你已经掌握了本教程的内容,可以考虑进一步学习:

性能测试:测试应用的响应时间和资源消耗 兼容性测试:在不同设备和系统版本上运行测试 压力测试:模拟多用户并发操作 安全测试:验证应用的安全性

自动化测试是一个持续改进的过程。随着你对Open-AutoGLM的深入理解,你会发现自己可以测试越来越复杂的场景,发现更多隐藏的问题,最终提升整个产品的质量。

记住,好的自动化测试不是替代人工测试,而是让测试工程师从重复劳动中解放出来,专注于更有价值的探索性测试和用户体验测试。希望本教程能为你的测试工作带来实质性的帮助!


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐