Unit-testing – Unit Testing Module-Internal Functions

ctestingunit testing

I'm writing a simple whitebox unit testing suite for a project I'm working on in C. The project is broken into modules (each has a .c file with an associated .h file), and all modules are compiled together into one .so file.

Obviously, the .h file for each module contains function prototypes for any function that is meant to be visible to the other modules, but does not contain prototypes for internal or helper functions.

My test suite is a collection of .c files in a separate directory. Each .c file is responsible for testing a specific module, plus a master file which executes all the tests. All of these files are compiled into one executable. Currently this binary is linked to the .so binary of the project, and I'm #includeing the project's .h files in the individual module testing files as appropriate. This allows me to test all of the "public" functions.

I would also like to directly test some of the internal and helper functions. I can think of a few ways to go about this.

  1. Go ahead and make all of a module's functions defined in that module's header file. I don't want to do this because it seems like bad practice.
  2. Create a second collection of .h files which contain the prototypes for all the internal/helper functions, and include these in the appropriate testing files. I'm hesitant to do this because it seems like a lot of work to maintain.
  3. #include the module's .c file directly. This would be easy to maintain, but it would make me feel so dirty inside.

Which (if any) of these techniques are the best way to go about this?

Best Answer

Unit tests are supposed to be for external functions only.

Nevertheless, if you have a lot of "internal code", it should be tested too right? So how?

Make smaller functions, separated from you code (another .c and .h), and use those functions as a library that can be unit tested. Then you should be able to test those functions that are used by the internal ones from the external API without any problem. What you cannot test is how you use those functions. But the behavior of those functions should cause something which can be tested on the external functions, otherwise, why are they there?

That is easy to maintain. A pain to do it if you have a lot of code already written, but doable.