两三年前我也遇到过类似的问题。我已将设备驱动程序从 VxWorks 移植到 Integrity。我们只更改了驱动程序的操作系统相关部分,但这是一个安全关键项目,因此所有单元测试、集成测试都重做。我们在单元测试中使用了一个名为 LDRA 测试平台的自动化测试工具。我们 99% 的单元测试都是在使用 Microsoft 编译器的 Windows 机器上完成的。现在我将解释如何做到这一点
首先,当您进行单元测试时,您正在测试软件。当您在测试中包含真实设备时,您也在测试该设备。有时硬件或硬件文档可能存在问题。当你在设计软件的时候,如果你已经清楚地描述了每个功能的行为,那么进行单元测试是很容易的,例如,考虑功能;
readMessageTime(int messageNo, int* time);
//This function calculates the message location, if the location is valid,
//it reads the time information
address=calculateMessageAddr(messageNo);
if(address!=NULL) {
read(address+TIME_OFFSET,time);
return success;
}
else {
return failure;
}
好吧,在这里你只是在测试 readMessageTime 是否正在做它应该做的事情。您不必测试 calculateMessageAddr 是否正在计算正确的结果,或者 read 读取正确的地址。那是其他一些单元测试的责任。所以你要做的是为 calculateMessageAddr 和 read(OS function) 编写存根,并检查它是否调用具有正确参数的函数。如果您不直接从驱动程序访问内存,就是这种情况。抱着这种心态,您可以在没有任何操作系统或设备的情况下测试任何类型的驱动程序代码。
如果您已将设备内存直接映射到您的内存空间,并且设备驱动程序读取和写入设备内存,因为它是它自己的内存,它会变得有点复杂。使用自动化测试工具,现在您必须观察指针的值并根据这些指针的值定义通过/失败标准。如果您正在从内存中读取值,则必须定义预期值。在某些情况下,这可能很难。
还有一个问题,开发人员总是对驱动程序的单元测试感到困惑,例如:
readMessageTime(int messageNo, int* time);
//This function calculates the message location, if the location is valid,
//it does some jobs to make the device ready to read then
//it reads the time information
address=calculateMessageAddr(messageNo);
if(address!=NULL) {
do_smoething(); // Get the device ready to read!
do_something_else() // do some other stuff so you can read the result in 3us.
status=NOT_READY;
while(status==NOT_READY) // mustn't be longer than 3us.
status=read(address+TIME_OFFSET,time);
return success;
} else
{
return failure;
}
这里 do_something 和 do_something_else 在设备上做一些工作以使其准备好读取。开发人员总是问自己“如果设备没有永远准备好并且我的代码在这里出现死锁怎么办”,他们倾向于在设备上测试这种东西。
好吧,您必须信任设备制造商和技术作者。如果他们说设备将在 1-2us 内准备好,您无需担心这一点。如果您的代码在这里失败,您必须将其报告给设备制造商,找到解决此问题的解决方法不是您的工作。你明白我的意思了吗?
我希望这有帮助…。