9

I am currently trying to write a unit test of my own. The unit test I am writing is mainly for linear algebra (I know there are great package out there but I want to use my own for my project). My current linear algebra consist of my_vector.hpp/cpp (3d) and my_matrix.h/cpp.

So I am currently writing a test_vector.cpp and test_matrix.cpp which will test the features of my_vector and my_matrix.

In regards to testing vector class, inside test_vector.cpp I test my_vector's add, subtract, divide, dotproduct etc features.

How I do it is :

// test_vector.cpp
void test_add(){

    my_vector a(2.0, 1.1, 2.1);
    my_vector b(2.1, 2.0, 1.1);

    // manually computed by adding a and b by hand
    // 
    my_vector expected(4.1, 3.1, 3.2);


    my_vector c = a + b;

    assert(c.x == expected.x);
    assert(c.y == expected.y);
    assert(c.z == expected.z);
}

void test_sub(){

    .....
}

int main(){
    test_add();
    test_sub();
    ....
return 0;
}  

I do similar for test_matrix.cpp as well.

In my_vector expected(4.1, 3.1, 3.2); I firstly manually added 2.0, 1.1, 2.1 of a and 2.1, 2.0, 1.1 of b and then compared to the value computed after using c = a + b. Do you think this is a proper way to do unit testing. I find it little cumbersome since I have to do the computation by hand for other complex test like rotation, cross product etc also. This kind of gives a feeling that I am doing something wrong.

Am I doing something wrong? Please let me know, I am open for any suggestions.

5 Answers 5

6

This is quite a common way of doing it, and I wouldn't describe it as wrong. There are alternatives, though -- for instance, you could find another calculation that you can apply to the results which should be simpler to calculate and would show they're correct. For addition, that's probably not feasible, but for rotation about 90 degrees, you could consider applying a dot product and checking its zero, and checking that the magnitude is correct, and that would give you a very good idea that the implementation is correct (assuming your implementation of these other, simpler operations is already known to be correct).

You can take this a step further and run such calculations on random data. Doing this on a large number of items can give you confidence that you've caught all of the edge cases in an algorithm.

One further piece of advice: I notice you're not using a unit testing framework. While this is possible, I would strongly suggest using a framework as they provide much better feedback when things go wrong. For C++, I tend to use Catch but there are many other alternatives too.

2

Using a unit testing framework is ver (very) sound advice, as Pariata Breatta pointed out. It makes testing much easier, and is supported by many IDEs.

Consider putting the equality test in your vector class itself, making it much easier to reuse it in unit tests later - and it will most probably come very handy sooner or later anyway. Oh, write a non-recursive unit test for that as well, of course. Checking all components is usually the way to go, and using your new method it will only have need assertion for that. Just comparing sums introduces new possible points of failures (think about permutation or numerical errors).

You might want to supply an "about equal"-check supporting some epsilon around your values to allow for numeric inaccuracy effects, as working with floating point numbers might just not end up the way you expect them to be.

2
  • When you say "Consider putting the equality test in your vector class itself" do you mean to write operator== for my_vector class? and also what do you really mean when you say "write a non-recursive unit test for that as well" .. and also I do actually have epsilon thing already implemented for decimal assertion:)
    – solti
    Commented Oct 20, 2016 at 16:13
  • @solti it doesn't have to be named that, but that is a good name, and it's what e.g. Catch's EXPECT_EQ will use
    – Caleth
    Commented Nov 16, 2023 at 15:43
1

You're doing it right. The only alternative I can see to the manual approach would be to use a trusted third party library to run your calculations, then have the test suite compare your calculations with the library's.

Of course, it would be redundant to implement the functionality of a library you already have access to. I imagine you would only do this if the library cannot, for whatever reason, be used when you go live and you are forced to implement your own.

By the way, shouldn't the expected result be (4.1, 3.1, 3.2) ?

1
  • thank you for the response and thank you for correcting my typo :)
    – solti
    Commented Oct 20, 2016 at 17:06
1

You can use this header file:

https://github.com/xiaochun888/CppUnitTestExpress

It is easy to be integrated or extended into your application, your example will be possible to write here:

#include "CppUnitTestExpress.h"

class my_vector : Unit<my_vector>
{
    ...
    void Test()
    {
        my_vector a(2.0, 1.1, 2.1);
        my_vector b(2.1, 2.0, 1.1);
        my_vector c = a + b;

        _assert(c.x == 4.1, "c.x should be egal to 4.1.");
        _assert(c.y == 3.1, "c.y should be egal to 3.1.");
        _assert(c.z == 3.2, "c.z should be egal to 3.2.");
     }
}

int main(){
    UnitTest ut;
    ut.runAll();
    ut.resume();
    ...
    return 0;
}  
0

Use Google Test framework. For mocking there's also Google Mock framework. Both are meant to be used with C++.

2
  • The question isn't a software recommendation one, so this isn't a good answer. Commented Oct 21, 2016 at 14:26
  • 8
    OP asks the following: 'Am I doing something wrong? Please let me know, I am open for any suggestions'. What he's doing wrong is NOT using a testing framework, and I suggested one of the best ones out there.
    – Eternal21
    Commented Oct 21, 2016 at 16:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.