Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 30

Unit testing and code

coverage for C++

1
cppUnit

Coding an individual test


Use assertion macros defined in unit test library
Elements for building tests
TestFixture, TestSuite, TestRunner

2
Code in an individual test
Use assertion macros defined in cppunit
If assertion fails, an exception is thrown
 CPPUNIT_ASSERT(condition):
 Checks the condition and throws an exception if it's false.
 CPPUNIT_ASSERT_MESSAGE(message, condition):
 Checks the condition and throws an exception and showing specified message if
it is false.
 CPPUNIT_ASSERT_EQUAL(expected,current):
 Checks whether the expected condition is the same as current, and raises an
exception showing the expected and current values.
 CPPUNIT_ASSERT_EQUAL_MESSAGE(message,expected,c
urrent)
 Checks whether the expected is the same as the actual, and raises an exception
showing the expected and current values, and specified message.
 CPPUNIT_ASSERT_DOUBLES_EQUAL(expected,current,delta):
 Checks whether the expected and current difference is smaller than delta. If it 3
fails, the expected and current values are shown.
TestFixture
 Each test should be derived from the abstract
class TestFixture
 Override two functions:
setUp
 operations that would be invoked prior to each individual test,
e.g. create new clean instances of class ready for next test
tearDown
 operations that would be invoked after to each individual test,
e.g. deletes instances

4
TestSuite, TestRunner

TestSuite
Groups a number of tests (using TestFixture) so
that they can all be run
TestRunner
Driver program

5
Test driven development
Test twice, code once
“The style here is to write a few lines of
code, then a test that should run, or even
better, to write a test that won't run, then
write the code that will make it run.”

6
Test driven development – step 0
 Define class Bitmap
Owns an array of unsigned long integers
 Methods
boolean Identity(const Bitmap& other)
 Are we the same Bitmap
 Compare our address with other’s address!
boolean Equals(const Bitmap& other)
 Are we equal?
 What do you mean equal?
• This is the part we test twice – code once!
void Zero()
 Set my bits all to zero.

7
#ifndef __MYBITSCLASS__
#define __MYBITSCLASS__
Class Bitmap
// Code assumes 32-bit unsigned long integers
#define MAXBITS 512
#define NUMWORDS 16
typedef unsigned long Bits;

class Bitmap {
public:
Bitmap();
void Zero(void);
bool Equals(const Bitmap &other) const;
bool Identity(const Bitmap &other) const;
private:
Bits fBits[NUMWORDS];
};
#endif

8
#include "Bitmap.h"
Bitmap::Bitmap() Class Bitmap
{
Zero();
}
void Bitmap::Zero(void)
{
for(int i=0;i<NUMWORDS; i++)
fBits[i] = 0;
}
bool Bitmap::Identity(const Bitmap& other) const
{
return (this == &other);
}
bool Bitmap::Equals(const Bitmap& other) const
{
return Identity(other);
// Incorrect implementation
}

9
Now write a test for Bitmap -- TestFixture
#ifndef BITMAPTEST_H
#define BITMAPTEST_H

#include <cppunit/TestCase.h>
#include <cppunit/extensions/HelperMacros.h>
#include "Bitmap.h"

class BitmapTest : public CppUnit::TestFixture


{
CPPUNIT_TEST_SUITE (BitmapTest);
CPPUNIT_TEST (testEquals);
CPPUNIT_TEST_SUITE_END ();
private:
Bitmap bitmap1;
Bitmap bitmap2;
public:
void setUp();
void tearDown();
protected:
void testEquals();
};

#endif 10
#include "BitmapTest.h"
#include "Bitmap.h"

CPPUNIT_TEST_SUITE_REGISTRATION (BitmapTest);

void BitmapTest::setUp()
{
// Put the bitmaps back in standard state
// (Need at least two as doing things like
// checking equality)
bitmap1.Zero();
bitmap2.Zero();
}

void BitmapTest::tearDown()
{
// Nothing to do
}

