Fake Function Framework – Request For Comments!

I have a little micro-framework called fff.h for generating fake functions (mocks) in C.  I have blogged about it in the past, and there have been some exciting changes over the last few weeks that I’d like to share.

Background

The basic premise is that testing a C source file is difficult in idiomatic C because of all the external function calls that are hardwired into the production code.  The way fff.h helps is to make it a one-liner to create fake implementations of these for the purposes of testing.

Now, the basic formula on my last project for testing a C module is like this:

Typical approach to testing legacy C code

This was crude but effective.  What really grated with me though was the amount of repetitive code that had to be written to answer very basic questions.  Was my fake function called? How many times? What parameters were passed in on each occasion? Was the unlock function called before the write function? To answer these questions we ended up writing endless amount of (not very pretty) code like this:

Manual Fake Functions

It seemed to me that it should be possible to write a macro to generate this code.  This would tidy up the test files in terms of readability and would make it easier for my team to make tests.  And that was the genesis of the Fake Function Framework.

The best introduction to the Fake Function Framework is on the fff github site so I won’t rehash that here.

New Developments

I have since moved on to a new project and haven’t thought about fff.h in a wee while.  Through a variety of coincidences it happened that Tore, the architect on my previous project, met James Grenning during a training course and introduced him to fff.h. James played around with fff.h and sent me some great suggestions for cleanup, and how to improve fff.h to produce globally linkable fakes.  At first I thought that this was an unneeded complication for an otherwise simple framework, but James convinced me that reusable fakes had a lot of value.

I set to work on making the generator able to generate the new style fakes.  I don’t know I would have attempted this without having a full regression test suite for the framework.

The way it works is instead of using the usual syntax to create a fake using the FAKE_xxx_FUNCn macros, you create a header file to hold the declarations:

Global Fake example header file

Global Fake example header file

And then create an implementation file for the function definitions:

Global Fake implementation file example

Global Fake implementation file example

Then you can link many test suites against this single object without any problems. Simple!

Breaking Changes

There have been some breaking changes to fff.h to enable these new features, and I have also taken that opportunity to clean up some weaknesses in the previous design.  But since fff.h is just a header file, both will happily exist in your codebase. All you have to do is name the new version of fff.h fff2.h and start using fff2.h in your new tests.

So theses are the basic changes you should know about if you are already familiar with the fake function framework.  Somewhere in the test executable you must define the globals for fff.  Why not put it beside the main function?

Define FFF globals

In the old version of fff.h there was a shortcut for resetting all the fakes in one step.  This is now gone. The reason is that it only worked in C++ using static initializers and the introduction of global fakes were incompatible with this.

Reset Fakes

There has also been some cleanup.  All the fake function framework variables have been moved into a struct to avoid polluting the global namespace.

fff globals now in struct

fff globals now in struct

And the variables for individual fakes are now defined in a struct.

Fake function data now in struct

Acknowledgements

The fake function framework would not exist as it does today without the support of key folks.  Tore Martin Hagen (and his whiteboard), my partner-in-crime in Oslo, was instrumental during the genesis of fff.  Jon Jagger, who during ACCU 2011 helped me teach the preprocessor to count.  And James Grenning, who convinced me the value of global fakes, sent me a prototype Implementation, and showed me how expressive a DSL can be.  Thanks to you all!

Request for comments

I hope you like the new changes, and if you have any feedback or suggestions for further improvements don’t hesitate to leave a comment or contact me via twitter.

Further reading

15 Comments

Filed under fff, quality, software, testing

15 responses to “Fake Function Framework – Request For Comments!

  1. John Lowe

    Hi Mike,
    I’ve started using FFF in a project and am very pleased with the results. The biggest pain point at the moment is the documentation- getting from what is documented in the github site vs whats actually implement in fff3. I’ve figured it all out, but it took awhile to get going with the framework. Overall I really like what your are doing- keep going… (and keep it simple…) (Also, BTW: I never use C++, so I view keeping FFF limited to just C as a good, value added, feature.)

    • meekrosoft

      Hi John, thanks for the feedback, really appreciated! I completely agree about the documentation, I haven’t updated it yet because I wanted to get some feedback first, but I realize now that was backwards thinking. I’ll get on it this weekend. Let me know if you have any more suggestions for improvements.

  2. Hello Mike,
    Attended BITsCon w. James Grenning as speaker and your framework was mentioned. Have since used it and found it very useful! One note though – when using custom fakes returning a value, it’s the FFF fake return value thats being returned. A more logical choice would be to use the return value from the custom fake, giving more control to which values are actually returned? Also, will you be doing a mock like API sometime in the future?

    • meekrosoft

      Hi,
      Great that you find it useful, thanks for posting the comment.

      You are absolutely correct about the custom fakes – they should return the value from the custom fake so this is a bug. I am on vacation at the moment but will post a fix next week.

      I had originally planned some kind of mock-like interface since I found it so useful in c++ but I haven’t spent any time on it so far. If you have any suggestions for a syntax please drop me a line (or even better a pull request).

      Thanks again for the feedback!

      • meekrosoft

        The latest fff now supports returning the value from the custom fake when it is a non-void function. Let me know if there are any issues.
        Cheers,
        Mike

  3. Hello,
    I used fff in a C+ (C++ without STL) project. Work pretty well.
    But today I’m in front of a problem/limitation.
    I would like to fake a template function. Is it possible ? How to do it ?
    Other problem I discovered, don’t find a way to fake a static function inside a class.
    Don’t find a way from the documentation or reading fff.h

    Can be very usefull to do that.

    Maybe you can just give me pointer on how to do implement it

    Sincerely

    Bertrand

    • meekrosoft

      Hi Bertrand,
      Sorry, I don’t have any solution for that. fff is a framework for testing C code, so it doesn’t support templates or class functions.

      For this type of problem I use the googlemock framework – it is very good at mocking C++ classes.

      Regards,
      Mik

      • I use GMock and HippoMock. They manage to mock classes easily. But static function inside class or template function I never manage to do that.
        Will dive into these frameworks details
        Thanks for your answer

  4. Hi Mike, does FFF support faking variable arg funcs, e.g. “void func(int myInt, …)”. If so, whats the notation?

  5. meekrosoft

    Actually, that is how the framework figures out how many arguments there are. For instance, when you define:

    FAKE_VOID_FUNC(foo, int, double)

    Internally that expands to:

    FAKE_VOID_FUNC2(…)

    The trouble is that the fake capture variables are defined at compile time whereas variadic functions don’t know the number of arguments until runtime.

    • Aah ok, I get it. Ok then, in my case I’ll just supply a “manual” stub over the variadic function. Thx for the answer.

      • meekrosoft

        No worries. I have added a todo to add a new macro FAKE_VARIADIC_FUNC that can fake a variadic function (but not capture the variables) just like you suggested. Thanks for the idea!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s