3. 测试环境搭建:硬件环境、软件环境与自动化框架选型

做固件升级稳定性测试,环境搭建是地基。地基没打好,后面跑出来的数据全是废的。我见过太多团队,一上来就急着写用例,结果环境里电源不稳、网络丢包、日志不全,折腾两周连一次完整的升级流程都跑不通。

这一章,我把环境拆成三块来讲:硬件、软件、自动化框架。每块都有我踩过的坑,你照着搭,至少能省一半的调试时间。

3.1 硬件环境:设备、电源、网络

硬件环境的核心就三个字:可控。你不能让被测设备在不可控的条件下跑测试,否则出了问题你根本分不清是固件 bug 还是环境干扰。

3.1.1 被测设备

设备选型上,我建议你准备至少三台同型号设备。为什么是三台?

  • 一台跑正常流程:用来做基准对比,确保测试环境本身没问题。
  • 一台跑异常流程:断电、断网、强制重启,这台就是用来折腾的。
  • 一台备用:万一刷成砖了,不用等维修,直接换上去继续跑。

另外,设备上的串口一定要引出来。我习惯用 USB 转 TTL 模块,焊在板子的调试口上。这样即使设备死机、网络不通,我还能通过串口看最后一条日志,知道它死在哪一步。

小技巧: 串口波特率别用默认的 115200。有些设备在升级过程中会动态切换波特率,我遇到过好几次,升级到一半串口突然乱码,后来发现是 bootloader 阶段用了 9600。建议你提前跟开发确认好各阶段的波特率。

3.1.2 电源

电源是很多人忽略的坑。你以为市电很稳?其实不是。工厂车间、实验室里,大功率设备一启动,电压瞬间能掉十几伏。

我的做法是这样的:

  • 用可编程直流电源,比如 ITECH 或 Rigol 的。可以设置电压、电流上限,还能记录电压波动曲线。
  • 模拟电压跌落:设置电源在升级过程中突然从 12V 降到 9V,持续 2 秒再恢复。看看设备会不会重启、升级会不会中断。
  • 模拟掉电:用继电器控制电源通断,在升级的不同阶段(擦写 flash 时、校验时、重启时)随机断电。
注意: 断电测试一定要控制好次数。我见过有人连续断电 500 次,结果 flash 芯片的寿命直接耗尽了。建议每轮测试不超过 100 次,并且每次断电后要检查设备是否能正常启动。

3.1.3 网络

网络环境要模拟真实场景。你不能只在千兆局域网里测,用户家里可能是 2.4G Wi-Fi,信号差、延迟高、偶尔丢包。

我推荐用 网络损伤仪,比如 Spirent 或 iTrinegy 的。如果预算有限,也可以用 Linux 的 tc 命令模拟。

下面是我常用的网络损伤参数:

场景 延迟 丢包率 带宽限制 抖动
理想局域网 < 1ms 0% 1000 Mbps 0ms
普通家庭 Wi-Fi 10-30ms 0.5% 50 Mbps 5ms
弱信号 Wi-Fi 50-150ms 2% 10 Mbps 20ms
移动网络(4G) 30-80ms 1% 20 Mbps 10ms

用 tc 模拟弱信号 Wi-Fi 的示例:

# 添加延迟 100ms,抖动 20ms,丢包 2%
tc qdisc add dev eth0 root netem delay 100ms 20ms loss 2%

# 限制带宽 10Mbps
tc qdisc add dev eth0 root tbf rate 10mbit burst 32kbit latency 400ms

3.2 软件环境:升级服务器、日志工具、抓包工具

软件环境决定了你能不能看清问题。我常说一句话:日志不全,等于没测。

3.2.1 升级服务器

升级服务器要能模拟各种异常响应。你不能只测正常流程,还要测服务器返回 404、500、超时、数据损坏等情况。

我习惯用 Python Flask 或 Node.js Express 搭一个轻量级升级服务器。代码量不大,但控制力很强。

下面是一个简单的 Flask 升级服务器示例,支持模拟各种异常:

from flask import Flask, send_file, abort, request
import time
import random

app = Flask(__name__)

@app.route('/upgrade/firmware.bin', methods=['GET'])
def upgrade():
    # 模拟网络延迟
    delay = request.args.get('delay', '0')
    time.sleep(float(delay))

    # 模拟随机失败
    if random.random() < 0.05:  # 5% 概率返回 500
        abort(500)

    # 模拟数据损坏(返回随机字节)
    if request.args.get('corrupt') == '1':
        return bytes([random.randint(0, 255) for _ in range(1024*1024)])

    # 正常返回固件文件
    return send_file('firmware.bin', mimetype='application/octet-stream')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)
