对用C编写的Python扩展模块进行单元测试相当简单(如果繁琐的话),包括许多Python/C API的错误情况,比如PyArg_ParseTuple。例如,启动实现Python函数或方法的C函数的惯用方式如下所示:
if (!PyArg_ParseTuple(args, "someformat:function_name")) {
return NULL;
}
这种情况的成功案例可以通过使用正确的参数数量和类型调用函数来进行单元测试。还可以通过调用函数来测试失败情况,首先使用错误数量的参数,然后使用正确数量的参数,但传递错误类型的值。这导致了对C代码的完整分支测试覆盖。
但是,对于其他Python/C API,还不清楚如何使用负路径。在C扩展中开始模块初始化的惯用方法如下:
if (PyType_Ready(&Some_Extension_Structure) < 0) {
return 0;
}
如何才能使PyType_Ready
失败?类似地,用于分配扩展类型的新实例的C函数经常使用像PyObject_New
这样的API
self = PyObject_New(Some_Structure, &Some_Extension_Structure);
if (self == NULL) {
return NULL;
}
如何对这种负面情况进行单元测试(特别是考虑到在执行单个单元测试方法的过程中可能会多次使用PyObject_New
)?
似乎可以构建一个通用的解决方案,依靠诸如LD_PRELOAD
之类的动态链接器技巧来提供这些C API的伪代码,这些伪代码可以在正确的时间以正确的方式失败。然而,构建这样一个系统的成本似乎有点遥不可及。有没有其他人已经这么做了,并且让结果可用?
有没有特定于Python/C的技巧可以简化这项测试?
我应该完全沿着其他路线思考吗?
发布于 2012-02-14 00:50:54
这是测试替身的一个明显的例子(例如,模拟)。由于Python C API不提供任何用于伪造内存不足情况的工具,因此您必须自己动手。
创建您自己的提供PyType_Ready
和PyObject_New
的层。让它们传递给C API函数,除非某些控件(可能是环境变量)指示它们不要这样做。它们可以造成任何你想要的混乱,并测试你的代码的反应。
https://stackoverflow.com/questions/9264299
复制相似问题