0

For example, my production code(say it builds to an executable) has

file_a.c (sub_module A)
   int func_a() {
      ....
   }

file_b.c (module B)
   func_b () {
       ...
       ret = func_a();
       ...
   }

For unit test, I am using CppUTest. If I test B with the real code of A, then

  1. I need real implementation of A,
  2. we might not be able to produces all different possible outputs from func_a().
  3. if func_a() calls other module's functions, it is hard to discover/setup all cases deep inside the function call chains.
  4. mabybe this is too extreme, but I can't convince ppl how this approach different from linking all code together and simply testing from main()?

But If I mock func_a() while testing B, then linker will complain multiple definitions once I start testing A since now real implementation will be linked. For this issue, I see two ways around it

  1. create a separate test executable for each file_a.c and file_b.c. But this will produce so many executables as the production grows, and also complications will happen if some "real" and "mock" combination tests is needed.
  2. compile production code as a shared library and link it to the test executable, then use link time interposing to intercept function calls towards the real implementation.

So what is the common practice for such scenarios? I am sure this is a very common scenario for unit testing c code.

Thanks,

wei
  • 6,629
  • 7
  • 40
  • 52
  • I am no expert in testing, but I found [this SO answer](http://stackoverflow.com/a/1410143/1174343) addressing your dependency problem quite interesting. – x squared Aug 19 '15 at 23:20
  • thanks for the link. This is more of an ' internal ' dependency than an 'external' dependency such as logger in the linked answer. For external dependency, mocking is the way to go which I see how it works nicely. – wei Aug 19 '15 at 23:54
  • Trigger all the cases is quite impossible, if you want to fake some result from func_A() without be able to trigger it, you can use `#ifndef`, `#ifdef` and `#define`. On test mode you set TEST, and on func_A you can choose to fake the return. But this can be use just for some corner cases, it is easier to try to set the environment to trigger all cases – Ôrel Aug 20 '15 at 02:41
  • I use 1.) to get around those sometimes-link-production-sometimes-mock issues. If you use CMake (incl. CTest) for building the amount of executable is not an issue; cmake will create them for you and ctest will run them all in a single command. – ollo Sep 03 '15 at 20:28

0 Answers0