ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

方案测试的 Python 只有一种正当用法:替你发 AT、收日志、填表格

方案测试的 Python 只有一种正当用法:替你发 AT、收日志、填表格

副标题:板端仍是 C;电脑侧 50 到 80 行脚本跑回归,不是做网站
专栏:《嵌入式学生的方案测试课》第 14 篇(胶水)
前置:第 4 篇会手发 AT;第 12 篇理解要统计数字;第 13 篇厌倦手抄拷机表
标签:嵌入式、Python、串口、软件测试、自动化
读者:会一点 Python 语法,没写过带超时的串口脚本;JD 写了简易 PC 工具
学完交什么:脚本 + csv + README(COM 口和波特率)+ 10 次错密码统计
主实验:ESP8266。没有板可以用串口环回或只跑解析函数的单元测试,但要写明。


0. 这篇结束你能干什么

  1. 写 50 到 80 行脚本:打开串口,发AT,判断OK/ERROR,有超时。
  2. 错密码连接 10 次,输出次数、每次耗时、ERROR 原文到 csv。
  3. 能说明:产品固件仍是 C;Python 在电脑上当手。不要和板子日志抢同一串口。
  4. 脚本判定条件写进缺陷单:「有回显」不等于成功,要看ret/OK/FAIL。

嵌入式校招 JD 公开要求简易 PC 调试工具(控制台/对话框)。方案测试用脚本跑回归,不是做 Web。


1. 为什么手发 AT 不够,却也不能一上来上框架

手发:学习协议、写第一份会话。回归 10 次错密码、100 次重连、2 小时一行,手会作弊、会漏。

学生容易跳到 pytest 插件宇宙,或写一个带登录页的平台。岗位要的是:

  • 发得对(新行、超时、编码)
  • 收得全(不要读一行当成功)
  • 判得严(关键字)
  • 落得盘(csv,方便贴报告)

泰芯公开 WiFiTestTool 通过串口下 AT 做 SRRC 发包;AH 有 netat/netlog 网口工具。学生脚本是同类胶水的迷你版。不逆向官方工具,只学「串口下命令 + 用返回值判定」。

公开 SRRC 警告:改 gain 要先暂停发包;AT 返回失败才是失败。脚本如果把「串口有回显」当成校准成功,会制造假通过。


2. 最小原理

2.1 串口是字节流,不是函数调用

pyserial读到的是流。AT 以\r\n分行(第 4 篇新行模式)。你要:

  • 写:命令 +\r\n
  • 读:直到OK/ERROR/FAIL或超时
  • 超时:宁可判失败,不要死等

编码:先latin-1或按字节,避免日志里的中文/乱码把decode('utf-8')摔死。保存原文。

2.2 不要抢串口

同一 COM 口不能:你脚本开着,串口助手也开着。拷机日志如果要人工看,脚本把日志 tee 到文件,人看文件。

2.3 判定写清楚

现象判定
收到独立一行 OKAT 成功(对 AT 探活)
收到 ERROR / FAIL / +CWJAP:x按用例:错密码可能是期望失败
超时失败,记录已收部分
有乱七八糟回显但无 OK失败
板子复位横幅单独事件,不是 OK

错密码 10 次的「成功」定义是:每次都在超时前给出明确失败,且之后 AT 仍探活。不是「连上了」。


3. 参考脚本(约 70 行,读懂再改 COM)

把下面存成labs/week14/at_wrongpass.py。COM 口改成你的。