关键点: 升级服务器必须记录所有请求日志,包括时间戳、客户端 IP、请求参数、响应状态码、响应大小。这样你才能回溯每次升级的完整链路。

3.2.2 日志工具

日志工具要解决两个问题:集中收集和实时分析。

我推荐用 ELK Stack(Elasticsearch + Logstash + Kibana)或者轻量级的 Loki + Grafana。如果设备数量不多,用 rsyslog 集中转发也行。

设备端日志格式要统一,我建议用 JSON 格式,方便解析:

{
  "timestamp": "2025-03-15T10:30:00.123Z",
  "device_id": "SN-20250315-001",
  "module": "ota_upgrade",
  "level": "ERROR",
  "message": "Flash write failed at offset 0x1000",
  "extra": {
    "retry_count": 3,
    "current_version": "v2.1.0",
    "target_version": "v2.2.0"
  }
}

日志级别我建议分四级:INFO(正常流程)、WARN(重试、超时)、ERROR(失败)、FATAL(设备死机)。这样在 Kibana 里一搜 level: ERROR 就能快速定位问题。

3.2.3 抓包工具

抓包工具用来分析网络协议层面的问题。我主要用 Wireshark 和 tcpdump。

抓包时要注意:

  • 只抓升级相关的端口,避免数据量太大。比如升级服务器端口是 8080,就只抓 port 8080。
  • 保存完整的 pcap 文件,不要只抓前几秒。有些问题发生在升级快结束时,比如最后的 ACK 丢了。
  • 用 tshark 做自动化分析,比如统计重传率、RTT 变化。

抓包命令示例:

# 只抓升级服务器的流量,保存到文件
tcpdump -i eth0 -w upgrade_test.pcap port 8080

# 用 tshark 统计重传包数量
tshark -r upgrade_test.pcap -Y "tcp.analysis.retransmission" | wc -l

3.3 自动化测试框架选型

手动测升级?一次两次还行,跑 1000 次你肯定崩溃。自动化是必须的。

选框架时,我主要看三点:设备控制能力、日志集成能力、报告生成能力。

3.3.1 主流框架对比

框架 适用场景 设备控制 日志集成 学习成本 我推荐吗?
pytest + paramiko Linux 设备、SSH 连接 强(SSH/串口) 中(需自行集成) 低 ✅ 推荐
Robot Framework 关键字驱动、非技术人员 中(需写库) 强(内置报告) 中 ✅ 推荐
Appium Android/iOS 设备 强(ADB/XCUITest) 中 高 ⚠️ 仅移动端
Jenkins Pipeline CI/CD 集成 弱(需脚本配合) 强(插件丰富) 中 ⚠️ 适合调度
自研框架 特殊协议、私有接口 最强 自定义 高 ⚠️ 最后选择

我个人最常用的是 pytest + paramiko。原因很简单:Python 生态成熟,paramiko 能直接通过 SSH 控制设备,pytest 的 fixture 机制很适合做升级前后的状态管理。

3.3.2 我的推荐组合

如果你现在要从零搭建,我建议这样选:

  • 测试框架:pytest(灵活、插件多)
  • 设备控制:paramiko(SSH)+ pyserial(串口)
  • 日志收集:ELK 或 Loki + Grafana
  • 网络模拟:tc 命令或网络损伤仪
  • 报告生成:pytest-html 或 Allure
  • 持续集成:Jenkins 或 GitLab CI
避坑指南: 我曾经用 Robot Framework 搭过一套升级测试框架,关键字写得飞起,但后来发现维护成本太高。每次固件接口一改,关键字库就要大改。后来换成 pytest,用 Python 直接写测试逻辑,反而更灵活。所以我的建议是:如果团队里都是开发背景,直接用 pytest;如果有测试人员不会写代码,再考虑 Robot Framework。

3.4 整体环境架构图

下面这张图是我搭建升级测试环境的整体架构。你可以照着这个结构来规划自己的环境。

固件升级稳定性测试环境架构 升级服务器 网络损伤模拟 交换机 / 路由器 被测设备 #1 被测设备 #2 被测设备 #3 可编程电源 串口日志服务器 抓包服务器 自动化测试控制机(pytest + paramiko) 说明:实线为网络数据流,虚线为控制/监控/供电链路。自动化控制机通过 SSH 和串口同时管理所有设备。

这张图里,自动化测试控制机是大脑,它通过 SSH 控制设备、通过串口收日志、通过继电器控制电源、通过 tc 命令调整网络。所有测试用例都在控制机上跑,结果统一汇总到 ELK 或 Grafana 展示。