Software validation checks that the software product satisfies or fits the intended use, i.e., the software meets the user requirements, not as needs of those who will operate the software only; but, as the needs of all the stakeholders (such as users, operators, administrators, managers, investors, etc.).

There are two ways to perform software validation: internal and external.

If the software meets the requirement specification, it has been internally validated. External validation happens when it is performed by asking the stakeholders if the software meets their needs.

Successful final external validation occurs when all the stakeholders accept the software product and express that it satisfies their needs.

Black Box Testing

Black Box Testing is a software testing method in which the internal structure/ design/ implementation of the item being tested is NOT known to the tester. Eg. Acceptance Testing, System Testing

White Box Testing

White Box Testing is a software testing method in which the internal structure/ design/ implementation of the item being tested is known to the tester. Eg. Unit Testing, Integration Testing

Unit Testing

A unit is the smallest testable part of software. It usually has one or a few inputs and usually a single output. In procedural programming a unit may be an individual program, function, procedure, etc. In object-oriented programming, the smallest unit is a method, which may belong to a base/ super class, abstract class or derived/ child class.

Integration Testing

Integration Testing is a level of software testing where individual units are combined and tested as a group. The purpose of this level of testing is to expose faults in the interaction between integrated units.

System Testing

The process of testing an integrated system to verify that it meets specified
requirements.

Acceptance Testing

The purpose of this test is to evaluate the system’s compliance with the requirements whether it is acceptable for delivery.

Why should we write unit tests?

  • Speed up development (Test driven development vs Debug later development)

A loosely coupled system is one in which each of its components has little or no knowledge of the definitions of other separate components.

Unit testing in C++ & Boost.Test

If you have many test cases in one program, then their maintenance could be hard. Boost.Test, like other frameworks, allows to group several test cases into test suite — this allows to work with them in easier way.

BOOST_AUTO_TEST_SUITE(suite1)

BOOST_AUTO_TEST_CASE(test1) {
BOOST_CHECK_EQUAL(2+2, 4);
}

BOOST_AUTO_TEST_CASE(test2) {
BOOST_CHECK_EQUAL(2*2, 4);
}

BOOST_AUTO_TEST_SUITE_END()

Basic macros (BOOST_WARN, BOOST_CHECK, and BOOST_REQUIRE) accept only one argument — expression to check, like following:

BOOST_WARN( sizeof(int) == sizeof(short) );
BOOST_CHECK( i == 1 );
BOOST_REQUIRE( i > 5 );

Mocking frameworks for C++

Google mock follows standard workflow of mocking:

  • create a mock object for given class — there are many macros to declare mocked functions. There is also a tool, that can generate mock definition from your source code;

We need to have class, that we’ll mock. This should be virtual class, so Google mock will able to override methods in it:

class PropHolder {
public:
PropHolder() { }
virtual ~PropHolder() { }

virtual void SetProperty(const std::string& name, int value) = 0;
virtual int GetProperty(const std::string& name) = 0;
};

This class will be used by functions in another class, that will store reference to instance of our base class PropHolder:

class TestClass {
public:
TestClass(PropHolder& ph) : fPropHolder(ph) { }
void doCalc() {
if (fPropHolder.GetProperty(std::string("test")) > 100) {
fPropHolder.SetProperty("test2", 555);
} else
fPropHolder.SetProperty("test2", 785);
}
private:
PropHolder& fPropHolder;
};

Now we need to create mocked class, that is inherited from PropHolder, and uses macros to implement corresponding stubs. Google mock provides different macros — MOCK_METHODN, MOCK_CONST_METHODN, where last Nshould match to number of arguments of mocked function. First argument of these macros is a name of method to mock, and second — function's signature:

class MockPropHolder : public PropHolder {
public:
MockPropHolder() { }
virtual ~MockPropHolder() { }
MOCK_METHOD2(SetProperty, void(const std::string& name, int value));
MOCK_METHOD1(GetProperty, int(const std::string& name));
};

Now we can use mocked class in our test. We create an instance of mocked class called mholder, and will set expectations on it. First expectation is that function GetProperty will be called once with parameter "test", and mocked object should return 101 for this call. The second expectation specifies that SetProperty function will be called with two arguments — "test2" and 555. After setting expectation, we create an instance of our TestClassand pass reference to mocked object to it. And last line — call of function doCalc, that uses functions from PropHolder class:

BOOST_AUTO_TEST_CASE(test_gmock) {
using ::testing::Return;
MockPropHolder mholder;
EXPECT_CALL(mholder, GetProperty(std::string("test"))).Times(1).WillOnce(Return(101));
EXPECT_CALL(mholder, SetProperty(std::string("test2"),555));
TestClass t(mholder);
t.doCalc();
}

Source: http://alexott.net/en/cpp/CppTestingIntro.html