tags:

views:

642

answers:

7

As applying unit-test to some C code, we run into a problem that some static function can not be called at the test file, without modifying the source code. Is there any simple or reasonable way to overcome this problem?

+2  A: 

You could add a non-static function to call the static function, then call the non-static function.

static int foo ()
{
   return 3;
}

#ifdef UNIT_TEST
int test_foo ()
{
  if (foo () == 3)
    return 0;

  return 1;
}
#endif
Paul Beckingham
That modifies the source, doesn't it?
Jonathan Leffler
Yes, it modifies the source, but doesn't remove the "static" from foo. Otherwise, the answer is pretty much that you can't call a static from the outside. I took a liberty.
Paul Beckingham
+4  A: 

I have a test harness. In dire cases - like trying to test a static function, I use:

#include "code_under_test.c"
...test framework...

That is, I include the whole of the file containing the function under test in the test harness. It is a last resort - but it works.

Jonathan Leffler
I think this should work without any impact.
Kevin Yu
+2  A: 

No - you cannot directly test a static function without modifying the source at least a little (that is the definition of static in C - that it cannot be called from a function in a different file).

You could create a separate function within the test file that just calls the static function?

For example:

//Your fn to test
static int foo(int bar)
{
  int retVal;
  //do something
  return retVal;
}

//Wrapper fn
int test_foo(int bar)
{
  return foo(bar);
}

We usually don't test our static functions directly, but rather ensure that the logic they perform is adequately tested by different tests of the calling function.

Jess
+1  A: 

Can you give more information as to why you can't call the function?

Is it not available because it's private to a .c file? If so, you're best bet is to use conditional compilation that allows for access to the function in order to allow for other compilation units to access it. For example

SomeHeaderSomewher.h

#if UNIT_TEST
#define unit_static 
#else
#define unit_static static
#endif

Foo.h

#if UNIT_TEST
void some_method
#endif

Foo.cpp

unit_static void some_method() ...
JaredPar
Which part of a static function are you misunderstanding? What does static mean other than private to a file?
Jonathan Leffler
@Jonathan, not misunderstanding, just left off part of the answer.
JaredPar
+3  A: 

For unit tests, we actually have the test code within the source file itself and we conditionally compile it in when testing. This gives the unit tests full access to all functions and file-level variables (static or otherwise).

The unit tests themselves are not static - this allows us to call the unit tests from a single super-test program which unit tests all compilation units.

When we ship the code, we conditionally compile out the unit tests but this isn't actually necessary (if you want to be certain you're shipping exactly the same code you tested).

We've always found it invaluable to have the unit tests in the same place as the code you're testing since it makes it more obvious that you need to update the tests if and when the code changes.

paxdiablo
I do that when the unit test is small enough to fit. When the unit tests become bigger than the source under test, I resort to separate test programs, which can either link with the object (when only using the external dependencies) or use the trick in my answer when playing with static functions.
Jonathan Leffler
+2  A: 

static functions are essentially helper functions to the public (i.e. exposed) functions. So IMO, your unit tests should call the public interface with inputs that exercise all the paths in the static function.

The output (return values / side effects) of the public function should be used to test the effect of the static.

This means you need to have appropriate stubs to 'catch' these side effects. (e.g. if a function calls file IO, you need to provide stubs to override these file IO lib functions). The best way to do this by making each test suite a seperate project/executable and avoid linking to any external lib functions. You can mock even C functions, but it's not worth the effort.

Anyway, this is the approach I've used so far and it works for me. Good luck

Dushara
A: 

Forgive me for posting a year after the last activity but this topic is exactly what I'm wresting with right now and I'm hoping to get an opinion/feedback...

Can't you use the preprocessor to #define out the word "static"? (e.g. gcc -Wall -Dstatic= *.c) It would change the accessibility of the static functions/variables, but for unit testing, is that really an issue?

miller