Handy development tools CppUnit quick-Use guide

Source: Internet
Author: User
Tags class definition naming convention

Background

CppUnit is an open source project based on LGPL, originally ported from JUnit, and is a very good open source testing framework. CppUnit and JUnit are the main ideas derived from Extreme programming (xprogramming). The main function is to manage the unit test and to automate the test. This description may not give you a sense of the power of the test framework, and did you encounter the following problems during the development process? If the answer is yes, you should learn to use this technique: test code is not well maintained and discarded, need to rewrite when testing again, put too much effort, find bugs, and new code will still appear similar bugs, write code, no bottom, whether there are a large number of bugs waiting for themselves; The newly modified code does not know whether to affect other parts of the code, because too much involved, resulting in the dare not to modify the code;
...

These questions will be covered below. This powerful test framework is not used in many of the native C + + language developers. This article introduces this framework from a developer's perspective, hoping to enable developers to master this technology at the lowest cost possible. The following are discussed in terms of basic principles, CppUnit Principles, Manual Use steps, commonly used steps, and other practical issues. The following discussion is based on CppUnit1.8.0.




Back to the top of the page


1. Basic Principles

For the above problem only shows that the use of CppUnit is not effective, the following first from the purpose of testing, testing principles and other aspects of the brief description, and then introduce the specific use of CppUnit.

The first thing to make clear is that the purpose of writing test code is to verify the correctness of the code or debug bugs. When you write the test code, you have the pertinence of writing test code that is prone to error and variable, without having to write test code for every detail, every feature, unless you have excessive energy or reliability requirements.

The relationship between coding and testing is inseparable, the recommended development process does not have to wait to write all or a lot of code to test, but to complete a part of the code, such as a function, immediately after writing the test code to verify. Then write some code, then write the test. Each test is performed on all previous tests. The advantage of this is that, after the completion of the code, but also the basic test, the heart of the code have confidence. And in the new code to constantly test the old code, the other part of the code impact can be quickly found, positioning. The process of constantly coding tests is the process of maintaining the test code so that the test code is always valid. With the various parts of the test code to ensure that there is a mechanism for automated testing, change the previous code without any concern. In extreme programming (a concept of software development), it is even emphasized to write the test code first, and then write the code that conforms to the test code to complete the software.

According to the above purpose, thought, the following summary of the normal development process unit Test principle: First write test code, and then write the code to match the test. At least after completing some of the code, complete the corresponding test code, the test code does not need to overwrite all the details, but should have a corresponding test case for all the major functions and possible errors, find bugs, first write the corresponding test cases, and then debug, and constantly summarize the reasons for the bug Write the appropriate test cases for other code, each time you write the completion code, run all the previous test cases, verify the impact on the previous code, and eliminate the impact as soon as possible, continuously maintain the test code, ensure that the code changes after all the tests;

With the above theory as a guide, test behavior can be regulated. So CppUnit how to implement this test framework, help us manage the test code, complete the automated test. Here is a look at the principle of CppUnit.




Back to the top of the page


2. Principle of CppUnit

In CppUnit, test subjects for one or a set of test cases are referred to as Fixture (facilities, below for easy understanding using English names as far as possible). Fixture is the target of the test, possibly an object or a group of related objects, or even a function.

With the tested fixture, you can write test code for a feature of this fixture, a potentially faulty process, so that a complete test of some aspect is called testcase (test case). Usually, the steps to write a TestCase include initializing the fixture and other initialization operations, such as generating a set of tested objects, initializing the value, manipulating the fixture according to a function or process to be tested, verifying the correctness of the results, and the fixture and its The release of his resources and other clean-up work.

For multiple test cases of fixture, typically (1) (4) Part of the code is similar, CppUnit introduces the setUp and teardown virtual functions in many places. You can complete (1) initialization of the code in the SetUp function and complete (4) code in the Teardown function. The specific test case function only needs to complete (2) (3) Part of the code, runtime CppUnit will automatically run the setUp for each test case function, then run teardown, so there is no cross impact between test cases.

All test cases for fixture can be encapsulated in a cppunit::testfixture subclass (the naming convention is [classname]test). Then define the fixture setUp and teardown functions, and define a test function for each test case (the naming convention is testxxx). Here's a simple example:

