5

I am new to test-driven development, but I'm loving it. There is, however, a main problem that prevents me from using it effectively.

I work for embedded medical applications, plain C, with safety issues.

Suppose you have module A that has a function A_function() that I want to test. This function call a function B_function, implemented in module B. I want to decouple the module so, as James Grenning teaches, I create a Mock module B that implements a mock version of B_function.

However the day comes when I have to implement module B with the real version of B_function. Of course the two B_function can not live in the same executable, so I don't know how to have a unique "launcher" to test both modules.

James Grenning way out is to replace, in module A, the call to B_function with a function pointer that can have the value of the mock or the real function according to the need. However I work in a team, and I can not justify this decision that would make no sense if it were not for the test, and no one asked me explicitly to use test-driven approach.

Maybe the only way out is to generate different a executable for each module.

Any smarter solution? Thank you

5
  • Why do you need a single executable to test both functions?
    – Mat
    Commented Sep 2, 2012 at 8:39
  • The test suite I use (CppUTest) supports many "test suites", but generates only one executable. My fear in having many executables is that I will not run all of them every time, and I will discover that one test is broken too late.Maybe I only need a more powerful IDE that supports multiple project active as one and runs more executables with one command.Which one do you use?
    – Angelo
    Commented Sep 2, 2012 at 10:42
  • 1
    Running all of your tests every time should be a no-brainer. Script it, make sure it works right and run that instead of running the test tool directly.
    – Blrfl
    Commented Sep 2, 2012 at 13:34
  • agree, I'll go that way.
    – Angelo
    Commented Sep 3, 2012 at 6:09
  • I need a single executable to test as downloading to the embedded device takes a minimum of 3 minutes, which includes physically inserting and removing the programming dongle. (Our current test scripts utilize the GetATechnitianToDoIt() function)
    – Philip
    Commented Sep 5, 2012 at 16:48

1 Answer 1

1

Based upon what you've described, I would suggest that's a horrible reason to use a function pointer. It will jack up your ability to debug, analyze core dumps, and it will complicate future development / maintenance. Function pointers have their place, but this isn't one of them.

I think you're approaching the testing from the wrong point of view. A_func depends upon B_func's presence for it to operate. Therefore, you can't truly test A without having the actual implementation of B in place. Putting a mock B_func in place will only generate a limited set of tests for A_func. By definition, you can't fully exercise A_func without the real B_func in place.

Presuming you're not dealing with a cascading series of module inclusions, the appropriate test suite would have some tests to exercise B_func and then some additional tests for exercising the variations that A_func can go through. It's understood that you may have some redundancy between the tests for B_func and the indirect testing of B_func from A_func, but it's generally not a big deal.

4
  • I agree that's a bad use for function pointers, but I don't agree that I can't test a function without the implementation of the functions it depends on. In embedded SW, "B_func" might be a function that accesses the HW that maybe is not available, while "A_func" might simply be a business function that manages data, and can be tested with fake values. By mocking B_func I don't limit the test on A_func but, on the contrary, I can let B_func return any value, even the ones the are hardly ever returned.
    – Angelo
    Commented Sep 3, 2012 at 6:03
  • @Angelo - that is true so long as B_func has a contract in place as to what it is guaranteed to produce. If the root issue is missing X (hardware) to drive B_func, and B_func is well specified on its returns, then you could use some pre-compiler conditional flags to stub in the test harness you need. It makes the code a little uglier, but is far more tolerable to the rest of the team.
    – user53019
    Commented Sep 3, 2012 at 12:37
  • 1
    What if you give it a hip name like Dependency Injection? Is it a good idea then?
    – Philip
    Commented Sep 5, 2012 at 16:41
  • @Philip - only if you don't intend to try and debug core dumps.... :-)
    – user53019
    Commented Sep 5, 2012 at 17:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.