Mocking support in CppUTest

I've added mocking support to the CppUTest C/C++ unit testing framework. Id like to clarify why I've added it, why I've added it the way it is and how you can use it.

Why mocking?

I won't cover why mocking and state-based TDD vs interaction-based TDD. There are other wonderful descriptions of this. For example:

When working in C++, I mainly used state-based TDD with sometimes handcrafted mocks. I've stayed away from most mocking frameworks as I didn't like them much (though google mock is quite nice). Neither do I prefer interaction based over state based or the other way around, both are tools and are useful in different situations.

Why CppUTest mocking?

I always want to keep CppuTest small and clean. We (mainly me and James Grenning) have quite strict design guidelines for CppUTest. No major C++ features ought to be used, such as rtti, expection handling, templates, and STL. The main reason is that we work a lot for embedded software and embedded C++ compilers aren't that good. A smaller C++ set leads to greater and easier portability. To keep it simple, I've never really wanted to add mock support. But recently I've changed my mind and added it to the CppuTestExt (extensions) library.

Why did I changed my mind? Well... when working on a piece of code... I figured that an interaction-based approach would be best to test-drive it (lots of interaction, few state). I started to build manual mocks, as I always do in that situation, and was getting annoyed. Why was I getting annoyed? Exactly because I always do.... the same thing... and was getting bored by that. Therefore I decided to extract the things I do manually into mocking support.

But why not use one of the existing mocking frameworks like googlemock, mockpp, MockItNow, CMock? Important, because we don't want to re-invent the wheel again. My reasons for not using any of these:

  • Need to use the same limited set of C++ as CppUTest
  • No code generation
  • No or very few macros
  • Wanted to use it in CppUTest but don't want a dependency to other frameworks

All existing frameworks failed to meet the criteria (yeah, I know, the last criteria is unfair and per definition all frameworks will not meet that).

What were my major design criteria? Simplicity. Also instead of mocking automatically, I wanted to make manual mocking easier. Manual mocking won't go away in C++ and being able to do that with nearly the same ease as automatic mock generation would be a Good Thing. Also, the syntax needs to be easy and it ought to be possible to use the same mocking in C and C++.

In other words, the mocking support needs to be non-controlling and non-invasive.

There we have it. That's why I've build it... but how does it work?

How does it work?

The only class you really need to use it is MockSupport (in CppUTestExt/MockSupport.h). There are a lot more classes under the hood, but usually you don't need to use these (except for the MockFunctionCall interface).

Usually I just create one of the MockSupport and dump it in global static namespace in my test, something like:

MockSupport mock;

(this is safe as the constructor/destructor don't do a thing)

In a test, if you except a call to a certain function, you do:

mock.expectOneCall("functionName");

Then at the end of your test, you need to check that this happened with:

mock.checkExpectations();

Thats basically all you need :) Oh, of course, you still need to make the actual call :P You can do this by putting a call to mock.actualCall inside the manual mock, like:

mock.actualCall("functionName");

(yes, you still have to create a manual mock! That's the whole point :) Yes, you can let the manual mock do whatever you want it to do still too.

What about parameters?

How do we deal with parameters? Simple. In our expect call you write:

mock.expectOneCall("functionName").withParameter("parameterName", 10);

Now the mocking support expects one parameter of value 10. In the actual call you put:

mock.actualCall("functionName").withParameter("parameterName", parameter);

You can pass however many parameters, for example:

mock.expectOneCall("functionName").withParameter("p1", 1).withParameter("p2", 2);

etc etc.

What about different types?

Also, same and easy. You add to the test:

mock.expectOneCall("functionName").withParameterOfType("typeName", "parameterName", objectPtr);

And, you probably already guess the actual call:

mock.actualCall("functionName").withParameterOfType("typeName", "parameterName", paraPtr);

The only problem is how to compare these types. For that, you'll need to create and install a Comparator. How? For example:

class MyTypeComparator : public MockParameterComparator
{
public:
  virtual bool isEqual(void* object1, void* object2)
  {
     return ((MyType*)object1)->field == ((MyType*)object2)->field;
  }
  virtual SimpleString valueToString(void* object)
   {
     return StringFrom(((MyType*)object)->field);
  }
};

Then you create one and install it like:

mock.installComparator("TypeName", myTypeComaprator);

That's it for now. This covers for most of my own mocking needs, so I stopped. We want to keep things simple and clear, and this is simple and clean.

You want to have more examples? I added an example to the CppUTest/Examples. You can find it here

How to use it?

Right now, its on the trunk. So you need to grab the trunk. Its not in the zipped releases yet.

Also its part of CppUTest extensions. You can make them with:

make extensions

It will produce a library at:

lib/libCppUTestExt.a

What next?

The main functionality I wanted is there. I don't want to make it too complex, but gradually add some more. My current wishlist for the next weeks is:

  • Support for return values
  • Support for checking the right object is called
  • A C interface
  • Support for comparators that aren't just for types (like Matchers)

With those, I think the main mocking functionality I use is implemented.

I'd love feedback and bug reports (of course, there aren't any bugs :P)

Read more

Scrum master ทำแค่เนี๊ยะ

Scrum master ทำแค่เนี๊ยะ

เวลามีคนถามว่า Scrum master ทำอะไร แล้วผมตอบว่าทำให้ Scrum เวิร์คสำหรับทั้งองค์กร ซึ่ง โฟกัสหลัก ๆ 4 อย่างก็จะอยู่ที่ Product owner, ทีม, engineering practices และ องค์กร บางครั้งที่ผมจะได้ยินเสียงตอบกลับมาเบา ๆ ว่า “แค่เนี๊ยะ?” ในฐานะ

By Chokchai
how to สร้าง Knowledge Management

how to สร้าง Knowledge Management

ตอนเรียน Large Scale Scrum กับ Jurgen de Smet สิ่งหนึ่งที่ผมได้เรียนรู้ คือ ปัจจัยสำคัญหนึ่งที่ทำให้องค์กรหนึ่ง ๆ จะเร็วขึ้นได้ คือ จะต้องเรียนรู้ไปพร้อม ๆ กันได้ ซึ่งถ้าอยากทำแบบนั้นได้ก็จะต้อง share ownership

By Chokchai
โลกการเขียนโค้ด ตอน ซามูไรกับสปาตั้น

โลกการเขียนโค้ด ตอน ซามูไรกับสปาตั้น

ซามูไรที่ได้รับความไว้วางใจให้แก้ core logic จะมีสัญชาตญาณซามูไร คือแก้ตรงนี้ จับยามสามตาแล้วรู้เลยว่าจะไประเบิดตรงโน้น แล้ววิ่งไปสกัดบั๊กไว้ก่อนความเสียหายจะเกิด (ถ้าเป็นในหนัง ตอนนี้เป็นบทที่บั๊กร้องว่า “มืงรู้ได้ไง?!” :D) หลังจากที

By Chokchai
ประสบการณ์ TDD

ประสบการณ์ TDD

มันมีบางชั่วขณะ ที่ผมอินกับ Test-Driven Development (TDD) มาก จนอยากจะแนะนำทักษะนี้ให้คนเขียนโค้ดทั่วโลกที่สนใจเลย ผมคิดว่า ทักษะนี้มีผลเยอะมาก ๆ กับความรู้ความชำนาญในการเขียนโค้ดของผมทุกวันนี้ แต่ที่ผมไม่เคยอธิบายเป็นคำพูดออกมาได้คือ ทำไมนะ? เมื่อเช้าตอนกำลังอ่านเกี

By Chokchai