Class Mathtest:public Cppunit::testfixture {
Protected
int m_value1, m_value2;
Public
Mathtest () {}
initialization function
void SetUp () {
M_value1 = 2;
M_value2 = 3;
}
Test function for test addition
void Testadd () {
Step (2), operate on the fixture
int result = m_value1 + m_value2;
Step (3), verify that the results are sought
Cppunit_assert (Result = = 5);
}

}

The success or failure of the test case is directly reflected in the successful or unsuccessful validation of the execution result in the test function. CppUnit provides a variety of ways to verify successful failures:

		Cppunit_assert (condition)					//Sure condition is true
Cppunit_assert_message (message, condition) //failure when condition is false, and print message
Cppunit_fail (message) //Current test failed and print message
Cppunit_assert_equal (expected, Actual) /Make sure the two are equal
Cppunit_assert_equal_message (message, expected, Actual) //Failed to print message at the same time
Cppunit_assert_doubles_equal (expected, actual, Delta) //When the difference between expected and actual is greater than delta failure

To turn a test function of fixture into a test case, you need to generate a Cppunit::testcaller object. When you finally run the test code for the entire application, you may need to run multiple test functions for one fixture, or even multiple fixture test cases at the same time. In CppUnit, this collection of test cases that run concurrently is called TestSuite. Testrunner, however, runs test cases or TestSuite to manage the lifecycle of all test cases. 3 types of Testrunner are currently available, including:

		Cppunit::textui::testrunner 	//text mode of Testrunner
Cppunit::qtui::testrunner //qt mode of Testrunner
Cppunit::mfcui::testrunner //MFC Way of Testrunner

The following is an example of a text-mode Testrunner:

		Cppunit::textui::testrunner runner;
Cppunit::testsuite *suite= new Cppunit::testsuite ();

Add a test case
Suite->addtest (New Cppunit::testcaller<mathtest> (
"Testadd", Testadd));


Runner.addtest (suite);
Start running, automatically show test progress and test results
Runner.run ("", true); Run all tests and wait

The management of test results, display and other functions involved in another class of objects, mainly for internal testing results, progress management, as well as progress and results of the display. There is no introduction here.

Let's sort out the idea, combine a simple example, and string together the ideas above.




Back to the top of the page


3. Manual Use Steps

The first step is to identify the object fixture the test, and then determine the test case based on its function, process, and previous experience. This step is very important and is directly related to the final effect of the test. Of course, the process of adding test cases is a phased task, after the completion of the code, complete the function of the test case, to ensure that the completion of the function, and then on the part of the possible error, combined with previous experience (such as boundary value test, path coverage test, etc.) to write test cases; Finally, when the bug Complete the test case.

For example, to test the integer addition, first define a new testfixture subclass, Mathtest, and write test code for the test case. When you need to add new test cases later, you just need to add new test functions and modify the setUp and teardown as needed. If you need to test the new fixture, define a new testfixture subclass. Note: The following code is used only to represent the principle and cannot be compiled.

///MathTest.h 
//A testfixture subclass.
Announce:use as your owner risk.
//Author:liqun (liqun@nsfocus.com)
//data:2003-7-5
#include "cppunit/testfixture.h"
class Mathtest : Public Cppunit::testfixture {
Protected:
int m_value1, m_value2;

Public:
Mathtest () {}

//initialization function
void SetUp ();
//scavenging function
void teardown ();

//test addition test function
void Testadd ();
//Can add new test function
};
MathTest.cpp
//A testfixture subclass.
Announce:use as your owner risk.
//Author:liqun (liqun@nsfocus.com)
//data:2003-7-5
#include "MathTest.h"
#include "Cppunit/testasse Rt.h '
void Mathtest::setup ()
{
m_value1 = 2;
M_value2 = 3;
}
void Mathtest::teardown ()
{
}
void Mathtest::testadd ()
{
int result = m_value1 + M_VALUE2;
Cppunit_assert (Result = = 5);
}

Then write the main function, organize the test cases that need to be tested into TestSuite, then run them through Testruner. This part of the code needs to be changed a little when adding new test cases later. Just add the new test cases to the TestSuite.

