TestStand API 编程【4】
TestStand架构与TestStand API
精心设计的模块化测试架构可提供极大的价值。灵活的通用架构可应用到多种测试系统上,以延长测试系统的使用寿命并降低测试开发成本。TestStand提供了基于模块化的平台,可简化测试系统及相应测试的开发过程。TestStand的强大之处在于其开放式架构,用户可通过该架构创建复杂且灵活的测试解决方案。
TestStand引擎提供TestStand组件所需的功能,组件通过TestStand API与引擎进行通信
TestStand的表示层(用户看到的内容)和业务逻辑层(用户动作背后的操作)之间存在明确的分隔。不同层之间通过TestStand API进行通信。通过这种方法,用户可创建通过TestStand API调用TestStand引擎的附加组件(例如,创建自定义用户界面、动态控制测试流、在运行时创建序列以及开发其他高级解决方案),从而扩展TestStand的功能。
TestStand API架构
TestStand引擎是一个ActiveX/COM自动化服务器,可通过API访问其功能。Microsoft开发的ActiveX应用程序通信标准提供了应用程序间的通信方法。ActiveX基于COM技术,多年来在业界得到了广泛应用。TestStand同样基于COM,因此能够超出ActiveX的生命周期并在未来的Windows操作系统版本上继续运行。
ActiveX采用的是客户端/服务器架构。ActiveX服务器是将特定功能开放给遵循ActiveX标准的客户端的应用程序。此外,ActiveX应用程序采用的是面向对象编程(OOP)方法。
ActiveX服务器架构允许任何可调用ActiveX代码的编程语言(例如LabVIEW、LabWindows™/CVI™、C#、VB .NET或C++)与TestStand引擎进行交互。使用TestStand API编程时,具体实现方法取决于用户使用的语言。例如:
- LabVIEW使用“属性”和“调用”节点来调用API。
- LabWindows/CVI使用仪器驱动wrapper来对API调用进行包装。
- C#或VB .NET使用TestStand提供的互操作程序集调用API。
- TestStand本身也提供了用于访问API的ActiveX/COM适配器,用户还可以通过表达式直接访问API。
无论使用哪种方式访问API,在任何环境中引发的行为都是相同的,因为具体功能在TestStand引擎中实现,与使用的接口无关。
API类
TestStand API定义了多种类来表示TestStand对象的类型,例如SequenceFile类或Execution类。每个类都定义了属性和方法,可用于访问相关数据或执行操作。例如,SequenceFile类定义了Path属性以存储序列文件在磁盘中的路径,还定义了Save方法以保存序列文件。
类继承
TestStand中的许多类通过继承相互关联:较为具体的类可继承通用类的属性或方法。例如,SequenceFile类是PropertyObject类的更具体版本。TestStand API所定义的类之间的继承关系允许较具体的类对象访问通用类的属性和方法。
SequenceFile类继承了更通用的PropertyObjectFile类和PropertyObject类的属性和方法。
几乎所有的TestStand API类都继承自PropertyObject基类,该基类中包含TestStand对象共享的常见方法和属性。PropertyObject类定义了通用属性(例如Name和Numeric Format),并提供了常用的对象管理方法(例如复制、设置/获取值、创建/删除对象及操作数组)。由于大多数TestStand API类继承自PropertyObject类,因此可以访问通用属性和方法。例如,您可以使用PropertyObject.Clone()方法创建步骤、序列或序列文件对象。
许多开发环境会阻止您直接访问父类的属性。同样的,在TestStand中,SequenceFile对象无法直接调用Clone()方法。但TestStand API提供的强制转换方法可允许对象访问通用类的属性和方法。如需访问PropertyObject类所定义的属性和方法,可调用AsPropertyObject方法将对象强制转换为父类。例如,如需在序列文件对象上访问Clone()方法,应使用
SequenceFile.AsPropertyObject.Clone()。
关于API继承和PropertyObject类属性及方法的详细信息,详见NI TestStand帮助。
动态属性与内置属性
TestStand对象有两种不同的属性类型:
- 内置属性(API属性)由对象的类定义,适用于特定类的所有对象。
- 动态属性(子属性)由对象定义,同一个类的不同对象之间可能会有差异。
步骤对象具有动态属性(因步骤类型而异)和静态属性(由TestStand API中的步骤类定义)
这两种不同的属性类型均可在TestStand表达式中使用“.”操作符进行访问, 因此很容易混淆。但在其他编程语言中使用API时,通过直接访问方法只能访问内置属性,例如在LabVIEW中使用属性节点。
如需访问动态属性,需使用PropertyObject API方法,例如GetValString()和GetValNumber(),并通过LookupString指定动态属性的名称:
在某些情况下,可使用动态属性或内置属性以多种方式对属性进行访问。在代码模块中使用TestStand API时,最好使用内置属性,因为内置属性可直接访问,无需维护查找字符串。
TestStand对象关系
TestStand对象可包含不同类中的其他对象,这称为API包含(API Containment)。例如,SequenceFile对象包含序列文件中定义的序列所对应的Sequence对象。每个Sequence对象又包含Step对象。
TestStand API中的对象通常包含另外一个类的其他对象
理解对象之间的包含关系有助于查找具体的对象。如父对象包含多个属于特定类的子对象,如果要查找所需的子对象,必须提供属性名称或索引。对于大多数子对象,可使用特定的getter方法,通过父对象访问被包含的对象,getter方法可接受对象名称或索引作为参数。例如,如需访问序列文件中的某个步骤,可使用:
SequenceFile.getSequenceByName(“MainSequence”).GetStepByName(“RAM Test”, StepGroup_Main)
此外,子对象可通过API访问其父对象。由于子对象只能有一个父对象,可使用属性直接访问父对象,无需使用getter方法。例如,如需访问SequenceContext对象的父对象execution,可使用:
ThisContext.Thread.Execution
在多数情况下,内置属性可用于访问关系较远的祖先类。例如,可从Sequence Context对象中直接访问execution对象:
ThisContext.Execution
通过TestStand API对象进行导航
除了通过包含关系进行导航之外,许多类还提供了用于访问其他相关对象的属性或方法。例如,Module类提供的Adapter属性可用于访问正在运行的相应适配器。
TestStand API参考帮助提供了所需的图表,来帮助您确定通过当前对象访问目标对象的方法。下表为该表格的一部分。
可根据对象关系从sequenceContext对象访问其他对象
访问TestStand API
根据要创建的应用程序类型,有两种常见的访问API的方法:
- 对于独立应用程序,需要创建一个新的TestStand引擎实例(instance)。
- 对于从现有应用程序中调用的代码模块或其他工具,必须传递TestStand引擎的现有引用。
创建独立TestStand应用程序
如需在新的应用程序中使用TestStand API,必须首先创建一个TestStand引擎实例。任何TestStand应用程序或进程(例如TestStand用户界面、序列编辑器或自定义工具)需要维护引擎的一个实例,也称为单例(singleton),才能执行任意TestStand功能。引擎将维护内存中所有对象的引用、设置/控制执行并存储TestStand会话的上下文数据以及站点全局变量和用户信息。
TestStand引擎提供了创建其他TestStand对象的方法,以关键字“new”表示,示例如下:
- Engine.NewSequenceFile()
- Engine.NewStep()
- Engine.NewExecution()
- Engine.NewPropertyObject()
关于引擎对象的可用属性和方法的完整列表,详见“TestStand引擎”主题。
应用程序完成后,必须先关闭TestStand引擎,然后再退出应用程序。关闭需要两个步骤,以确保用户能够终止任何正在运行的执行过程,具体说明见TestStand帮助中的关闭引擎主题。
NI建议使用TestStand UI控件开发TestStand应用程序和用户界面,以降低程序的复杂度,而非直接创建TestStand引擎对象。TestStand UI控件在TestStand API之上提供了一个抽象层,使得独立TestStand应用程序的开发变得更加容易。关于使用UI控件的更多信息,见本文档的[UI控件API]部分。
从现有应用程序调用代码模块或工具
在从其他TestStand应用程序中调用的代码模块或工具中使用API时,可使用顶层应用程序所创建的TestStand引擎。如从正在执行的序列(例如代码模块)中调用代码,最好使用SequenceContext的输入参数来完成操作。相对于直接传递TestStand引擎,该方法更具优势,因为通过sequence context不仅可以访问TestStand引擎对象,还可以访问当前执行状态。
SequenceContext表示序列的当前执行状态,可提供正在执行的特定序列的所有数据快照。任何线程中的每个执行序列都有自己的SequenceContext。
浏览“变量”视图时看到的列表为Sequence Context一级属性,其中包括全部变量类型、当前步骤及RunState属性。SequenceContext还提供了许多其他对象的引用,并将其作为内置属性。
RunState与SequenceContext
RunState属性和SequenceContext均可用于访问大多数同类对象,例如当前执行、线程、序列文件以及序列。但RunState属性包含这些对象,且将其视为动态属性,而SequenceContext将其视为内置属性。
因此,访问TestStand表达式中的状态相关信息时应使用RunState属性;SequenceContext更适用于无法直接访问动态属性的代码模块。
SequenceContext同时使用内置属性和动态属性提供执行状态信息,而RunState属性仅使用动态属性提供状态信息。
序列数据的存在时间
执行序列中的步骤之前,TestStand将为序列创建运行时副本(run-time copy),以便为每个序列调用维护单独的局部变量和步骤属性值。在多数情况下,通过执行序列内部的Runstate或SequenceContext访问对象时,实际访问的对象为运行时副本。这意味着,用户对这些对象所作的改动在执行结束后将不复存在。例如,更改局部变量的值或以编程方式为参数创建子属性均不会影响磁盘中的序列文件:
Locals.SetValString("RuntimeVariable",1, "value")
继承自PropertyObjectFile类的对象(如SequenceFile对象)不具有单独的运行时副本,因此通过这些对象所做的改动在执行结束后仍将存在。例如,通过SequenceFile对象访问Locals属性可创建持续存在的局部变量。
RunState.sequencefile.GetSequenceByName("MainSequence").Locals.SetValString("PersistantVariable",1, "value")
TestStand API的常见应用
虽然TestStand API能够实现所有TestStand功能自动化,但API常用于下列应用:
- 创建自定义属性
- 创建新序列文件
- 修改现有序列
创建自定义属性
可使用TestStand API在运行时动态创建自定义属性,例如,在特定组件测试失败时向测试结果添加特定诊断数据,或向报告表头添加自定义数据。
可通过多种方式使用API创建自定义属性。对于原生数据类型,创建新属性最简单的方法是使用具有InsertIfMissing选项的“SetVal”方法。例如,可使用下列表达式向数值限制测试步骤添加新属性:
RunState.Sequence.Main["Numeric Limit Test"].AsPropertyObject.SetValString(
"Result.extraResult",
PropOption_InsertIfMissing,
"this string is an extra result")
如需向报告添加自定义属性,必须同时设置对象的IncludeInReport参数,报告生成器通过该参数选择要记录的结果属性:
RunState.Sequence.Main["Numeric Limit Test"].AsPropertyObject.SetFlags(
"Result.extraResult",
0,
PropFlags_IncludeInReport)
关于使用API向测试报告添加数据的详细信息,详见Adding Custom Data to a Report范例。
对于较复杂的属性(例如容器),需使用NewSubProperty()方法直接创建属性,该方法可用于创建容器、数据类型实例以及数组。例如,可使用下列表达式创建类型为Error的新局部变量:
Locals.NewSubProperty("ComplexContainer.Error",PropValType_NamedType, False, "Error",0)
关于使用API创建属性的详细信息,详见[Creating new properties using API]范例。
创建新序列
如需根据用户输入自动创建序列文件,可使用TestStand API生成新的序列文件或创建现有文件的修改副本。例如,可创建自定义工具使其根据特定用户输入生成初始序列文件,或对现有序列文件的步骤执行特定的修改。
关于使用API创建新序列文件的详细信息,详见 Building a Sequence Using the API 范例。
也可以使用TestStand API开发序列文件转换器,生成自定义文件格式的序列文件。创建序列文件转换器时,可通过TestStand API根据指定文件中的数据生成序列文件、序列、步骤及属性。用户可通过转换器架构将上述代码集成至TestStand,并直接以自定义格式打开文件。
关于使用序列文件转换器的详细信息,详见TestStand帮助中的序列文件转换器主题
修改序列
可在自定义工具中使用TestStand API对现有的序列文件进行修改。例如,可创建工具对由绝对路径指定的代码模块进行检查,并将其替换为相对路径。
详细信息见Creating a Sequence File Iteration Tool范例。
其他TestStand API
除了核心TestStand API以外,TestStand的其他API可用于扩展性能及提供额外功能:
- UI控件API
- 适配器API
- 同步服务器API
与核心TestStand API不同,这些API不能通过表达式直接访问,必须通过ActiveX步骤或单独的代码模块才能使用。
UI控件API
TestStand包含一组用户界面控件,可用于快速开发TestStand用户界面。这些控件包括用于显示TestStand数据的可见控件(例如步骤视图或变量视图)以及在TestStand用户界面中处理与TestStand引擎API之间大部分通信的不可见管理程序控件。
开发独立的TestStand应用程序时,NI建议用户使用UI控件来开发应用程序,而非直接创建TestStand引擎实例。
用户可使用UI控件API通过管理程序控件实现常见的用户界面任务,例如打开和执行序列文件、响应UI消息及处理应用程序关闭。UI控件API还提供了用于配置UI控件的连接方法。
关于使用UI控件和UI控件API的详细信息,详见下列帮助主题:
- TestStand UI控件-概述了如何使用UI控件开发TestStand UI应用。
- TestStand UI控件API参考帮助-介绍UI控件API中的类。
- UI开发最佳实践-介绍使用UI控件和API的最佳操作方法。
可将TestStand UI控件想象为TestStand引擎API之上的一个软件层。这些控件对用户界面中的许多常用功能包装起来,例如打开序列、运行测试、显示测试进度等。TestStand UI控件功能丰富,且包含自身的API。尽管本文档的范围并不涵盖用户界面控件的功能,但应指出的是,这些控件所提供的功能是建立在TestStand引擎API的基础之上。
适配器API
适配器API能够为TestStand中包含的不同适配器提供专用的类。通常,在核心API中使用适配器或模块类时,可使用适配器API来获取适配器特有的信息或功能。此时,对象将会被强制转换为合适的适配器API类。例如,可使用LabVIEWModule类访问用于LabVIEW步骤中的模块对象的LabVIEW特有属性和方法。
使用适配器API访问模块或适配器类的适配器特有属性和方法
同步服务器API
同步服务器API可提供直接访问TestStand同步对象(例如,队列、锁定或通知)的方法。要使用该API,首先需通过Engine.GetSyncManager方法获取同步管理器的引用。将该对象强制转换为同步服务器API中所定义的同步管理器类之后,可用其访问或创建新的同步对象。
使用SyncManager和同步服务器API在代码中创建并访问TestStand同步对象
该API适用于开发与TestStand测试同时运行且需访问执行状态信息的应用程序,例如,状态监控应用程序。
关于可用的类的详细信息,详见同步服务器API参考主题。