Re: Generating sequence diagrams from unit tests

Hello everybody,

I’ve been doing some progress regarded sequence diagrams generated from unit tests and I feel it’s again time to post information about the latest state. I hope I would get some people hooked on the topic and that they would give me some useful feedback!

Shortly after my previous post on the topic I came across the problem of calling functions from the test environment (see attached image). For the Connection example that would be when bool Connection::write (const QByteArray &) calls in effect quint64 ConnectionImpStub::writeData (const char*, quint64). It’s quite obvious how the corresponding sequence diagram would look like, the difficult part is how to represent that in C++ code! I was trying out different solutions and after looking at MockPP I got what I needed – object chaining. In my latest BitTorrent branch (revno 93) there is a quick and dirty implementation that makes this possible.

Here is a snippet:

INVOKE (connection, setWriteBufferSize (writeBufferSize)) IS_OK;
CALL (connection, canWrite (writeBufferSize)) SHOULD_RETURN (true);
CALL (connection, canWrite (writeBufferSize + 1)) SHOULD_RETURN (false);
CALL (connection, write (bytes))
	EXPECT (*imp) IS_CALLED (writeData (bytes)) RETURNS (bytes.size())
SHOULD_RETURN (bytes.size() < = writeBufferSize);


I hope it is clear what the above code expresses. CALL actually creates a CallDriver object, which is kind of a function object bound to the actual class method with the arguments provided in the test. EXPECT adds an expectation to the CallDriver object. If the expectation is that a non-void function is called, then the return value of this function should be stubbed using RETURNS. Finally, SHOULD_RETURN calls the bound function and compares the returned value with the result of the provided expression.

The advantage of method chaining is that this way we can achieve any level of calls and expectation. For example, the following would also be possible (it makes no sense but just imagine the corresponding sequence diagram:

CALL (o, f1 (1))
	EXPECT (e) IS_CALLED (g1 (1))
		CALL (o, f2()) SHOULD_RETURN (2)
	RETURNS (2)
SHOULD_RETURN (2)


Now, the interesting part is how to get the implementation of this nice. I wanted to use Boost.Function together with Boost.Bind but don’t want to have dependency of Calitko on yet another library. Actually I wanted to bundle only the parts of Boost I want to use, so I used bcp to extract Boost.Function together with all its dependencies (it’s really great that Boost people have written this tool) but the result was more than 5MB in include only.

I was quite impressed by what is achieved with templates metaprogramming in Boost! I felt like I need to read a book about that! While searching for a good one I came across the Loki library by Andrei Alexandrescu – author of Modern C++ Design. It also has a Function class, which I can use for my stuff, so I guess I’ll try it out!

Regards,

Peter

Attached Files:

write.png 25K

Would you like to post a relpy?


This post is a reply to:
Re: Generating sequence diagrams from unit tests
Hello everybody, I’m very much hooked by all the new stuff I learn about testing from my sequence diagram generation experiments. I just came again across http://www.mockobjects.com. I say again (more...)

Follow-ups:
Re: Generating sequence diagrams from unit tests
Hello everybody, I just pushed my latest revision to the calitko-BitTorrent branch. I’ve again done some work related to our improving our unit-tests by providing a framework that helps us write (more...)