Main.cpp
Main file for Cppunit test.
Announce:use as your owner risk.
Author : Liqun (liqun@nsfocus.com)
Data : 2003-7-5
Note: Cannot compile, a for study.
#include "MathTest.h"
#include "Cppunit/ui/text/testrunner.h"
#include "Cppunit/testcaller.h"
#include "cppunit/testsuite.h"
int main ()
{
Cppunit::textui::testrunner runner;
Cppunit::testsuite *suite= new Cppunit::testsuite ();

Add a test case
Suite->addtest (New Cppunit::testcaller<mathtest> (
"Testadd", Testadd));


Runner.addtest (suite);
Start running, automatically show test progress and test results
Runner.run ("", true); Run all tests and wait
}





Back to the top of the page


4. Common use mode

In the way above, if you want to add a new test case, you need to add each test case to the TestSuite, and adding a new testfixture needs to add all the header files to the main.cpp, which is cumbersome. For this CppUnit, Cppunit::testsuitebuilder,cppunit::testfactoryregistry and a bunch of macros are provided to facilitate the registration of testfixture and test cases into TestSuite. Here's how it's usually used:

MathTest.h
A Testfixture Subclass.
Announce:use as your owner risk.
Author:liqun (liqun@nsfocus.com)
Data:2003-7-5
#include "Cppunit/extensions/helpermacros.h"
Class Mathtest:public Cppunit::testfixture {
Declare a Testsuite
Cppunit_test_suite (mathtest);
Adding a test case to testsuite, defining a new test case requires a statement here
Cppunit_test (Testadd);
Testsuite Declaration Complete
Cppunit_test_suite_end ();
The rest is unchanged.
Protected
int m_value1, m_value2;

Public
Mathtest () {}

initialization function
void SetUp ();
Cleanup function
void Teardown ();

Test function for test addition
void Testadd ();
You can add a new test function
};
MathTest.cpp
A Testfixture Subclass.
Announce:use as your owner risk.
Author:liqun (liqun@nsfocus.com)
Data:2003-7-5
#include "MathTest.h"
Register this testsuite in the testsuite named "AllTest", if not defined, automatically define
You can also cppunit_test_suite_registration (mathtest) and register to an unnamed testsuite in the global.
Cppunit_test_suite_named_registration (Mathtest, "alltest");
The following is not changed
void Mathtest::setup ()
{
M_value1 = 2;
M_value2 = 3;
}
void Mathtest::teardown ()
{
}
void Mathtest::testadd ()
{
int result = m_value1 + m_value2;
Cppunit_assert (Result = = 5);
}
Main.cpp
Main file for Cppunit test.
Announce:use as your owner risk.
compile:g++-lcppunit MathTest.cpp main.cpp
Run:./a.out
Test:redhat 8.0 CppUnit1.8.0
Author:liqun (a Litthle modification. liqun@nsfocus.com)
Data:2003-7-5
Do not need to include header files for all testfixture subclasses
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
If you do not change testsuite, this file does not need to be changed later.
int main ()
{
Cppunit::textui::testrunner runner;

Gets the specific testsuite from the registered Testsuite, without parameters to get the unnamed testsuite.
Cppunit::testfactoryregistry &registry = cppunit::testfactoryregistry::getregistry ("AllTest");
Add this testsuite to Testrunner
Runner.addtest (Registry.maketest ());
Run Tests
Runner.run ();
}

Adding a new test case just needs to be declared at the beginning of the class definition.




Back to the top of the page


5. Other practical issues

Typically, a test case code is included and the object being tested is in a different project. You should write testfixture in another project (preferably in a different directory), and then include the tested objects in your test project.

When testing a class or function, the testfixture may refer to other classes or other functions, in order to isolate the effects of other parts of the code, you should temporarily define some stubs in the source file to simulate these classes or functions. This code can be used in a test project through a macro definition and is not valid in the project being tested.

Reference CppUnit Home

Junittest infected:programmers Love Writing Tests

CppUnit Cookbook

Xprogramming Home

Test framework

This Code downloads


About the author

Lie group, currently focusing on the development of network security products, research, software development process and so on. You can contact him through liqun@nsfocus.com.


The above is from: IBM Developer Community

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.