Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A good way to write unit tests

Tags:

unit-testing

So, I previously wasn't really in the practice of writing unit tests - now I kind of am and I need to check if I'm on the right track.

Say you have a class that deals with math computations.

class Vector3
{
public:  // Yes, public.
  float x,y,z ;
  // ... ctors ...
} ;

Vector3 operator+( const Vector3& a, const Vector3 &b )
{
  return Vector3( a.x + b.y /* oops!! hence the need for unit testing.. */,
                  a.y + b.y,
                  a.z + b.z ) ;
}

There are 2 ways I can really think of to do a unit test on a Vector class:

1) Hand-solve some problems, then hard code the numbers into the unit test and pass only if equal to your hand and hard-coded result

bool UnitTest_ClassVector3_operatorPlus()
{
  Vector3 a( 2, 3, 4 ) ;
  Vector3 b( 5, 6, 7 ) ;

  Vector3 result = a + b ;

  // "expected" is computed outside of computer, and
  // hard coded here.  For more complicated operations like
  // arbitrary axis rotation this takes a bit of paperwork,
  // but only the final result will ever be entered here.
  Vector3 expected( 7, 9, 11 ) ;

  if( result.isNear( expected ) )
    return PASS ;
  else
    return FAIL ;
}

2) Rewrite the computation code very carefully inside the unit test.

bool UnitTest_ClassVector3_operatorPlus()
{
  Vector3 a( 2, 3, 4 ) ;
  Vector3 b( 5, 6, 7 ) ;

  Vector3 result = a + b ;

  // "expected" is computed HERE.  This
  // means all you've done is coded the
  // same thing twice, hopefully not having
  // repeated the same mistake again
  Vector3 expected( 2 + 5, 6 + 3, 4 + 7 ) ;

  if( result.isNear( expected ) )
    return PASS ;
  else
    return FAIL ;
}

Or is there another way to do something like this?

like image 280
bobobobo Avatar asked Jun 13 '10 17:06

bobobobo


People also ask

Is it hard to write unit tests?

But, being a white box software testing technique, unit testing is an in-depth process that requires a lot of knowledge about the code and how it interacts with other parts of the project. As a result, it can be hard to start writing unit tests, especially if you are new to the codebase.


2 Answers

Way #1 is the generally accepted way of doing Unit testing. By rewriting your code, you could be rewriting faulty code into the test. A lot of the time, only one real test case is needed per method that you're testing, so it's not TOO time consuming.

like image 167
codersarepeople Avatar answered Sep 28 '22 04:09

codersarepeople


It depends always on the use case. I would choose always that version, that makes the tested idea more obvious. For that reason I would also not use the isNear method. I would check for

expected.x == 7;
expected.y == 9;
expected.z == 11;

Using a good xUnit library you will get a clean error message which component of expected was wrong. In your example you would have to search for the real source of the error.

like image 26
Achim Avatar answered Sep 28 '22 04:09

Achim