This is a fairly simple (if tedious) extension module written in C, including errors for many Python / C APIs such as PyArg_ParseTuple. For example, the idiomatic way to run a C function that implements a Python function or method is as follows:
if (!PyArg_ParseTuple(args, "someformat:function_name")) { return NULL; }
The success case of this can be verified by the module by calling a function with the correct number and type of arguments. Failures can also be tested by calling a function with the first incorrect number of arguments and then the correct number of arguments, but passing values โโof the wrong type. This leads to full coverage of C code branch testing.
However, it is unclear how to use negative paths for other Python / C APIs. The idiomatic way to start module initialization in extension C is as follows:
if (PyType_Ready(&Some_Extension_Structure) < 0) { return 0; }
How can PyType_Ready
fail? Similarly, the C function often uses an API to assign a new instance of an extension type, such as PyObject_New
:
self = PyObject_New(Some_Structure, &Some_Extension_Structure); if (self == NULL) { return NULL; }
How does one unit test this negative case (especially considering PyObject_New
is probably used many times during the execution of one unit test method)?
It seems possible to create a common solution based on dynamic linker tricks, such as LD_PRELOAD
, to provide fakes for these C APIs, which can be aimed at unsuccessful attempts in the right ways at the right time. The cost of building such a system seems a bit out of reach. Has anyone else done this and made the result available?
Are there any Python / C tricks that could facilitate this testing?
Should I think of other lines entirely?