第一次用Tessy给嵌入式C项目做单元测试时,我遇到了各种奇葩的头文件导入问题。记得当时一个简单的#include语句就能让整个测试环境崩溃,那种挫败感至今难忘。后来才发现,Tessy对头文件的处理方式和我们平时开发时不太一样,需要特别注意几个关键点。
最常见的就是"No such file or directory"报错。这个问题我遇到过不下十次,每次都是因为路径设置不对。Tessy在解析头文件时,会严格按照你在工程中设置的搜索路径来查找。如果头文件引用了其他目录下的文件,而你又没把这些目录添加到搜索路径中,就会报错。
举个例子,假设你的工程结构是这样的:
code复制project/
├── src/
│ ├── main.c
│ └── module/
│ ├── module.c
│ └── module.h
└── include/
├── common.h
└── config.h
在Tessy中,你需要把include目录和src/module目录都添加到头文件搜索路径中。我建议使用相对路径而不是绝对路径,这样工程迁移到其他机器上时不会出问题。具体操作是在Tessy的"Environment Settings"里找到"Include Paths",然后添加这两个目录。
另一个常见问题是头文件编码格式。有次我导入一个头文件后,Tessy一直报"null character(s) ignored"警告,折腾了半天才发现是因为头文件是GB2312编码的。Tessy默认使用UTF-8编码,遇到其他编码的文件就会出问题。解决方法很简单,用记事本或VS Code把文件另存为UTF-8格式就行了。
递归导入头文件也是个技术活。当你的工程很大,有几十上百个头文件时,手动一个个导入太麻烦了。Tessy提供了递归导入功能,但用不好容易出问题。我的经验是,先确保所有头文件都在正确的目录结构中,然后用"Add Folder Recursively"功能导入整个目录树。导入后一定要检查Tessy生成的依赖关系图,看看有没有漏掉的头文件。
配置Tessy测试环境时,我踩过不少坑。最让人头疼的就是编译器设置问题。Tessy支持多种编译器,但默认设置可能和你的工程不匹配。比如你的工程用的是GCC,但Tessy默认可能是MSVC,这样编译测试用例时就会出各种奇怪的错误。
检查编译器设置的方法是:
内存模型设置也很重要。嵌入式项目经常使用特定的内存模型,比如small、compact或large。如果Tessy中的内存模型设置和实际工程不一致,测试时就会出现内存访问错误。我建议在"Target Settings"里仔细检查这些参数,最好和工程编译选项保持一致。
中断向量表是另一个容易出问题的地方。有一次我测试一个带中断的模块,Tessy一直报"isr中断向量注册表出错"。后来发现是因为Tessy不支持直接在测试代码中定义中断向量。解决方法是在"Overview->Source->Define"中预先定义好需要用到的中断服务程序,然后在测试用例中引用。
Tessy的TIE(Test Interface Editor)界面经常让人困惑。这里定义了被测函数和外部函数的接口关系。新手常犯的错误是把实际会用到的接口标记为"irrelevant",导致测试时出现"Master signaled error 0x6"这类错误。我的经验是,在TIE中仔细检查每个接口,特别是指针类型的参数,确保它们的设置和实际使用场景一致。
桩函数是单元测试的核心,但在Tessy中设置起来并不简单。我遇到过最典型的问题是"Undefined reference to xxxx"错误,通常是因为忘记给外部函数打桩。
Tessy提供了两种桩函数:普通桩和进阶桩。返回值是void的函数用普通桩就行,而非void返回值的函数需要用进阶桩。打桩时要注意参数传递方式,特别是结构体和指针参数。有次我测试一个带结构体指针参数的函数,因为桩函数没处理好指针解引用,导致测试结果完全不对。
打桩的具体步骤是:
指针参数的处理要特别小心。Tessy默认会把指针参数当作输入参数,但如果函数会修改指针指向的内容,就需要在TIE中把这个参数标记为输出参数。我曾经测试一个链表操作函数,因为没设置输出参数,导致测试完全检测不到链表的变化。
全局变量的处理也很关键。如果被测函数会修改全局变量,记得在测试用例中先初始化这些变量,并在TIE中把它们标记为"used"。否则Tessy可能会优化掉对这些变量的访问,导致测试结果异常。
经过多次实战,我总结出一套Tessy问题排查的方法论。当遇到错误时,首先要看错误信息的完整上下文。Tessy的错误提示有时不太直观,但仔细分析还是能找到线索。
对于编译错误,比如"expected '=', ',', ';', 'asm' or 'attribute' before '{' token",通常是因为语法问题。我遇到的大部分情况是函数声明后面漏了分号,或者宏定义有问题。建议先检查报错位置附近的代码,确认语法是否正确。
链接错误"Undefined reference"相对好解决,要么是忘记打桩,要么是库文件没正确链接。在Tessy的"Linker Settings"中检查库文件路径和名称是否正确。嵌入式项目经常用到特殊库,这些库都要明确告诉Tessy在哪里能找到。
运行时错误最难排查,比如"Master signaled error 0x4"。这类错误通常和TIE设置有关。我的排查步骤是:
头文件顺序问题看似简单,但可能引发各种奇怪错误。Tessy处理头文件的顺序有时和编译器不一样,特别是当有循环依赖时。解决方案是调整头文件包含顺序,或者把公共定义提取到单独的头文件中。我曾经遇到一个案例,只是因为交换了两个头文件的包含顺序,就解决了一个困扰多时的类型定义错误。
最后,当所有方法都无效时,考虑重装Tessy。有次我遇到分析时出现大量乱码的问题,各种尝试都无效,重装后就好了。软件本身可能在某些情况下会出现异常,及时重装能节省大量排查时间。