11
void BitmapTest::testEquals()
{
// Identity should work
CPPUNIT_ASSERT(bitmap1.Identity(bitmap1));
CPPUNIT_ASSERT(bitmap2.Identity(bitmap2));
CPPUNIT_ASSERT(!bitmap1.Identity(bitmap2));

// At this stage - equality incorrectly defined


// It is identity
// (It shouldn't be!)

// This test should succeed - I'm equal to me


CPPUNIT_ASSERT(bitmap1.Equals(bitmap1));

// so should this
CPPUNIT_ASSERT(bitmap2.Equals(bitmap2));

// But this should fail


CPPUNIT_ASSERT(bitmap1.Equals(bitmap2));
}

12
The Driver -- TestRunner

int main (int argc, char* argv[])


{
// Result collection
CPPUNIT_NS :: TestResult testresult;
CPPUNIT_NS :: TestResultCollector collectedresults;
testresult.addListener (&collectedresults);
CPPUNIT_NS :: TextTestProgressListener tracker;
testresult.addListener(&tracker);

// Setting up runner and running test


CPPUNIT_NS :: TestRunner testrunner;
testrunner.addTest (CPPUNIT_NS :: TestFactoryRegistry :: getRegistry ().makeTest
());
testrunner.run (testresult);

// Reporting
CPPUNIT_NS :: CompilerOutputter compileroutputter (&collectedresults, std::cerr);
compileroutputter.write ();

return collectedresults.wasSuccessful () ? 0 : 1; 13
}
Build and run

!!!FAILURES!!!
Test Results:
Run: 1 Failures: 1 Errors: 0

1) test: BitmapTest::testEquals(F) line: 34


BitmapTest.cc
assertion failed
Expression: bitmap1.Equals(bitmap2)

14
“Refactor”

bool Bitmap::Equals(const Bitmap& other) const


{
for(int i = 0; i < NUMWORDS; i++)
if(this->fBits[i] != other.fBits[i]) return false;
return true;
}

15
Next increment – more functionality in
Bitmap

class Bitmap {
public:
Bitmap();
void Zero(void);
void SetBit(int bitnum);
int Count(void) const;

bool Equals(const Bitmap &other) const;


bool Identity(const Bitmap &other) const;
private:
Bits fBits[NUMWORDS];
};

16
BitmapTest
class BitmapTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE (BitmapTest);
CPPUNIT_TEST (testEquals);
CPPUNIT_TEST (testSetBit);
CPPUNIT_TEST (testSetBitAndCount);
CPPUNIT_TEST_SUITE_END ();
private:
Bitmap bitmap1;
Bitmap bitmap2;
public:
void setUp();
void tearDown();
protected:
void testEquals();
void testSetBit();
void testSetBitAndCount();
};

17
BitmapTest

Extended equality test


Can now make Bitmaps that are not equal (by
using set bit operation)
Add two more extensive tests on new test
and count operations

18
void BitmapTest::testEquals()
{ BitmapTest
// Identity should work
CPPUNIT_ASSERT(bitmap1.Identity(bitmap1));
CPPUNIT_ASSERT(bitmap2.Identity(bitmap2));
CPPUNIT_ASSERT(!bitmap1.Identity(bitmap2));
CPPUNIT_ASSERT(bitmap1.Equals(bitmap1));
CPPUNIT_ASSERT(bitmap2.Equals(bitmap2));
CPPUNIT_ASSERT(bitmap1.Equals(bitmap2));

// Have some functionality to change the bits


// See if equals works after that
// Set a different bit
bitmap1.SetBit(22);
bitmap2.SetBit(123);
// Shouldn't be equals any more!
CPPUNIT_ASSERT(!bitmap1.Equals(bitmap2));
}
19
void BitmapTest::testSetBit()
{ BitmapTest
// If set bit 0 in one, they should not be equal
bitmap1.SetBit(0);
CPPUNIT_ASSERT(!bitmap1.Equals(bitmap2));
// Just being pedantic - reverse roles in test
CPPUNIT_ASSERT(!bitmap2.Equals(bitmap1));
bitmap1.Zero();
// But should be equal after it got cleared
CPPUNIT_ASSERT(bitmap1.Equals(bitmap2));
CPPUNIT_ASSERT(bitmap2.Equals(bitmap1));
// If set a non-existent bit it isn't supposed
// to change anything
bitmap1.SetBit(-1);
bitmap2.SetBit(513);
CPPUNIT_ASSERT(bitmap2.Equals(bitmap1));
}

