Isolator++: Introduction

Isolator++ is the new isolation framework from Typemock. In C++ everything is harder, even unit testing, believe it or not. When people start doing unit tests, they run into the dependency problem. And this is where Isolator++ comes to the rescue. But let’s go back to the beginning.

There are a couple of test frameworks around: CPPUnit, UnitTest++, YAFFUT, and many more. These test frameworks compile into a console app, and give you the API to identify tests and assert pass/fail criteria. But the frameworks don’t give you everything.

Let’s take a look at a FileHandler class. It has a SafeDelete method, that does the following:

void FileHandler::SafeDelete(const char* filename)

{

    FILE* fp = fopen(filename, "r");

    if (fp == NULL)

    {

        throw ("File does not exist");

    }

    else

    {

        fclose(fp);

        remove (filename);

    }

}

SafeDelete basically checks that a file is there prior to deleting it. How can I test this method?

The first case I want to check is that if there’s no file there, I’ll get an exception:

TEST_F(FileHandlerTests, SafeDelete_NoFile_ExceptionThrown)

{

    FileHandler handler;

    bool result = false;

 

    try

    {

        handler.SafeDelete("AnyFile");

    }

    catch (char* exception)

    {

        result = true;

    }

 

    ASSERT_TRUE(result);

}

As you can see, I’m just invoking the SafeDelete method, and expecting an exception, if the file is missing.

Of course, it means there should never be a file called “AnyFile” on the disk, otherwise, the method will actually delete it.

This whole business of depending on the state on the file system, and affecting that state once the method runs, is annoying. You need to prepare a file for the next test, need to clean up after you, and this can escalate very quickly to something that’s impossible to write.

This is where Isolator++ comes in. It helps you simulate behavior of method calls, without leaving any marks. Here’s how we deterministically make sure that the fopen method returns NULL:

    1 TEST_F(FileHandlerTests, SafeDelete_NoFile_ExceptionThrown)

    2 {

    3     FileHandler handler;

    4     bool result = false;

    5 

    6     try

    7     {

    8         FAKE_GLOBAL(fopen);

    9         WHEN_CALLED(fopen(_,_)).ReturnPtr(NULL);

   10         handler.SafeDelete("AnyFile");

   11     }

   12     catch (char* exception)

   13     {

   14         result = true;

   15     }

   16 

   17     ASSERT_TRUE(result);

   18     ISOLATOR_CLEANUP();

   19 }

Let’s go over the code:

Line 8, We declare we want to fake fopen with FAKE_GLOBAL.

Line 9: Since fopen returns a FILE *, we need to tell it to return NULL, with WHEN_CALLED. Note that since we don’t care about the arguments of fopen, just the behavior, we use the _ macro, instead of declaring any arguments. Much more readable like this.

Line 18: At the end of the test, we clean up every fake setup we declared, with ISOLATOR_CLEANUP. This way, we’re making sure we don’t carry over any side effects to the next test.

And that’s basically it. We worked around the dependency of the file system, by faking the call, and returning a custom value.

Isolator++ can do much more. Stay tuned for more examples and how-tos.

Gil Zilberfeld