Can I write custom assertions in CxxTest?

495 views Asked by At

I'm just starting to use CxxTest and would like to test whether a std::vector has been sorted correctly. Here's my test so far:

void testSort() {
  std::sort(vec.begin(), vec.end()); // This could be any sorting function

  for (unsigned int i = 0; i < vec.size() - 1; ++i) {
    TS_ASSERT(vec[i] <= vec[i + 1]);
  }
}

Obviously, CxxTest does not provide a TS_ASSERT_SORTED assertion, but is there a way to write custom assertions? That would allow me to do this:

void testSort() {
  std::sort(vec.begin(), vec.end()); // This could be any sorting function

  TS_ASSERT_SORTED(vec);
}

It's significantly easier to see the intent of the test when it's written this way.

I looked through the CxxTest user's guide but couldn't figure out whether you can write custom assertions like this. As an alternative, I could write a class IsSorted and implement its operator(). I could then write the test like this:

void testSort() {
  std::sort(vec.begin(), vec.end()); // This could be any sorting function

  TS_ASSERT_PREDICATE(IsSorted, vec);
}

I'm guessing this is the correct approach. If I do this, though, should I place the definition of class IsSorted in its own header file, separate from my test suite? I'm still trying to figure out the best practices associated with unit testing, especially in this framework.

One final question: should I be sorting the vector in the setUp() method or in the test itself?

3

There are 3 answers

0
Uri Cohen On BEST ANSWER

You can add a few new macros of your own by changing cxxtest header files. It's open source, after-all! Make sure you fail the test correctly from those macros (see what TS_ASSERT_EQUALS do, unlike the example given here by martiert which is not compatible with how cxxtest work).

1
martiert On

You could use a #define


#define TS_ASSERT_PREDICATE( vec )\
    std::vector tmp = vec;\
    for(int i = 0; i  tmp[i+1]) \
            return false;\ 
    }\ 
    return true;\ 
}
0
Mark Bessey On

Well, the assertions are just preprocessor macros, so you could probably implement them however you want, and then #define a macro for them. I'd think it'd be better to use a name that doesn't start with TS_ASSERT_, so that you don't confuse later readers of the code.

The predicate version doesn't look all that clumsy to me - I'd probably go with that, or possibly implement a check_ method on the class you're testing, and call that from the test. I often end up needing methods that validate the internal structure of the class for run-time debugging & logging, anyway...