前言
CANoe提供的COM接口使得外部腳本能夠訪問或控制CANoe軟件,從而實現自動化測試任務,而易用且具有豐富生態的Python無疑是一個很好的選擇。本文將介紹CANoe COM基本構成、常用COM對象以及Python腳本調用CANoe COM的方法,在此之前,先介紹一些基本概念。
CANoe COM Server & Python pywin32
COM全稱Component Object Model,是微軟為Windows平台軟件提出的、實現軟件之間互操作的標准。它不會規定軟件的具體實現,而是聲明一種對象模型,使得滿足這種模型的對象之間能交互,這些對象通常被稱為組件(Component)。組件會實現特定的功能,而這些功能以特定的方式提供——即接口(Interface),其他組件通過接口使用它們。另外,組件需要經過注冊(Registry),才能被其他軟件發現和使用。注冊后的組件向其他軟件提供服務,因此組件將作為服務端(COM Server),其他想要使用服務的作為客戶端(COM Client)。
在安裝完成CANoe軟件后,CANoe已經在Windows組件服務管理器中注冊了CANoe COM Server,如果需要重新注冊,可以在安裝目錄下(默認為C:\Program Files\Vector CANoe 14)的Exec64文件夾中找到RegisterComponents.exe,運行即手動注冊。
Python pywin32 package,它提供了許多Python擴展以調用Windows API,其中就包括COM組件,由於Python腳本將使用CANoe COM提供的服務,因此Python腳本將作為COM Client,在pywin32包中就對應win32com.client模塊,所以后續的Python腳本都要導入win32com.client模塊。
了解以上的概念后,下面就看看本文的主要內容。
COM Object Hierarchy
在CANoe中,各個功能模塊按照一定的層級組織在一起構成整個CANoe軟件。與這些功能模塊直接相關的COM組件同樣也是按照相應的層級組織的,這就形成了COM Object Hierarchy:
如上圖所示,圖的最左側是Application對象,是訪問其他對象的入口;通過它可以訪問Configuration對象,而通過Configuration對象才能訪問CommunicationSetup對象;要想設置CommunicationSetup,就需要按照Application->Configuration->CommunicationSetup從左向右的層級順序,找到相應的屬性或是方法,從而實現設置。
Type Library
了解COM Object Hierarchy能幫助快速找到所需功能,但是不能知道實現所需功能對象的繼承關系,為此還需要了解CANoe Type Library。在CANoe軟件安裝目錄下(默認為C:\Program Files\Vector CANoe 14)的Exec32\COMdev目錄中包含了注冊COM所用的類型庫,如下圖所示CANoe.h頭文件:
在CANoe.h頭文件中包含所有CANoe COM對象的接口定義,比如ITestConfiguration接口:
而如果想要設置TestConfigurationSettings對象,從COM Object Hierarchy得知需要從TestConfiguration對象訪問:
但是在Type Library中Configuration對象有多個ITestConfiguration接口,比如:
可以看到,ITestConfiguration2繼承自ITestConfiguration,在它的基礎上又擴充了許多方法,比如獲取TestConfigurationSettings對象的方法get_Settings就在其中。
也就是說,要通過實現了ITestConfiguration2接口的TestConfiguration對象的get_Settings方法,才能獲得TestConfigurationSettings對象。
為此,通過win32com.client模塊中的CastTo方法,能將TestConfiguration轉換成基於ITestConfiguration2接口的對象。
COM Object
COM Object Hierarchy中有許多COM對象,短時間內掌握所有COM對象是不現實的,下面僅針對常用的、與自動化測試緊密相關的COM對象做介紹。
Application
使用Python控制CANoe,首先要獲取關聯整個CANoe進程的COM對象,也就是Application對象。通過Dispatch方法就可以獲得關聯到當前CANoe進程的COM對象,如果當前並沒有CANoe進程,則會啟動一個CANoe進程;而如果想要另外獲得一個CANoe進程,則可以使用DispatchEx方法。
下面是獲取Application對象的代碼示例:
在以上示例中,CANoe各部分功能封裝在CANoe類中,在CANoe類初始化時,把獲得的Application對象保存在CANoe類的App成員中,這樣在CANoe類的其他方法中,就可以通過使用App成員來訪問Application對象。
有了Application對象,才能訪問CANoe工程的各個功能模塊,比如打開CANoe工程:
而在open_canoe_config方法中,使用Application對象的Open方法打開特定的CANoe工程,具體Application對象的接口定義(這里僅展示IApplication的部分方法,其他方法以及后續擴展的方法並未展示)如下:
Measurement
要想控制CANoe啟動測量,就需要獲取Measurement對象,對於上面獲得的Application對象,使用self.App.Measurement獲得。
在Measurement對象的接口定義中,可以看到Start方法,使用Measurement.Start()就能啟動CANoe測量。
下面是啟動CANoe測量的代碼示例:
System Variables
系統變量作為CANoe中重要的部分,要想獲取任意系統變量的值,就要獲取對應系統變量的對象。
從COM Object Hierarchy中可以看到,系統變量Variable對象是按照Application->System->Namespaces->Namespace->Variables->Variable順序訪問的。
其中Namespaces和Variables分別表示Namespace和Variable對象的集合,因此可以使用Namespace名稱(Variable名稱)作為索引,從Namespaces(Variables)中獲得相應的Namespace(Variable)對象。
另外,在Variable對象的接口定義中,可以看到get_Value和put_Value方法,而Python將這兩種方法轉變成了Value屬性,也就是說可以直接對Variable.Value取值或賦值。
下面是獲得系統變量值的代碼示例:
在以上示例中,添加了簡單的異常處理可以暫且不看,僅考察if分支中的語句。首先,使用self.App.System.Namespaces獲得Namespaces對象,將其保存在system_namespaces變量中;然后使用剛保存的變量,以ns_name作為索引獲得Namespace對象並保存在sys_namespace變量中;再通過sysvar_name索引獲得Variable對象sys_variable,最后返回sys_variable.Value屬性值。
Test Configuration & Test Unit
與自動化測試 (這里僅介紹Test Configuration配置,即與vTESTstudio軟件聯合使用的自動化測試)直接相關的就是Test Configuration以及Test Unit,前者對應整個測試執行的設置,后者包含具體執行的測試用例。在COM Object Hierarchy中可以看到,它們的層級構成為Application->Configuration->TestConfigurations->TestConfiguration->TestUnits->TestUnit:
其中,TestConfigurations與TestUnits跟前文類似,表示TestConfiguration和TestUnit的集合,同樣可以通過索引訪問。除了可以使用相應TestConfiguration(TestUnit)名稱作為索引以外,還能使用數字索引,但是切記索引起始為1。對於僅有一個TestConfiguration的情況,僅需要TestConfigurations(1)來獲得唯一的TestConfiguration對象。
當CANoe工程中還沒有TestConfiguration或者TestUnit時,就需要先添加。查看它們的接口定義:
可以看到Add方法能添加相應的對象,對於TestConfigurations.Add()不需要其他參數,即可添加並獲得新的TestConfiguration對象;而TestUnits.Add()需要提供所要添加的TestUnit的絕對路徑,同樣可以獲得對應的TestUnit對象。另外值得注意的是,TestUnits的Add方法是在ITestUnits2接口上擴展的,所以要通過前文所述的CastTo方法將TestUnits (默認為基於ITestUnits接口)轉換成基於ITestUnits2的對象。
下面請看加載測試配置的代碼示例:
在以上示例中,首先通過TestConfigurations.Add()方法新添加一個TestConfiguration對象,並把它保存為類成員self.test_config;之后使用CastTo方法將新添加的TestConfiguration中的TestUnits對象轉換成基於ITestUnits2接口的TestUnits對象(默認為ITestUnits接口);最后使用轉換后的TestUnits對象的Add方法,添加test_unit_path路徑下的測試單元(.vtuexe文件)。
加載測試配置后,還需要啟動測試執行,查看ITestConfiguration接口定義,可以發現Start方法:
下面是執行測試的代碼示例(這里使用了之前保存的類成員self.test_config):
執行完測試后,需要獲得測試結果,可以通過CANoe軟件為Test Configuration創建的系統變量VerdictSummary查看:
下面是獲得測試結果的代碼示例:
這里get_test_result方法有一個帶有默認值的參數test_config_name表示實際執行測試的TestConfiguration名稱,它的默認值是Test_Configuration_1,如果沒有修改過就不需要提供參數,否則需要提供;get_test_result返回保存在VerdictSummary中的測試結果,其數據類型是整型,需要在接口定義中查詢具體數值對應的結果:
Test demo
聯合使用上述COM對象就能夠實現自動化測試,下面展示完整的代碼示例:
基於Canoe類,就可以通過實例化Canoe類,調用實例對象的方法來實現自動化測試,下面是簡單的代碼示例:
首先,實例化Canoe類,將實例化后的對象保存在canoe變量中;之后定義了canoePrj變量表示CANoe工程的絕對路徑,然后使用open_canoe_config方法打開此工程;接着定義testPrj變量表示測試單元可執行文件的絕對路徑,使用load_test_config方法加載測試單元;然后使用start_canoe方法啟動CANoe測量,等待2s后,使用run_test_config方法執行測試,等待10s后測試停止;最后打印通過get_test_result方法獲得的測試結果。
這里使用了Vector CANoe 14自帶的PythonBasicEmpty.cfg demo工程作為測試工程,下面是關於此demo的介紹文檔:
這個demo中有更豐富的COM對象的應用、更完善的信息提示,比如對測試啟動、停止等事件的控制,對CANoe運行狀態的打印,在此不再贅述。
最后,運行以上腳本后,可以獲得自動化測試結果,對照前文的VerdictState,可以確定測試通過:
總結
本文介紹了使用Python訪問CANoe COM以實現自動化測試的基本方法,通過幾個常用的COM對象及方法,構建了簡單的自動化測試示例工程。對於更復雜的工程,同樣可以根據基本方法,靈活運用COM以滿足測試需求。進一步,可以將CANoe COM封裝成Python庫,利用可復用性高效地完成針對不同需求的自動化測試。
CANoe是德國Vector公司出的一款總線開發環境,是網絡和ECU開發、測試和分析的專業工具,支持從需求分析到系統實現的整個系統開發過程;其豐富的功能和配置選項被OEM和供應商的網絡設計工程師、開發工程師和測試工程師所廣泛使用。
北匯信息作為Vector中國的合作伙伴,不僅提供相應的工具和技術支持服務及培訓,還針對不同的應用提供相應的解決方案,助力中國客戶的研發效率提升。
注:本文部分圖片來源於Vector。