# at_wrongpass.py 教学脚本:错密码 10 次统计importcsvimporttimeimportargparseimportserialdefread_until(ser,tokens,timeout):"""读到 tokens 之一或超时。返回 (text, hit, elapsed)."""ser.timeout=0.2buf=b""t0=time.time()tokens_b=[t.encode("latin-1")fortintokens]whiletime.time()-t0<timeout:chunk=ser.read(256)ifchunk:buf+=chunkfori,tbinenumerate(tokens_b):iftbinbuf:text=buf.decode("latin-1",errors="replace")returntext,tokens[i],time.time()-t0# 无数据也继续等到 timeouttext=buf.decode("latin-1",errors="replace")returntext,None,time.time()-t0defat_cmd(ser,cmd,tokens=("OK","ERROR","FAIL"),timeout=5.0):ser.reset_input_buffer()ser.write((cmd+"\r\n").encode("latin-1"))returnread_until(ser,tokens,timeout)defmain():ap=argparse.ArgumentParser()ap.add_argument("--port",default="COM3")ap.add_argument("--baud",type=int,default=115200)ap.add_argument("--ssid",default="lab-ap-01")ap.add_argument("--badpass",default="wrong-password-xx")ap.add_argument("--n",type=int,default=10)ap.add_argument("--out",default="wrongpass.csv")args=ap.parse_args()ser=serial.Serial(args.port,args.baud,timeout=0.2)time.sleep(0.2)text,hit,dt=at_cmd(ser,"AT")ifhit!="OK":raiseSystemExit("AT probe failed: %r %r"%(hit,text))rows=[]foriinrange(1,args.n+1):cmd='AT+CWJAP="%s","%s"'%(args.ssid,args.badpass)text,hit,dt=at_cmd(ser,cmd,tokens=("FAIL","ERROR","OK","WIFI GOT IP"),timeout=15.0,)# 错密码期望 FAIL/ERROR,若 OK/GOT IP 则判异常成功expected_fail=hitin("FAIL","ERROR")probe_text,probe_hit,_=at_cmd(ser,"AT",timeout=3.0)rows.append({"i":i,"hit":hitor"TIMEOUT","seconds":"%.3f"%dt,"still_ok":probe_hit=="OK","expected_fail":expected_fail,"excerpt":text.replace("\r","\\r").replace("\n","\\n")[:200],})print(i,rows[-1]["hit"],rows[-1]["seconds"],"alive"ifrows[-1]["still_ok"]else"dead")withopen(args.out,"w",newline="",encoding="utf-8")asf:w=csv.DictWriter(f,fieldnames=list(rows[0].keys()))w.writeheader()w.writerows(rows)n_fail=sum(1forrinrowsifr["expected_fail"])n_alive=sum(1forrinrowsifr["still_ok"])print("expected_fail %d/%d, alive_after %d/%d, csv=%s"%(n_fail,args.n,n_alive,args.n,args.out))ser.close()if__name__=="__main__":main()

依赖:pip install pyserial。README 写 Python 版本、COM、波特率、新行已经由脚本发\r\n。

可选作业:从AT+CWLAP文本里用正则抠 RSSI 数字,追加一列。抠不到就留空,不要编。

可选:用subprocess调iperf3 -c ...把最后一行 Mbps 解析进另一张 csv。解析失败当失败,不要用「进程返回 0」当吞吐合格。


4. 实验步骤

  1. 手发 AT 探活仍 OK(第 4 篇)。先关串口助手。
  2. 改--port。跑--n 1看能否完整结束。
  3. --n 10生成 csv。
  4. 人工抽看第 1、第 10 次 excerpt 是否真是错密码失败。
  5. 若 10 次里出现WIFI GOT IP:密码其实对了或 AP 开放,环境错,不是脚本胜利。
  6. 把 csv 贴进测试记录。缺陷只在:超时、死后不探活、偶发连上。

没有板:把read_until用假字节喂单元测试(io.BytesIO不够串口,可用自己写 FakeSer)。交测试代码同样及格,注明无硬件。


5. 缺陷单:脚本判定条件

标题:【工具】自动化把「串口有回显」当成 AT 成功,SRRC 发包实际 ret=-1 说明(教学):公开 SRRC/AT 文档以返回码为准。脚本必须匹配 OK/ERROR/ret=。 期望:ret=-1 记失败,不写校准通过 实际:脚本见任意字节就点绿灯 分层:测试工具,不是芯片

你自己的脚本若超时当成功,同样提单打自己。


6. 泰芯对照

公开工具学生迷你版
WiFiTestTool 串口 AT 发包pyserial 发 AT
netat 网口 AT本篇不实现;知道网桥可以不插 UART
netlog 拉日志脚本 tee 到文件
对话框/控制台小工具(嵌入式 JD)本篇控制台即可,对话框是加分不是主业

