This document can be considered a "port" of the JUnit Guide I wrote. In particular, this document talks about using CppUnit in MS Visual C++ 6.0. As in the JUnit Guide, I have included only the bare minimum to get you started. I will first go through the installation of CppUnit in the next section, followed by a description of how to use CppUnit using a sample program. Next, I will suggest some ways of organizing your project and test codes before ending the document with pointers to some useful references.
Next, select Build->Rebuild All to create the culib.lib library.
There will be some failures and errors - it's okie. Close the TestRunner window. Another window will pop up. Just close it. CppUnit is now installed properly.
Next, add the files for running the text interface. Select Project->Add To Project->Files and go to the directory C:\CppUnit\test\textui and add the files TextTestResult.h and TextTestResult.cpp. You need to change one more setting. Select Project->Settings and choose the C/C++ tab. Under the Category dropbox, select Preprocessor. Put "C:\CppUnit\test\framework" in the textbox for "Additional include directories".
Finally, select Build->Rebuild All to create the CppUnit library.
Assuming that you want to test a class called Parser. The following are the general steps to use the CppUnit framework to test this class:
You will be prompted for the kind of Console Application - just select "An empty project" and click on the Finish button. A window showing the new project information will be displayed. Click on the Ok button to close it.
Next, you need to create the classes used for the example. You can enter the code using any editor of your choice, placed them in the directory C:\CS3214s\tutorial and then add them to the tutorial project through the IDE (using Project->Add To Project->Files), or you can make use of the IDE to create the necessary files. Take a few minutes to examine the following two classes (.h and .cpp files) to see what they are doing:
#ifndef Course_h #define Course_h #include <string> class Course { public: // Default constructor Course(); // Constructor Course(std::string nm, int gr); // method to get the name of the course std::string getCourseName(); // method to get the grade of the course int getCourseGrade(); private: std::string course_name; // name of this course int grade; // grade of this course }; #endif
#include "Course.h" // default constructor Course::Course() { course_name = ""; grade = -1; } // constructor Course::Course(std::string nm, int gr):course_name(nm) { grade = gr; } // method to get the name of the course std::string Course::getCourseName() { return course_name; } // method to get the grade of the course int Course::getCourseGrade() { return grade; }
#ifndef Student_h #define Student_h #include <iostream> #include <string> #include "Course.h" const int MAXNUM = 20; // Maximum number of courses allowed per student class Student { public : // Constructor Student(std::string nm, std::string no); // Method to return student's name std::string getStuName(); // Method to return student's number std::string getStuNumber(); // Method to assign a grade to a course void assignGrade(std::string co, int gr); // Method to return the grade of a course int getGrade(std::string co); private: std::string name; // name of the student std::string number; // the student's number Course course_grades[MAXNUM]; // courses taken by student int no_of_courses; // the current number of courses taken }; #endif
#include "Student.h" // Constructor Student::Student(std::string nm, std::string no):name(nm), number(no) { no_of_courses = 0; } // Method to return student's name std::string Student::getStuName() { return name; } // Method to return student's number std::string Student::getStuNumber() { return number; } // Method to assign a grade to course void Student::assignGrade(std::string co, int gr) { // check whether the maximum number of courses have been taken if (no_of_courses == MAXNUM) { std::cout << "You have exceeded the maximum number of courses !\n"; return; } // create a new course Course c(co, gr); course_grades[no_of_courses++] = c; } // Method to return the grade of a course int Student::getGrade(std::string co) { int i = 0; while (i < no_of_courses) { //check if course name the same as co if (course_grades[i].getCourseName() == co) return (course_grades[i].getCourseGrade()); i++; } return(-1); }
#ifndef TestStudent_h #define TestStudent_h #include <iostream> #include <string> // Note 1 #include "TestCase.h" #include "TestSuite.h" #include "TestCaller.h" #include "Student.h" class StudentTestCase : public TestCase { // Note 2 public: // constructor - Note 3 StudentTestCase(std::string name) : TestCase(name) {} // method to test the constructor void testConstructor(); // method to test the assigning and retrieval of grades void testAssignAndRetrieveGrades(); // method to create a suite of tests static Test *suite (); }; #endif
#include "TestStudent.h" // method to test the constructor void StudentTestCase::testConstructor() { // Note 4 // create a student object Student stu("Tan Meng Chee", "94-1111B-13"); // check that the object is constructed correctly - Note 5 std::string student_name = stu.getStuName(); assert(student_name == "Tan Meng Chee"); std::string student_number = stu.getStuNumber(); assert(student_number == "94-1111B-13"); } // method to test the assigning and retrieval of grades void StudentTestCase::testAssignAndRetrieveGrades() { // create a student Student stu("Jimmy", "946302B"); // assign a few grades to this student stu.assignGrade("cs2102", 60); stu.assignGrade("cs2103", 70); stu.assignGrade("cs3214s", 80); // verify that the assignment is correct - Note 6 assertEquals(60, stu.getGrade("cs2102")); assertEquals(70, stu.getGrade("cs2103")); // attempt to retrieve a course that does not exist assertEquals(-1, stu.getGrade("cs21002")); } // method to create a suite of tests - Note 7 Test *StudentTestCase::suite () { TestSuite *testSuite = new TestSuite ("StudentTestCase"); // add the tests testSuite->addTest (new TestCaller <StudentTestCase> ("testConstructor", &StudentTestCase::testConstructor)); testSuite->addTest (new TestCaller <StudentTestCase> ("testAssignAndRetrieveGrades", &StudentTestCase::testAssignAndRetrieveGrades)); return testSuite; }
change: #include "ExampleTestCase.h" to: #include "TestStudent.h" and change: runner.addTest ("ExampleTestCase", ExampleTestCase::suite ()); to: runner.addTest ("StudentTestCase", StudentTestCase::suite ());As you write different test classes for your testing, remember to modify (or create) TestRunner.cpp for your own usage.
Now, you are ready to compile and run the tests. Before that, you need to configure some settings for your project. Select Project->Settings and then the C/C++ tab. Under the Category dropbox, select Preprocessor. Put "C:\CppUnit\test\framework, C:\CppUnit\test\textui" in the "Additional include directories" textbox.
Last of all, click on the Link tab and append "C:\CppUnit\ms\culib\Debug\culib.lib" to the string in the "Object/library modules" textbox. Click Ok, we are now ready for testing.
Select Build->Rebuild All to start your compilation. You should get some warnings but there shouldn't be any errors. Finally, open your dos prompt and go to C:\CS3214s\tutorial\Debug. Type
tutorial StudentTestCaseIf you get the following output, you have successfully completed your unit testing.
// In Student.h under public // Method to return the average grade float findAveGrade(); // In Student.cpp // Method to return the average grade float Student::findAveGrade() { float sum = 0.0, average; // sum up the marks in all the courses for (int i = 0; i < no_of_courses; i++) sum += course_grades[i].getCourseGrade(); average = sum / no_of_courses; return(average); }Your job is to write a method in the StudentTestCase class to test this newly created method. Give it a try and see whether you really know how to use CppUnit ;-)