20
void BitmapTest::testSetBitAndCount()
{ BitmapTest
// Set some bits and check that count equals number of bits set
int bits1[] = { 0, 3, 17, 21, 33, 54, 68, 77, 91, 103, 211, 304 };
int bits2[] = { 0, 31, 32, 33, 63, 64, 65, 300, 400, 500, 511 };
int count1 = sizeof(bits1)/sizeof(int);
int count2 = sizeof(bits2)/sizeof(int);
for(int i=0;i<count1;i++)
bitmap1.SetBit(bits1[i]);
for(int i=0;i<count2;i++)
bitmap2.SetBit(bits2[i]);
CPPUNIT_ASSERT_EQUAL(count1, bitmap1.Count());
// Deliberate error to get a failed test
CPPUNIT_ASSERT_EQUAL(count1, bitmap2.Count());
}

21
Rebuild, rerun

!!!FAILURES!!! Text
Test Results:
Run: 3 Failures: 1 Errors: 0

1) test: BitmapTest::testSetBitAndCount (F) line: 77


BitmapTest.cc
equality assertion failed
- Expected: 12
- Actual : 11
22
cppunit

Available at
http://sourceforge.net/projects/cppunit

Is installed on Linux machines in lab used


for CSCI222

23
Tutorials …

http://www.comp.nus.edu.sg/~cs3214s/too
ls/cppunitSol.html
http://www.evocomp.de/tutorials/tutorium_
cppunit/howto_tutorial_cppunit_en.html
Documentation with cppUnit
Docs folder in /share/cs-pub/222/testing
“Money” tutorial

24
Code coverage
g++ compiler and
gcov analysis tool

25
Compilation for code coverage

Set extra compile flags


In NetBeans setup, it is simplest just to specify
--coverage
in the "command line" options for both the compilation
and linker steps

26
Run, then use gcov to analyze
 NetBeans can be used to run the application
under test
Best to run several times with different input data so as
to try to test all options
 gcov analysis should be done in terminal
session
cd to directory with C++ source
Identify directory where gcov files (.gcno, .gcda) were
created – should be ./build/Debug/GNU-Linux-x86
Run gcov specifying the data directory and file for
analysis

27
Gcov analysis : function summaries
gcov –o ./build/Debug/GNU-Linux-x86 -f Bitmap.cc
100.00% of 3 source lines executed in function void Bitmap::Zero()
100.00% of 7 source lines executed in function void Bitmap::SetBit(int)
100.00% of 8 source lines executed in function void Bitmap::ClearBit(int)
0.00% of 4 source lines executed in function void Bitmap::SetAs(int, int)
85.71% of 7 source lines executed in function int Bitmap::TestBit(int) const
100.00% of 7 source lines executed in function void Bitmap::FlipBit(int)
100.00% of 2 source lines executed in function void
Bitmap::ReadFrom(std::fstream&)

100.00% of 4 source lines executed in function int Bitmap::Equals(const
Bitmap&) const
94.32% of 88 source lines executed in file Bitmap.cc

28
Gcov analysis: branch counts
$ gcov –o ./build/Debug/GNU-Linux-x86 -c Bitmap.cc

94.32% of 88 source lines executed in file Bitmap.cc
Creating Bitmap.cc.gcov.
$ cat Bitmap.cc.gcov
#include "Bitmap.h"
Bitmap::Bitmap()
14 {
14 Zero();
}
void Bitmap::Zero(void)
15 {
255 for(int i=0;i<NUMWORDS; i++)
240 fBits[i] = 0;
}
void Bitmap::SetBit(int bitnum)
113 {
113 if((bitnum < 0) || (bitnum >= MAXBITS))
113 return;
113 int word = bitnum / 32;

29
Inspect profiles

Profiles and function summaries


immediately reveal untested code.

30

You might also like