不反编译、不破解授权、不把官方 exe 当自己作品写进简历。


7. 30 秒口径

Python 在电脑上发 AT、收日志、写 csv,固件仍是 C。
脚本必须有超时,用 OK/ERROR/FAIL 判定,不把有回显当成功。
错密码 10 次我用来统计失败是否可观察、之后是否还活着。
不和串口助手抢同一 COM。


8. 作业

labs/week14/ README.md at_wrongpass.py wrongpass.csv requirements.txt # pyserial

README 至少:COM、波特率、如何停、不要抢口、期望失败的定义。

Git 提交可以,但不要提交真实 SSID 密码。--ssid用实验名。


9. 自测题

  1. 为什么 decode utf-8 可能把日志读炸?
  2. 错密码用例里收到 OK 该高兴吗?
  3. 脚本和串口助手同时打开会怎样?
  4. 死等没有 timeout 的危害?
  5. 简历写精通 Django 对这个岗有帮助吗?
  6. iperf 返回码 0 能否当吞吐达标?
  7. 官方 WiFiTestTool 能否写进「我开发的工具」?
  8. 10 次统计的分母为什么重要?

10. 学生常见翻车

  1. 简历精通 Python Web。
  2. 脚本无 timeout。
  3. 抢串口。
  4. 把期望失败当成脚本 bug 反复改密码。
  5. csv 不提交只交「感觉 10 次都挂了」。
  6. 真密码进 Git。

11. 下一篇预告

第 15 篇:《先查供电、天线和传感器 CRC:方案测试怎么跟硬件同事对话》。

脚本再绿,天线没接也是红。下一篇松天线、拔传感器、波特率设错、劣质线供电,把锅从协议栈拿开。


附录 A. 自测题参考答案

  1. 非 UTF-8 字节抛异常,后面的 OK 再也读不到。
  2. 不高兴。错密码连上是安全/逻辑缺陷。
  3. 端口占用或各读走一半字节,判定随机。
  4. 拷机脚本卡死,假阳性过夜。
  5. 几乎没有。要串口和表格。
  6. 不能。要解析 Mbps 和丢失,对照需求。
  7. 不能。可写「使用过公开工具,理解串口 AT 发包」。
  8. 3/3 和 3/100 决策完全不同。

附录 B. 公开资料

  • 嵌入式软件工程师 JD:PC 端控制台/对话框小工具
  • Wi-Fi4 SRRC:WiFiTestTool 串口 AT;返回值
  • AH:netat / netlog
  • 第 4 篇新行与超时

(第 14 篇完)


12. README 最低限度(作业按此抄)

# at_wrongpass Python 3.x pip install pyserial 用法: python at_wrongpass.py --port COM5 --baud 115200 --ssid lab-ap-01 --badpass xx --n 10 前置:关闭串口助手;模组已 AT OK;实验 AP 存在 期望:10 次均为 FAIL/ERROR,之后仍 AT OK 不要:真实家庭密码;把 TIMEOUT 当通过 输出:wrongpass.csv

13. 常见脚本病和对应缺陷

病现象修
没\r\n永远 timeout第 4 篇新行
timeout 太短正确连网被判失败CWJAP 用 15s,探活用 3s
读一行就当结束漏掉 FAIL 在后面读到 token 或超时
utf-8 decode异常退出latin-1
不 reset 输入缓冲上次尾巴污染本次reset_input_buffer
和助手抢口随机关助手
把 OK 当错密码成功逻辑反了expected_fail

第 14 篇脚本里WIFI GOT IP出现在错密码实验 = 立刻停,检查 SSID/密码是否其实对了,或 AP 开放。


14. 把 iperf 解析进 csv 的边界

subprocess.run(["iperf3","-c",ip,"-t","5"], capture_output=True, text=True)
然后找Mbits/sec。解析不到 = 失败,返回码 0 不够。
不要在脚本里写if bitrate > 10: pass除非需求签字。脚本负责记数,人负责对照需求。


15. 和官方工具的关系,简历一句

「使用串口 AT 做过回归统计脚本;了解原厂 WiFiTestTool/netat 是同类胶水。未逆向。」
不要:「开发了泰芯产线校准软件」。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进