1. 单元测试框架入门
任务说明
本案例要求搭建一个ATE(Automatic Test Equipment)测试程序的最小可运行框架,该框架必须包含三个核心模块:初始化模块(负责测试系统与DUT的准备工作)、测试流程模块(执行具体的测试项并记录结果)、结果输出模块(将测试结果汇总并格式化输出)。框架采用Python实现,不依赖具体厂商的ATE硬件API,而是通过模拟接口保持逻辑完整性,便于独立运行与验证。
框架设计
框架采用模块化结构,各模块职责如下:
- 初始化模块:建立与测试座(socket)的连接、加载测试配置参数、执行DUT上电复位序列;
- 测试流程模块:按顺序执行预定义的测试项列表,每个测试项包含唯一的测试编号、名称、执行函数及上下限判定逻辑;
- 结果输出模块:将每个测试项的实测值、判定结果(PASS/FAIL)及测试时间戳汇总,生成文本格式的测试报告。
框架通过一个主控类ATEFramework串联上述模块,测试项以注册方式加入流程,便于后续扩展。当前案例聚焦框架本身的完整闭环,不涉及具体芯片的复杂测试算法。
代码实现
import time
import datetime
from dataclasses import dataclass, field
from typing import Callable, List, Tuple, Optional
# ---------- 结果记录数据结构 ----------
@dataclass
class TestResult:
test_id: str
test_name: str
value: float
low_limit: float
high_limit: float
unit: str
passed: bool
timestamp: str = field(default_factory=lambda: datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
def to_string(self) -> str:
status = "PASS" if self.passed else "FAIL"
return (f"[{self.timestamp}] {self.test_id} {self.test_name}: "
f"{self.value:.3f}{self.unit} (限值: {self.low_limit:.3f}~{self.high_limit:.3f}{self.unit}) -> {status}")
# ---------- 初始化模块 ----------
class InitModule:
"""模拟ATE测试系统的初始化:连接、配置加载、DUT复位"""
def __init__(self, config: dict):
self.config = config
self.socket_connected = False
self.dut_powered = False
def connect_socket(self) -> None:
# 模拟建立与测试座的通信连接
self.socket_connected = True
print("[初始化] 测试座连接成功")
def load_config(self) -> None:
# 从配置字典加载测试参数
print(f"[初始化] 加载配置: 测试项数量={self.config.get('test_count', 0)}")
print(f"[初始化] 配置加载完成")
def dut_power_on_reset(self) -> None:
# 模拟DUT上电与复位时序
time.sleep(0.05) # 模拟硬件延时
self.dut_powered = True
print("[初始化] DUT上电复位完成")
def run_all(self) -> None:
self.connect_socket()
self.load_config()
self.dut_power_on_reset()
# ---------- 测试流程模块 ----------
class TestFlowModule:
"""管理测试项注册与顺序执行"""
def __init__(self):
self.test_items: List[Tuple[str, str, Callable[[], float], float, float, str]] = []
self.results: List[TestResult] = []
def register_test(self, test_id: str, test_name: str,
func: Callable[[], float],
low_limit: float, high_limit: float, unit: str) -> None:
"""注册一个测试项: ID, 名称, 执行函数, 下限, 上限, 单位"""
self.test_items.append((test_id, test_name, func, low_limit, high_limit, unit))
def execute_all(self) -> List[TestResult]:
"""顺序执行所有已注册的测试项"""
for test_id, test_name, func, low, high, unit in self.test_items:
try:
measured_value = func() # 调用测试函数获得实测值
except Exception as e:
# 测试执行异常时按FAIL处理
measured_value = float('nan')
print(f"[测试] {test_id} 执行异常: {e}")
passed = (low <= measured_value <= high)
result = TestResult(test_id, test_name, measured_value, low, high, unit, passed)
self.results.append(result)
print(f"[测试] 完成 {test_id} {test_name}: {measured_value:.3f}{unit} {'PASS' if passed else 'FAIL'}")
return self.results
# ---------- 结果输出模块 ----------
class ReportModule:
"""生成测试汇总报告"""
@staticmethod
def generate_report(results: List[TestResult]) -> str:
lines = []
lines.append("=" * 60)
lines.append("ATE 测试报告")
lines.append("=" * 60)
total = len(results)
passed_count = sum(1 for r in results if r.passed)
for r in results:
lines.append(r.to_string())
lines.append("-" * 60)
lines.append(f"总计: {total} 项, 通过: {passed_count} 项, 失败: {total - passed_count} 项")
lines.append("=" * 60)
return "\n".join(lines)
# ---------- 主控框架 ----------
class ATEFramework:
"""ATE测试程序主控类,串联初始化、测试流程与结果输出"""
def __init__(self, config: dict):
self.config = config
self.init_module = InitModule(config)
self.test_flow = TestFlowModule()
self.report_module = ReportModule()
def run(self) -> str:
"""执行完整测试流程,返回报告文本"""
# 1. 初始化
self.init_module.run_all()
# 2. 执行测试流程
results = self.test_flow.execute_all()
# 3. 生成报告
report = self.report_module.generate_report(results)
return report
# ---------- 测试项定义(模拟DUT测量) ----------
def test_vcc_measure() -> float:
"""模拟测量DUT的VCC电压,返回3.30V附近的值"""
# 实际项目中此处调用ATE板卡测量函数
return 3.298 # 模拟实测值
def test_iq_measure() -> float:
"""模拟测量DUT静态电流,返回2.5mA附近的值"""
return 2.45
def test_clk_freq() -> float:
"""模拟测量时钟频率,返回10MHz附近的值"""
return 10.02
# ---------- 主程序入口 ----------
if __name__ == "__main__":
# 测试配置
config = {
"test_count": 3,
"device": "DUT_CHIP_001",
"socket_id": "SOCKET_A"
}
# 创建框架实例
framework = ATEFramework(config)
# 注册测试项: (ID, 名称, 函数, 下限, 上限, 单位)
framework.test_flow.register_test("T001", "VCC电压测试", test_vcc_measure, 3.15, 3.45, "V")
framework.test_flow.register_test("T002", "静态电流测试", test_iq_measure, 1.80, 3.20, "mA")
framework.test_flow.register_test("T003", "时钟频率测试", test_clk_freq, 9.50, 10.50, "MHz")
# 运行完整测试流程
final_report = framework.run()
# 输出报告
print("\n" + final_report)
落地与运行方式
将上述代码保存为ate_framework.py,在Python 3.8+环境中直接运行:
python ate_framework.py
代码仅使用Python标准库(time、datetime、dataclasses、typing),无需安装第三方依赖。
验证方法与判定标准
运行程序后,观察控制台输出,需满足以下条件即判定框架搭建成功:
- 初始化阶段依次打印“测试座连接成功”“配置加载完成”“DUT上电复位完成”三条日志;
- 测试流程阶段依次执行3个已注册的测试项,每项打印实测值与PASS/FAIL状态;
- 最终输出包含“ATE 测试报告”标题、每项详细结果行以及汇总统计行(总计3项,通过3项,失败0项)。
由于三个测试项的模拟返回值(3.298V、2.45mA、10.02MHz)均在设计限值范围内,预期全部判定为PASS。若需验证FAIL路径,可修改某个测试函数的返回值使其超出限值范围,重新运行后对应测试项应显示FAIL,且汇总统计中失败计数相应增加。