1 前言
CANoe大家应该都知道和了解,CAN界的软件标杆,有个非常偶然的机会接触到了CANoe中的Test选项卡中的Test Module功能,这个小功能可以让我们定制化测试CAN的测试项目,并且它还可以自动生成测试报告,总之非常好用,都是科技与狠活。接下来就举个例子来介绍一下这个小功能的使用流程。
2 Test Setup配置
打开CANoe,选择Test选项卡,然后点击Test Module中的Test Setup,如下图:
随后就会打开Test Setup for Test Module窗口,右击该窗口空白处,选择New Test Environment新建一个测试环境。
随后在右击新建的测试环境,选择Insert XML Test Module来新建一个测试模块,至于为什么要选择XML呢,因为接下来我使用的是XML语法来写的测试脚本。
新建完测试模块后,这个时候不要着急,先去随便找个位置新建两个测试脚本文件,一个.vxt文件,一个.can文件,文件名称随意,如下:
新建完上述两个文件后,再右击测试模块选择Configuration打开配置窗口,如下:
在Comnon中的Test Script选择之前新建的.vxt文件,如下
在Components中添加之前新建的.can文件,如下
在这里稍微解释一下,.can文件大家应该都知道,就是Vector自己家的CAPL语言脚本文件,我们需要在里面写测试CAPL脚本,而.vxt文件就相当于是一个目录,我们需要在里面定义各种测试项并且将各个测试项与.can文件中测试CAPL脚本链接,然后Test Module运行起来时,就会根据测试项调用CAPL脚本来达到测试目的。
3 .vxt和.can的编写
上面我们已经完成了Test Module的配置,接下来就是最重要的脚本编写了,我们需要完成两个文件的编写,首先双击测试模块打开测试模块窗口,然后就可以点击下方的编辑按钮对.vxt和.can文件进行编辑(当然了也可以使用外部编辑器),如下:
.vxt的格式其实就是XML格式,非常简单。我这里想要测试的是UDS通信,所以里面的测试项都是UDS,简单示例如下:
<?xml version="1.0" encoding="utf-8"?>
<testmodule title="CANoe Test Module" version="1.1" xmlns="http://www.vector-informatik.de/CANoe/TestModule/1.18">
<description>For execution of the test module ensure that no macro is running!</description>
<sut>
<info>
<name>Test Module</name>
<description>Function Integration Test Automation</description>
</info>
</sut>
<engineer>
<info>
<name>ShuwenOu</name>
<description>CSDN Note</description>
</info>
</engineer>
<testgroup title="BasicTest">
<description>This test group verify basic function for SleepWakeup feature.</description>
<capltestcase name="EcuReset" title="EcuReset" ident="TC_Basic_000000"></capltestcase>
<capltestcase name="DefualtSession" title="DefualtSession" ident="TC_Basic_00001"></capltestcase>
<capltestcase name="ExtendSession" title="ExtendSession" ident="TC_Basic_000002"></capltestcase>
</testgroup>
<testgroup title="ManuDIDTest">
<description>This test group verify basic function for Manu DID feature.</description>
<capltestcase name="ReadEcuBootSwRefNumber" title="ReadEcuBootSwRefNumber" ident="TC_Basic_000000"></capltestcase>
<capltestcase name="ReadEcuPartNumber" title="ReadEcuPartNumber" ident="TC_Basic_000001"></capltestcase>
<capltestcase name="ReadSystemSupplierID" title="ReadSystemSupplierID" ident="TC_Basic_000002"></capltestcase>
<capltestcase name="ReadEcuManufactureDate" title="ReadEcuManufactureDate" ident="TC_Basic_000003"></capltestcase>
<capltestcase name="ReadSupplierEcuSN" title="ReadSupplierEcuSN" ident="TC_Basic_000004"></capltestcase>
<capltestcase name="ReadVIN" title="ReadVIN" ident="TC_Basic_000000"></capltestcase>
<capltestcase name="ReadEcuHardwareNumber" title="ReadEcuHardwareNumber" ident="TC_Basic_000005"></capltestcase>
</testgroup>
</testmodule>
在.vxt文件中,最重要的就是需要定义capltestcase name,这个参数是关键,凡是在vxt中的定义的test case,就需要在.can中去实现这个test case脚本,test case脚本的函数名必须与capltestcase name相同,因为两个文件就是通过这来链接的。
在vxt中编写完测试项后,然后就需要在.can文件完成各个测试项的CAPL脚本编写,具体思路就是调用函数发送报文,然后根据回复判断是否正确,然后在脚本中调用TestStepFail报告测试失败,调用TestStepPass报告测试通过。示例如下:
/*@!Encoding:936*/
variables
{
/*ECU Reset*/
DiagRequest EcuReset_HardReset dr_HardReset;
/*session control*/
DiagRequest DiagnosticSessionControl_Default dr_DefaultSession;
DiagRequest DiagnosticSessionControl_Programming dr_ProgSession;
DiagRequest DiagnosticSessionControl_Extended dr_ExtendSession;
/*ReadDataByIdentifier*/
DiagRequest EcuBootSwRefNumber dr_22_F183; //10
DiagRequest EcuPartNumber dr_22_F187; //6
DiagRequest SystemSupplierID dr_22_F18A; //6
DiagRequest EcuManufactureDate dr_22_F18B;//4
DiagRequest SupplierEcuSN dr_22_F18C;//10
DiagRequest VIN dr_22_F190;//17
DiagRequest EcuHardwareNumber dr_22_F191;//6
diagResponse EcuBootSwRefNumber resp_22_F183;
diagResponse EcuPartNumber resp_22_F187;
diagResponse SystemSupplierID resp_22_F18A;
diagResponse EcuManufactureDate resp_22_F18B;
diagResponse SupplierEcuSN resp_22_F18C;
diagResponse VIN resp_22_F190;
diagResponse EcuHardwareNumber resp_22_F191;
int iRespTimeout=500;
byte respdata[100];
}
testcase EcuReset()
{
diagSendRequest(dr_HardReset);
testWaitForTimeout(500);
}
testcase DefualtSession()
{
diagSetTarget("BasicDiagnosticsEcu");
DiagSetSession(dr_DefaultSession);
testWaitForTimeout(100);
}
testcase ExtendSession()
{
diagSetTarget("BasicDiagnosticsEcu");
DiagSetSession(dr_ExtendSession);
testWaitForTimeout(100);
}
testcase ReadEcuBootSwRefNumber()
{
ReadDataByIdentifiter(dr_22_F183, resp_22_F183, 10);
}
testcase ReadEcuPartNumber()
{
ReadDataByIdentifiter(dr_22_F187, resp_22_F187, 6);
}
testcase ReadSystemSupplierID()
{
ReadDataByIdentifiter(dr_22_F18A, resp_22_F18A, 6);
}
testcase ReadEcuManufactureDate()
{
ReadDataByIdentifiter(dr_22_F18B, resp_22_F18B, 4);
}
testcase ReadSupplierEcuSN()
{
ReadDataByIdentifiter(dr_22_F18C, resp_22_F18C, 10);
}
testcase ReadVIN()
{
ReadDataByIdentifiter(dr_22_F190, resp_22_F190, 17);
}
testcase ReadEcuHardwareNumber()
{
ReadDataByIdentifiter(dr_22_F191, resp_22_F191, 6);
}
void DiagSetSession(diagRequest * gReq)
{
long result;
diagSendRequest(gReq);
switch(TestWaitForDiagResponse( gReq, iRespTimeout))
{
case 0:
TestStepFail("Session Chanage", "No answer from ECU!");
break;
case 1:
TestReportWriteDiagResponse(gReq);
if( diagGetLastResponseCode(gReq) == -1)
{
TestStepPass("Session Chanage", "Positive response received!");
}
else
{
TestStepFail("Session Chanage", "Negative response received");
}
break;
default:
TestStepFail("Session Chanage", "Error in TestCase!");
break;
}
}
void ReadDataByIdentifiter(diagRequest *gReq,diagResponse *gResp, int len)
{
long size;
diagSendRequest(gReq);
switch(TestWaitForDiagResponse(gReq, iRespTimeout))
{
case 0:
TestStepFail("Read Data", "No answer from ECU!");
break;
case 1:
TestReportWriteDiagResponse(gReq);
if( diagGetLastResponseCode(gReq) == -1)
{
TestStepPass("Read Data", "Positive response received!");
diagGetLastResponse (gReq, gResp);
size=DiagGetPrimitiveSize(gResp)-3;
if(size!=len)
{
TestStepFail("Read Data", "response length is error");
}
diagGetParameterRaw(gResp,"Data",respdata,len);
}
else
{
TestStepFail("Read Data", "Negative response received");
}
break;
default:
TestStepFail("Read Data", "Error in TestCase!");
break;
}
}
4 运行Test Module
以上的准备工作都准备好之后,随后就是运行Test Module了,在测试模块窗口模块中可以直接点击运行按钮开始测试,运行完之后还可以生成测试报告,如下:
运行结果如下:
生成报告如下(可将报告转换成PDF格式,非常好用方便):