3. TestStand内置报告模板剖析
TestStand 安装目录下的 Components\Report\ 中,默认报告模板以 .xaml(WPF/XPS 报告)或 .xsl(HTML/XML 报告)形式存在。很多工程师第一次打开这些文件时,看到的是大量 <Grid>、<DataTemplate>、<xsl:for-each> 与 TestStand 命名空间混排的标记,很容易直接放弃。其实,默认模板的结构非常规整:它把一次测试执行拆成若干"区块",每个区块对应报告中的一段可视区域,区块内部再用循环和条件判断决定"哪些数据出现、出现几次、以什么样式出现"。理解这套结构,是后续自定义模板、增删字段、调整层级的前提。
一、报告模板的三层骨架
无论 XAML 还是 XSL,默认模板都遵循同一套三层骨架:报告头(Report Header)→ 序列与步骤主体(Sequence/Step Body)→ 报告尾(Report Footer)。报告头承载 UUT 信息、操作员、工位、开始时间、总体判定等"一次执行只出现一次"的字段;主体部分按序列调用层级递归展开,每个序列、每个步骤、每个测量值都可能产生一段输出;报告尾则汇总统计信息,如总步骤数、通过/失败计数、总耗时。
这三层并非简单的顺序排列,而是由 TestStand 的 Report 对象模型驱动。模板中大量出现 ThisContext、RunState、Sequence、Step 等绑定路径,它们分别指向当前执行上下文、运行状态、当前序列和当前步骤。模板本身不"计算"数据,只负责把引擎已经组织好的对象树"翻译"成可视标记。
二、循环结构:序列循环与步骤循环
默认模板中最核心的循环有两层。外层是序列循环,对应 Sequence 集合的遍历。TestStand 执行时可能调用多个序列(主序列、子序列、回调序列),模板通过 for-each 或 ItemsControl 逐一遍历,每个序列生成一个可折叠的区块标题。内层是步骤循环,对应某个序列内 Step 集合的遍历,每个步骤生成一行记录。
以 XSL 模板为例,典型写法是:
<xsl:for-each select="TestStand/Sequences/Sequence">
<xsl:for-each select="Steps/Step">
<tr>
<td><xsl:value-of select="@Name"/></td>
<td><xsl:value-of select="Result/@Status"/></td>
<td><xsl:value-of select="Result/@MeasuredValue"/></td>
</tr>
</xsl:for-each>
</xsl:for-each>
这里 @Name、@Status、@MeasuredValue 就是字段映射的落点。XAML 模板中对应的是 {Binding Name}、{Binding Result.Status} 这类绑定表达式。两者语义一致,只是语法不同。
三、条件判断:决定"显示什么"与"怎么显示"
默认模板不会把所有步骤一视同仁地输出。它通过条件判断控制三类行为:
- 是否显示该步骤:例如
Step.Result.Status = "Skipped"时,某些模板会跳过该行,或仅以灰色小字标注。 - 显示哪些字段:数值型步骤展开
MeasuredValue、Limits.Low、Limits.High;字符串型步骤则显示MeasuredString;无测量值的步骤只显示状态与耗时。 - 用什么样式显示:Passed 用绿色背景,Failed 用红色背景,Error 用橙色并附加错误信息,Done 用灰色。这些样式通常由
DataTrigger或xsl:choose实现。
一个常见的判断链是:先判断 Result.Status,再判断 Step.Result.Error.Code 是否非零,最后判断 Step.Result.ReportText 是否为空。只有全部条件满足,才输出完整的失败详情区块。这种"层层过滤"的设计,保证了报告既不过于冗长,也不会丢失关键失败信息。
四、数据字段映射:从对象模型到可视元素
默认模板中出现的字段并非随意命名,而是严格对应 TestStand 的 Result 对象属性。下表列出最常用的映射关系,可作为自定义模板时的对照参考:
| 报告显示内容 | 绑定路径 / XPath | 说明 |
|---|---|---|
| 步骤名称 | Step.Name | 步骤在序列中的名称 |
| 步骤状态 | Step.Result.Status | Passed / Failed / Error / Skipped / Done |
| 测量值 | Step.Result.MeasuredValue | 数值型测量结果 |
| 下限 / 上限 | Step.Result.Limits.Low / High | 数值限值 |
| 判定结果 | Step.Result.PassFail | True / False |
| 错误码 | Step.Result.Error.Code | 非零表示出错 |
| 错误描述 | Step.Result.Error.Msg | 错误文本 |
| 步骤耗时 | Step.Result.TotalTime | 秒为单位 |
| 报告文本 | Step.Result.ReportText | 自定义附加说明 |
| 序列名 | Sequence.Name | 当前序列名称 |
| UUT 序列号 | RunState.Root.ReportHeader.UUT.SerialNumber | 报告头字段 |
五、逐行阅读模板的实操方法
面对一份默认模板,建议按以下顺序阅读,而不是从第一行硬啃:
- 先搜索
ReportHeader,定位报告头区块,确认哪些字段被输出。 - 再搜索
for-each或ItemsControl,找到两层循环的边界,明确"序列循环"和"步骤循环"分别从哪里开始、到哪里结束。 - 在步骤循环内部搜索
choose、if、DataTrigger,列出所有条件分支及其触发条件。 - 最后搜索
Binding或value-of,把所有字段映射整理成一张对照表,与上表比对,确认哪些字段被使用、哪些被忽略。
.xaml 或 .xsl 复制一份到工作目录,用支持语法高亮的编辑器打开,再配合 TestStand 实际生成的报告对照查看。每改一处绑定,就重新执行一次简单序列,观察报告变化,比单纯读代码效率高得多。
Report 属性中指定新路径。否则软件升级或修复安装时,你的修改可能被覆盖,导致报告格式突然回退。
掌握默认模板的区块划分、循环结构、条件判断与字段映射之后,后续自定义报告时就能做到"知道改哪里、知道为什么改、知道改完看什么"。例如,若想在报告中增加"测试站编号",只需在报告头区块插入一个绑定 RunState.Root.ReportHeader.StationID 的文本元素;若想隐藏 Skipped 步骤,只需在步骤循环的条件判断中增加一条过滤规则。模板不再是黑盒,而是一份可读、可改、可验证的工程文件。