单元测试 C 生成 python 代码
Unit test C-generating python code
我有一个项目涉及一些(相当简单的)C 代码生成作为构建系统的一部分。本质上,我有一些与项目(嵌入式 C)相关的版本信息,我想在我的二进制文件中公开这些信息,以便我可以轻松确定为特定设备编程的固件版本以进行调试。
我正在编写一些简单的 python 工具来执行此操作,并且我想确保它们已经过全面测试。总的来说,这相当简单,但我不确定代码生成部分的最佳策略是什么。本质上,我想确保生成的文件都:
- 语法正确
- 包含必要的信息
第二,我可以(我相信)通过正则表达式匹配达到合理的程度。然而,第一个任务是一项更大的任务。我可能可以使用 pycparser 之类的东西并检查生成的 AST 来实现这两个目标,但这似乎是一个不必要的重量级解决方案。
编辑:我的构建层次结构的数据流图
感谢您的图表!由于您没有测试覆盖率,如果是我,我只会编译生成的 C 代码并查看它是否有效:)。你没有提到你的工具链,但在类 Unix 环境中,gcc <whatever build flags> -c generated-file.c || echo 'Oops!'
应该足够了。
现在,生成的代码可能不是独立的编译单元。没问题:写一个垫片。例子 shim.c
:
#include <stdio.h>
#include "generated-file.c"
main() {
printf("%s\n", GENERATED_VERSION); //or whatever is in generated-file.c
}
然后gcc -o shim shim.c && diff <(./shim) "name of a file holding the expected output" || echo 'Oops!'
应该给你一个基本的测试。 (<()
是 bash process substitution。)保存预期结果的文件可能已经在您的 git 存储库中,或者您可以使用 Python 将其写入磁盘某处的例程。
编辑 2 即使您的实际工具链不适合自动化,这种方法也能奏效。要测试代码的语法有效性,您可以使用 gcc
,即使您为目标处理器使用不同的编译器也是如此。例如,使用 gcc -ansi
编译将禁用许多 GNU 扩展,这意味着使用 gcc -ansi
编译的代码比使用完整的 GNU 扩展编译的代码更有可能在另一个编译器上编译gcc
。请参阅 "C Dialect Options" for all the different flavors you can use (ditto C++ 上的 gcc 页面。
Edit顺便说一句,这与GNU autoconf使用的方法相同:将一个小的测试程序写入磁盘(autoconf称之为conftest.c
),编译它,看看是否编译成功。测试程序(最好)是测试一切是否正常所必需的最低限度。根据您的 Python 的复杂程度,您可能希望使用相应的不同填充程序测试生成代码的几个不同方面。
我有一个项目涉及一些(相当简单的)C 代码生成作为构建系统的一部分。本质上,我有一些与项目(嵌入式 C)相关的版本信息,我想在我的二进制文件中公开这些信息,以便我可以轻松确定为特定设备编程的固件版本以进行调试。
我正在编写一些简单的 python 工具来执行此操作,并且我想确保它们已经过全面测试。总的来说,这相当简单,但我不确定代码生成部分的最佳策略是什么。本质上,我想确保生成的文件都:
- 语法正确
- 包含必要的信息
第二,我可以(我相信)通过正则表达式匹配达到合理的程度。然而,第一个任务是一项更大的任务。我可能可以使用 pycparser 之类的东西并检查生成的 AST 来实现这两个目标,但这似乎是一个不必要的重量级解决方案。
编辑:我的构建层次结构的数据流图
感谢您的图表!由于您没有测试覆盖率,如果是我,我只会编译生成的 C 代码并查看它是否有效:)。你没有提到你的工具链,但在类 Unix 环境中,gcc <whatever build flags> -c generated-file.c || echo 'Oops!'
应该足够了。
现在,生成的代码可能不是独立的编译单元。没问题:写一个垫片。例子 shim.c
:
#include <stdio.h>
#include "generated-file.c"
main() {
printf("%s\n", GENERATED_VERSION); //or whatever is in generated-file.c
}
然后gcc -o shim shim.c && diff <(./shim) "name of a file holding the expected output" || echo 'Oops!'
应该给你一个基本的测试。 (<()
是 bash process substitution。)保存预期结果的文件可能已经在您的 git 存储库中,或者您可以使用 Python 将其写入磁盘某处的例程。
编辑 2 即使您的实际工具链不适合自动化,这种方法也能奏效。要测试代码的语法有效性,您可以使用 gcc
,即使您为目标处理器使用不同的编译器也是如此。例如,使用 gcc -ansi
编译将禁用许多 GNU 扩展,这意味着使用 gcc -ansi
编译的代码比使用完整的 GNU 扩展编译的代码更有可能在另一个编译器上编译gcc
。请参阅 "C Dialect Options" for all the different flavors you can use (ditto C++ 上的 gcc 页面。
Edit顺便说一句,这与GNU autoconf使用的方法相同:将一个小的测试程序写入磁盘(autoconf称之为conftest.c
),编译它,看看是否编译成功。测试程序(最好)是测试一切是否正常所必需的最低限度。根据您的 Python 的复杂程度,您可能希望使用相应的不同填充程序测试生成代码的几个不同方面。