概覽
本文檔討論了開發測試系統代碼模塊並從測試序列中調用這些模塊時可能會用到的最佳實踐。要使用本文檔,您需要掌握TestStand的基本工作原理,其中包括創建基本測試序列的方法。如果您不熟悉這些概念,請在使用本文檔之前了解以下入門資源: NI TestStand 基礎學習篇
內容
- 確定代碼模塊開發的策略
- 選擇要實現功能的位置
- 實現代碼模塊的最佳實踐
- 使用代碼模塊中的儀器
確定代碼模塊開發的策略
開始開發測試系統之前,請考慮為測試系統的以下方面確定一種通用方法:
- 代碼模塊的粒度 — 定義每個模塊的功能范圍。
- 定義測試代碼的目錄結構 — 定義明確的目錄結構使開發人員之間可以更輕松地共享代碼,且更易於測試系統的代碼部署。
代碼模塊的粒度
在設計測試系統時,請務必為代碼模塊定義一致的粒度級別。 粒度是指測試系統中每個代碼模塊的功能范圍。 粒度低的測試序列調用的代碼模塊數量少,每個代碼模塊執行的功能更多;而粒度高的測試序列調用的代碼模塊數量多,每個代碼模塊執行的功能更少。
低粒度 | 高粒度 |
|
|
由於二者各有優勢,因此您應該在這些極端情況之間取得平衡。
利用不同的粒度級別實現簡單測試
為了在整個測試系統中保持一致的粒度,需要為代碼模塊開發創建一組標准,例如:
- 在單獨的代碼模塊中執行硬件初始化和關閉,讓TestStand管理硬件會話的生命周期。
- 為每個需求項目創建單個測試步驟,從而根據測試需求確定粒度。 這種方法可以更輕松地確保所有要求均得到滿足。 此外,NI Requirements Gateway可與TestStand搭配使用,創建測試步驟與需求文檔之間的關聯。 如需更多信息,請參閱《NI Requirements Gateway與TestStand搭配使用》教程。
- 所需的測試結果結構可用於幫助確定各個步驟的范圍。 由於每個步驟都會生成一個結果條目,因此創建測試步驟到所需結果條目的一對一映射將使組織測試結果變得更容易,且對報告或數據庫記錄的更改最少。
定義序列文件和代碼模塊的目錄結構
指定測試步驟中代碼模塊的路徑時,可選擇使用絕對路徑或相對路徑。建議不要使用絕對路徑,原因如下:
- 在磁盤上移動序列文件及其依賴項后,相應路徑將失效。
- 如果將序列文件部署到目標計算機,除非文件安裝在同一位置,否則相應路徑將失效。
指定相對路徑時,TestStand會使用搜索目錄列表來解析路徑。 這些搜索目錄通常包含當前序列文件目錄、TestStand特定目錄和系統目錄。
在開始開發之前,請務必為測試序列和代碼模塊定義文件結構。 請按照以下指南定義用於存儲序列文件和代碼模塊的策略。
- 對於用於單個序列文件的代碼模塊,請將代碼模塊文件保存在與序列文件相關的子目錄中。 這將確保,即使序列文件在系統中移動或復制到另一個系統上,它也能夠找到代碼模塊。
- 對於在多個相關序列文件之間共享的代碼模塊,如果相關序列文件保存在同一目錄中,則可以使用與單個序列文件相同的方法。 考慮創建一個工作區來容納所有相關的序列文件和代碼模塊。
- 對於在多個不相關的序列文件之間共享的代碼模塊,請考慮創建一個特定目錄來容納所有共享的代碼模塊,並創建指向此位置的新搜索目錄。 這將確保系統中的所有序列文件都可以使用此搜索目錄的相對路徑來找到相應文件。 部署代碼模塊時,可同時部署位於<TestStand Application Data>\Cfg\SearchDirectories.cfg的搜索目錄配置文件。 使用此方法時,請不要在目錄內移動代碼模塊文件,以免破壞調用序列文件時指定的路徑。
定義目錄結構,其中代碼模塊位於序列文件的子目錄中
使用TestStand部署工具部署測試代碼時,可為序列文件和相關代碼模塊選擇特定的目標。 如果序列文件和代碼模塊的目標目錄之間存在相對路徑,則TestStand部署工具會更新序列文件中的路徑來指向更新后的位置。 在大多數情況下,最好使部署的目錄結構與開發系統上的目錄結構相匹配,從而確保部署與開發計算機上的代碼盡可能相似。
選擇要實現功能的位置
在定義測試系統的代碼模塊范圍時,請務必定義在代碼模塊和序列文件中實現功能的策略。以下部分可幫助確定最適合實現常用功能的位置:
- 根據極限評估測試測量值
- 定義激勵值
- 報告並記錄測試結果和錯誤
- 循環操作
- 執行開關操作
- 執行計算和處理數據
評估極限和測試結果
理想情況下,代碼模塊應包含與獲得測試測量值直接相關的功能,並且測試序列應處理原始測試結果。這種方法具有以下優勢:
- 由於在序列文件中可使用屬性加載器等工具在單個中心節點管理多個步驟的極限,因此測試極限在序列文件中更易於管理。
- 序列中定義的測試極限將自動添加到測試結果中,例如報告或數據庫。
- 測試極限可在不更改代碼模塊的情況下進行更新,並且由於只修改了測試序列,因此所需的驗證更少。
為了簡化測量,代碼模塊可以將原始測量值返回到序列中進行處理。例如,如果測試步驟用於測量待測設備(UUT)特定引腳上的電壓,則代碼模塊應返回測量值,而不是直接在代碼模塊中執行檢查。 您可以使用數值邊界測試步驟來處理該值,從而確定序列文件中的測試結果。
在測試步驟中評估極限可簡化代碼模塊並改進結果記錄
但是,由於某些測試十分復雜,因此並非總是能夠在序列文件中處理原始測試結果。 對於更復雜的測量,可能需要對結果數據進行進一步處理。 復雜數據可處理為單個字符串或數值結果,然后便可以在TestStand中使用字符串或數值比較功能對其進行評估。 例如,掃頻測試的結果很復雜,無法直接進行評估,但可以將這些數據處理為代表最小值的單個數字。 在這種情況下,代碼模塊應評估處理后的結果,並以單獨的參數形式返回頻率數據,以便記錄,如下面的移動設備測試示例所示:
對於更復雜的數據,請在代碼模塊中處理數據,生成數值或字符串結果,然后使用參數傳出原始數據,以便記錄
如果原始數據非常大,則將數據傳遞給TestStand的過程可能會對性能產生重大影響。 在這種情況下,可考慮將數據直接記錄到TDMS文件中,並在測試報告中添加指向該文件的鏈接。 如此一來,可在無需將數據傳遞給TestStand的情況下從報告中引用數據。 關於此方法的更多信息,請參閱《在報告中添加超鏈接 — TDMS文件》。
如果該步驟無法使用測試步驟中可用的評估類型來確定測試結果,請考慮創建具有附加功能的新步驟類型來處理所需的測試類型。 關於創建自定義步驟類型的更多信息,請參閱本系列中的《自定義步驟類型開發的最佳實踐》一文。
定義測試激勵
對於許多測試而言,UUT或測試環境必須處於特定狀態下才能執行測試。 例如,進行溫度測量可能需要使用激勵電壓,或者必須將加熱室設置為指定溫度。 對於這些類型的模塊,應使用參數來傳遞輸入值,例如激勵電壓或所需溫度。 與上一部分所述的直接在代碼中處理極限相比,這與在測試代碼模塊中返回原始數據具有許多相同的優勢。
記錄測試結果
TestStand具有使用測試步驟的結果來生成報告和記錄數據庫的內置功能。因此,請避免直接在代碼模塊內進行任何類型的數據記錄。 相反,請確保將要記錄的所有數據以參數形式傳出,並使用TestStand記錄相應數據。 一些數據(例如測試結果、極限和錯誤信息)將自動記錄。 要記錄其他數據,可使用其他結果功能來指定要添加到報告中的其他參數。
關於將結果添加到測試報告中的更多信息,請參閱TestStand隨附的《將自定義數據添加到報告》示例。
如果您對記錄有特定要求,請考慮修改或創建結果處理插件。如此一來,可以使用內置的TestStand結果收集功能收集結果,同時可以確定結果的處理方式和顯示方式。如需更多信息,請參閱《TestStand過程模型開發和自定義的最佳實踐》文檔的“創建插件”部分
循環操作
由於實現循環的每種方法都有其自身的優缺點,因此很難確定理想的方法。請使用以下指南來幫助確定最適合您的應用程序的策略:
在代碼模塊中進行內部循環
- 性能得以提高,尤其是在快速循環時。 由於每次代碼模塊調用都會產生幾毫秒的開銷,因此使用外部循環進行數百或數千次迭代循環會影響測試速度。
- 支持更復雜的循環行為。
在序列文件中進行外部循環
- 直接在序列文件中查看和修改循環設置,不需要修改代碼模塊。
- 輕松訪問序列文件中的循環索引。 這對於確定基於當前迭代而變化的開關路由或其他行為很有用。
- 循環的每次迭代均單獨記錄,在報告或數據庫中顯示每次迭代的結果。
執行開關操作
許多測試系統可借助開關功能使用單個硬件測試多個待測區。 借助預定義的路由,開關功能支持以編程方式控制連接到特定硬件的待測設備(UUT)引腳。
您可以通過以下方式在TestStand代碼模塊中實現開關功能:
- 使用步驟的內置開關屬性(需要NI Switch Executive)
- 使用TestStand IVI Switch步驟(僅適用於32位TestStand)
- 直接在代碼模塊中調用開關驅動程序函數
使用NI Switch硬件時,NI Switch Executive可用於快速定義路由。在可以訪問NI Switch Executive的情況下,使用內置的步驟設置來實現開關功能通常是最佳方法,此方法具有以下優勢:
- 在步驟中定義開關配置可以將開關函數與測試代碼分離,從而提高可復用性並降低代碼模塊的復雜性。
- 開關設置中的許多字段都是通過表達式指定的,因此可利用RunState.LoopIndex屬性或其他變量來為要迭代的步驟建立路由或路由組名稱的索引。
- 對於並行測試,可在路由字符串中添加測試插槽索引(RunState.TestSockets.MyIndex),對每個測試插槽使用不同的開關路由。
- 連接生命周期可與步驟、序列、線程或執行關聯起來。
使用NI Switch Executive直接在TestStand步驟設置中指定路由,包括TestStand表達式支持,從而使用當前循環索引或其他屬性來動態確定路由
關於使用開關步驟屬性整合開關功能的更多信息,請參見《借助NI Switch Executive加速開發並簡化維護》在線教程。
執行計算和處理數據
為了避免為較簡單的任務維護代碼模塊,可使用TestStand中的表達式語言來執行基本計算和單維數組操作。由於編程語言提供了更適合這些任務且更強大的功能,因此應在代碼模塊中執行更高級的編程要求。 例如,與使用表達式語言相比,使用原生LabVIEW創建數組函數可更輕松地完成多維數組的連接。
在某些情況下,可使用.NET框架隨附的原生類避免創建過於復雜的表達式。 例如,System.IO.Path類可在無需創建代碼模塊的情況下用於快速執行路徑操作。
無需代碼模塊的參與,即可借助.NET步驟來使用.NET框架方法
實現代碼模塊的最佳實踐
實現代碼模塊時,許多設計決策都會影響創建的許多代碼模塊。 本部分提供有關以下概念的指南:
- 將數據從TestStand傳遞到代碼模塊
- 處理代碼模塊中的序列終止
- 向TestStand報告代碼模塊錯誤
- 管理代碼模塊的執行速度和內存使用
將數據從TestStand傳遞到代碼模塊
訪問代碼模塊中的TestStand數據的方法有兩種:
- 通過代碼模塊參數傳遞數據
- 使用TestStand API在代碼模塊內直接訪問數據
在大多數情況下,與使用TestStand API直接訪問數據相比,使用參數傳遞數據是一種更好的方法,具體原因如下:
- 出錯可能性更低 — 由於參數值是在TestStand的步驟類型設置中定義的,而不是直接在代碼模塊中定義的,因此更容易發現屬性名稱或數據類型中的錯誤。
- 更易於維護 — 對步驟屬性的更改是在TestStand的參數配置中指定的,無需修改代碼模塊。
- 更容易在TestStand之外復用 — 由於代碼模塊不依賴於TestStand API,因此模塊無需修改即可在TestStand之外使用
盡可能使用參數將所需數據傳遞到代碼模塊
但是,根據步驟的狀態,當代碼模塊需要動態訪問各種數據時,使用API直接訪問屬性可能很有幫助。 在這種情況下,使用步驟參數會導致參數過多,而在不同情況下,實際用到的參數只有一部分。
如果要在代碼模塊中使用TestStand API,則需要向SequenceContext對象(ThisContext)傳遞一個引用作為參數。SequenceContext對象可訪問所有其他TestStand對象,包括TestStand引擎和當前的Runstate。如果使用終止監視器或模態對話框VI,則需要序列上下文引用。
使用SequenceContext訪問代碼模塊中的TestStand API,可用於以編程方式訪問數據
如果要在TestStand之外復用代碼模塊,請記住,只有在從TestStand序列調用相應模塊的情況下,才能使用TestStand API進行操作。模塊通過API從TestStand獲取的所有數據將不可用。 從TestStand外部調用代碼模塊時,可先檢查序列上下文引用是否為空,從而定義獲取測試數據的備用機制。 在LabVIEW中,可以使用Not A Number/Path/Refnum?函數,它會返回一個布爾值,如圖3所示。
對於在TestStand之外使用的代碼模塊,請使用Not a Number/Path/Refnum?檢查SequenceContext對象引用的有效性
在代碼模塊中處理大型數據集
在許多情況下,代碼模塊會在測量或分析過程中生成大量復雜數據。 由於TestStand會在存儲此類數據時創建數據副本,因此請避免將此類數據存儲在TestStand變量中。 這些副本可能會降低Runtime性能和/或導致內存不足錯誤。 使用以下方法來管理大型數據集,即可避免創建不必要的副本:
- 在代碼模塊內處理大型數據集,例如在獲取數據的同一代碼模塊中分析數據,並且僅向TestStand返回所需的結果
- 在TestStand和代碼模塊之間傳遞數據指針。 對於LabVIEW代碼模塊,請使用數據值引用(DVR)
處理代碼模塊中的序列終止
用戶按下“終止”按鈕時,TestStand會停止執行序列並運行所有“清理”步驟。但是,如果執行調用了代碼模塊,則該模塊必須完成執行並將控制權交回TestStand,然后序列才能終止。如果代碼模塊的運行時間超過數秒,或者模塊需要等待用戶輸入之類的條件發生,對於用戶來說,終止命令可能會被忽略。
要解決此問題,可以使用終止監視器,讓代碼模塊檢查並響應調用執行的終止狀態。例如,“計算機主板測試”隨附范例會使用仿真對話框中的終止監視器,如下圖所示。 如果測試序列終止,則檢查終止狀態VI會返回假值,循環停止。
處理錯誤
測試系統中的錯誤是非預期Run-Time行為,會妨礙測試的執行。代碼模塊產生錯誤時,請將該信息傳回測試序列,以此確定下一步要執行的操作,例如終止執行、重復上一次測試或提示測試操作員。
要向TestStand提供來自代碼模塊的任何錯誤信息,請使用步驟的Result.Error容器,如下圖所示。 執行每個步驟之后,TestStand都會自動檢查此屬性來確定是否發生錯誤。 無需將錯誤信息從TestStand傳遞到代碼模塊。如果代碼模塊向TestStand返回錯誤,則執行過程會引出分支到測試序列的另一部分,例如“清理”步驟組。
您可以使用“測試站選項”的“執行”選項卡中的“Run-Time錯誤”設置來確定TestStand響應步驟錯誤的方式。 通常,在開發用於協助調試的序列時應使用“顯示對話框”選項,因為此選項可中斷執行並檢查序列的當前狀態。 對於已部署的系統,請考慮使用“運行清理”或“忽略”選項,而不是要求測試操作員進行輸入。 錯誤信息將自動記錄到測試結果中,可用於查找錯誤的原因。
將錯誤信息傳遞到Step.Result.Error容器,用於通知TestStand是否發生了步驟錯誤
管理代碼模塊的性能和內存使用
默認狀態下,在文件中執行序列時,TestStand會將序列文件中的所有代碼模塊加載到內存中,並保持加載狀態,直到關閉序列文件為止。 使用這些設置后,如果在模塊加載的同時開始一個序列,則會出現初始延遲。 但是,由於模塊仍在內存中,因此序列文件的后續執行會更快。
步驟設置窗格的“運行選項”選項卡可用於配置何時加載和卸載代碼模塊。通常,默認的加載選項可提供出色的性能,但是在某些情況下,可將加載選項設置為動態加載,從而使代碼模塊僅在使用時才加載,這可能是一種更好的選擇。 對於不在常用執行中調用的代碼模塊,例如僅在特定測試失敗后才運行的診斷,應采取動態加載方式,因為在大多數情況下這些模塊根本不需要加載。
請注意,在動態加載代碼模塊時,TestStand只會在加載代碼模塊之后才會報告相應代碼模塊的問題,此時漫長的執行過程可能即將結束。但是,可以在執行之前使用序列分析儀驗證序列中是否存在錯誤。 分析儀將檢查靜態和動態加載的代碼模塊。
對於內存密集型代碼模塊,可修改默認的卸載選項來減少總內存使用量。 例如,將模塊設置為步驟執行后卸載或序列執行后卸載。 但是,此更改將增加執行時間,因為TestStand需要為每次后續調用重新加載模塊。如有可能,可以使用64位版本的TestStand和具有更多物理內存的系統,這種方法更好,在對內存使用量有較高要求的情況下仍獲得出色的測試性能。
如果代碼模塊維護共享數據,例如靜態變量或LabVIEW功能全局變量,由於在模塊卸載時會丟失全局數據,因此修改卸載選項可能會導致行為改變。更改卸載選項時,請確保將任何必需的數據傳遞到TestStand序列或存儲在更為永久的位置,防止數據丟失。
關於優化測試系統性能的其他方式的更多信息,請參閱《提高NI TestStand系統性能的最佳實踐》。
使用代碼模塊中的儀器
代碼模塊的常見用途是與測試硬件連接以設置激勵並進行測試測量。 與硬件通信的方法包括:
• 使用硬件驅動程序(例如NI-DAQmx)直接與硬件通信。
• 使用儀器驅動程序,此驅動程序可在內部通過VISA或IVI硬件驅動程序將命令發送到儀器。
所采用的通信方式取決於使用的硬件類型。 對於這兩種通信,您都需要在進行特定驅動程序的調用之前打開針對驅動程序的引用或會話,並在交互完成后關閉句柄。
選擇管理硬件引用的方法
在大多數情況下,您將在多個測試步驟中與同一硬件進行通信。為了避免在每個代碼模塊中打開和關閉儀器會話對性能的影響,請務必考慮如何在測試序列中管理硬件引用。 管理硬件引用的常用方法有兩種:
- 通過從代碼模塊調用初始化和關閉函數來手動管理硬件引用。
- 使用會話管理器自動管理硬件引用生命周期。
如果使用的是儀器驅動程序,或者使用VISA或IVI驅動程序直接與儀器通信,除非特別需要直接控制硬件會話生命周期,否則請使用會話管理器。 如果使用的是DAQmx等硬件驅動程序,則不能使用會話管理器,必須手動管理引用。
使用TestStand變量手動管理硬件引用
初始化儀器時,將會話引用作為輸出參數傳遞給調用序列,然后將引用存儲在變量中。 然后,可將變量作為輸入傳遞到需要訪問儀器的各個步驟。
包括NI-DAQmx和VISA在內的許多驅動程序以及大多數儀器驅動程序都使用I/O引用數據類型來存儲會話引用。在TestStand中使用LabviewIOControl數據類型來存儲這些引用。
使用LabVIEWIOControl類型的變量在代碼模塊之間傳遞硬件引用,例如DAQ任務引用
在TestStand和代碼模塊之間顯式傳遞儀器句柄時,請將硬件引用存儲在局部變量中。 如果硬件在多個序列中使用,請將句柄作為序列參數傳遞給有需求的每個序列。 避免使用全局變量存儲硬件引用,因為可能難以確保儀器已在使用引用之前完成初始化。
請使用“設置”步驟組初始化硬件,並使用“清理”步驟組關閉硬件引用,具體原因如下:
- 由於清除步驟組總是在執行終止時運行,因此如果用戶終止序列執行,硬件引用仍將關閉。
- 由於設置和清除步驟組會在所選步驟之前和之后執行,因此可交互地執行使用硬件引用的步驟。
使用“設置”和“清理”組初始化和關閉硬件引用
使用會話管理器自動管理硬件引用
對於VISA和IVI儀器句柄,可使用會話管理器自動管理硬件引用。使用會話管理器具有諸多優勢,包括:
- 減少耦合 — 不必在軟件組件之間傳遞儀器句柄變量。每個組件都會指定一個邏輯儀器名稱來獲取會話。
- 減少編程語言障礙 — 用不同語言編寫的代碼模塊可以使用同一會話,而無需傳遞可能難以在各種語言之間轉換的句柄。
- 生命周期控制 — 由於儀器會話是具有引用計數的ActiveX對象,因此可將會話的生命周期與ActiveX引用變量的生命周期相關聯,而無需使用支持ActiveX引用變量的語言顯式關閉儀器。
會話管理器會在創建會話后自動初始化相應句柄,並在針對此會話的最后一個引用釋放后自動關閉相應句柄。代碼模塊和序列會傳遞一個邏輯名稱(例如“DMM1”),用於從會話管理器中獲取會話對象,該對象包含相應的儀器句柄。
使用會話管理器時,請將會話對象存儲在TestStand對象引用變量中。 由於會話生命周期與對象引用變量的生命周期相關聯,因此無論有多少序列代碼模塊和子序列訪問同一會話,每次執行時儀器句柄都會初始化和關閉一次。
在以下示例中,“獲取DMM會話”步驟使用邏輯名稱獲取針對DMM儀器會話對象的引用。此步驟將會話引用存儲在局部變量中,使會話在序列執行期間保持初始化狀態。
借助會話管理器,可使用邏輯名稱引用儀器。 會話管理器VI使用邏輯名稱獲取DMM IO引用
關於如何使用會話管理器的更多信息,請參閱<Program Files>\National Instruments\Shared\Session Manager中的《NI會話管理器幫助》。
上一個示例序列從調用會話管理器的LabVIEW代碼模塊中獲取會話,而不是直接調用會話管理器,因為該示例將LabVIEW適配器配置為在單獨的進程中運行VI。 關於如何使用會話管理器的更多信息,請參閱<Program Files>\National Instruments\Shared\Session Manager中的《NI會話管理器幫助》。
調用硬件驅動程序庫
要與任意類型的硬件通信,需要使用驅動程序庫,該庫提供的一系列功能有助於使用編程語言執行各種任務。 使用驅動程序庫時,通常會調用多個VI或函數來執行單個邏輯操作,例如進行測量或配置觸發器。 創建代碼模塊來實現此功能,而不是直接在TestStand步驟中調用庫函數,此方法具有以下優勢:
- 避免了針對各函數的步驟功能產生的開銷
- 提供了驅動程序調用和TestStand序列之間的抽象層
- 更易於跨測試程序共享實現過程
本文轉載: