6. System under test In many circumstances, the environment or context in which the system under test (SUT) operates very much influences the behavior of the SUT . In other cases, we must peer "inside"(Technically, the SUT is whatever software we are testing and doesn't include anything it depends on so "inside" is a misnomer. It is better to think of the depended-on component (DOC) that is the destination of indirect outputs as being "behind" the SUT . the SUT to be able to determine whether the expected behavior has occurred. A Mock Object is a powerful way to implement Behavior Verification while avoiding Test Code Duplication between similar tests by delegating the job of verifying the indirect outputs of the SUT entirely to a Test Double . First, we define a Mock Object that implements the same interface as an object on which the SUT depends. Then, during the test, we configure the Mock Object with the values with which it should respond to the SUT and the method calls (complete with expected arguments) to expect from the SUT . Before exercising the SUT , we install the Mock Object so that the SUT uses it instead of the real implementation. When called during SUT execution, the Mock Object compares the actual arguments received with the expected arguments using Equality Assertions and fails the test if they don't match. The test need not do any assertions at all!
7. Test double Test Doubles are used for many reasons during the development of Fully Automated Tests The behavior of the Test Double may vary from test to test. There are many ways to define this behavior. When the Test Double is very simple and/or very specific to a single test, the simplest solution is often to hard-code the behavior right into the Test Double . The Test Double has all its behavior hard-coded right into it by the test automater . That is, if it needs to return a value for a method call, the value is hard-coded into the return statement. If it needs to verify that a certain parameter had a specific value, the assertion is hard-coded with the value that is expected. http://xunitpatterns.com/Hard-Coded%20Test%20Double.html
8. Test stub We replace a real object with a test-specific object that feeds the desired indirect inputs into the system under test. In many circumstances, the environment or context in which the system under test (SUT) operates very much influences the behavior of the SUT . To get good enough control over the indirect inputs of the SUT , we may have to replace some of the context with something we can control, a Test Stub . First, we define a test-specific implementation of an interface on which the SUT depends. This implementation is configured to respond to calls from the SUT with the values (or exceptions) that will exercise the Untested Code within the SUT . Before exercising the SUT , we install the Test Stub so that the SUT uses it instead of the real implementation. When called by the SUT during test execution, the Test Stub returns the previously defined values. The test can then verify the expected outcome in the normal way. http://xunitpatterns.com/Test%20Stub.html
9. Fragile test We have one or more tests that used to run and pass which either fail to compile and run or fail when they are run. When we have changed the behavior of the SUT in question this change in test results is expected, but when we don't think the change should have affected the tests that are failing or we haven't changed any production code or tests we then have a case of Fragile Test . Past efforts at automated testing have often run afoul of the "four sensitivities" of automated tests. These sensitivities are what cause Fully Automated Tests that previously passed to suddenly start failing. The root cause for tests failing can be loosely classified into one of these four "sensitivities". Each sensitivity may be cause by a variety of specific test coding behaviors but it is useful to understand the sensitivities in their own right. http://xunitpatterns.com/Fragile%20Test.html#Overspecified Software
10.
11.
12.
13.
14.
15.
16. Tutorial Using Google Mock is easy! Inside your C++ source file, just #include "gtest/gtest.h" and "gmock/gmock.h", and you are ready to go.
17.
18.
19. Writing a Mock Class You don't need to define these mock methods somewhere else - the MOCK_METHOD* macros will generate the definitions for you. It's that simple! Once you get the hang of it, you can pump out mock classes faster than your source-control system can handle your check-ins. Tip: If even this is too much work for you, you'll find the gmock_gen.py tool in Google Mock's scripts/generator/ directory (courtesy of the cppclean project) useful. This command-line tool requires that you have Python 2.4 installed. You give it a C++ file and the name of an abstract class defined in it, and it will print the definition of the mock class for you. Due to the complexity of the C++ language, this script may not always work, but it can be quite handy when it does. .hpp file Mock_class http://googlemock.googlecode.com/svn-history/r294/trunk/scripts/generator/
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32. Matchers A matcher matches a single argument. You can use it inside ON_CALL() or EXPECT_CALL() , or use it to validate a value directly: Built-in matchers (where argument is the function argument) are divided into several categories: Wildcard EXPECT_THAT(value, matcher) Asserts that value matches matcher . ASSERT_THAT(value, matcher) The same as EXPECT_THAT(value, matcher) , except that it generates a fatal failure. _ argument can be any value of the correct type. A<type>() or An<type>() argument can be any value of type type .
33. Matchers Generic Comparison Except Ref() , these matchers make a copy of value in case it's modified or destructed later. If the compiler complains that value doesn't have a public copy constructor, try wrap it in ByRef() , e.g. Eq(ByRef(non_copyable_value)) . If you do that, make sure non_copyable_value is not changed afterwards, or the meaning of your matcher will be changed. Eq(value) or value argument == value Ge(value) argument >= value Gt(value) argument > value Le(value) argument <= value Lt(value) argument < value Ne(value) argument != value IsNull() argument is a NULL pointer (raw or smart). NotNull() argument is a non-null pointer (raw or smart). Ref(variable) argument is a reference to variable . TypedEq<type>(value) argument has type type and is equal to value . You may need to use this instead of Eq(value) when the mock function is overloaded.
34. Matchers Floating-Point Matchers These matchers use ULP-based comparison (the same as used in Google Test ). They automatically pick a reasonable error bound based on the absolute value of the expected value. DoubleEq() and FloatEq() conform to the IEEE standard, which requires comparing two NaNs for equality to return false. The NanSensitive* version instead treats two NaNs as equal, which is often what a user wants. DoubleEq(a_double) argument is a double value approximately equal to a_double , treating two NaNs as unequal. FloatEq(a_float) argument is a float value approximately equal to a_float , treating two NaNs as unequal. NanSensitiveDoubleEq(a_double) argument is a double value approximately equal to a_double , treating two NaNs as equal. NanSensitiveFloatEq(a_float) argument is a float value approximately equal to a_float , treating two NaNs as equal.
35. Matchers String Matchers ¶ The argument can be either a C string or a C++ string object: StrCaseEq() , StrCaseNe() , StrEq() , and StrNe() work for wide strings as well. ContainsRegex(string) argument matches the given regular expression. EndsWith(suffix) argument ends with string suffix . HasSubstr(string) argument contains string as a sub-string. MatchesRegex(string) argument matches the given regular expression with the match starting at the first character and ending at the last character. StartsWith(prefix) argument starts with string prefix . StrCaseEq(string) argument is equal to string , ignoring case. StrCaseNe(string) argument is not equal to string , ignoring case. StrEq(string) argument is equal to string . StrNe(string) argument is not equal to string .
36.
37. Matchers Member Matchers Matching the Result of a Function or Functor Pointer Matchers Multiargument Matchers Technically, all matchers match a single value. A "multi-argument" matcher is just one that matches a tuple . The following matchers can be used to match a tuple (x, y) : Field(&class::field, m) argument.field (or argument->field when argument is a plain pointer) matches matcher m , where argument is an object of type class . Key(e) argument.first matches e , which can be either a value or a matcher. E.g. Contains(Key(Le(5))) can verify that a map contains a key <= 5 . Pair(m1, m2) argument is an std::pair whose first field matches m1 and second field matches m2 . Property(&class::property, m) argument.property() (or argument->property() when argument is a plain pointer) matches matcher m , where argument is an object of type class . ResultOf(f, m) f(argument) matches matcher m , where f is a function or functor. Pointee(m) argument (either a smart pointer or a raw pointer) points to a value that matches matcher m .
38. Matchers Multiargument Matchers Technically, all matchers match a single value. A "multi-argument" matcher is just one that matches a tuple . The following matchers can be used to match a tuple (x, y) : You can use the following selectors to pick a subset of the arguments (or reorder them) to participate in the matching: Eq() x == y Ge() x >= y Gt() x > y Le() x <= y Lt() x < y Ne() x != y AllArgs(m) Equivalent to m . Useful as syntactic sugar in .With(AllArgs(m)) . Args<N1, N2, ..., Nk>(m) The tuple of the k selected (using 0-based indices) arguments matches m , e.g. Args<1, 2>(Eq()) .
39. Matchers Composite Matchers You can make a matcher from one or more other matchers: Adapters for Matchers Matchers as Predicates AllOf(m1, m2, ..., mn) argument matches all of the matchers m1 to mn . AnyOf(m1, m2, ..., mn) argument matches at least one of the matchers m1 to mn . Not(m) argument doesn't match matcher m . MatcherCast<T>(m) casts matcher m to type Matcher<T> . SafeMatcherCast<T>(m) safely casts matcher m to type Matcher<T> . Truly(predicate) predicate(argument) returns something considered by C++ to be true, where predicate is a function or functor. Matches(m) a unary functor that returns true if the argument matches m . ExplainMatchResult(m, value, result_listener) returns true if value matches m , explaining the result to result_listener . Value(x, m) returns true if the value of x matches m .
40.
41. Actions Actions specify what a mock function should do when invoked. Returning a Value Return() Return from a void mock function. Return(value) Return value . If the type of value is different to the mock function's return type, value is converted to the latter type at the time the expectation is set , not when the action is executed. ReturnArg<N>() Return the N -th (0-based) argument. ReturnNew<T>(a1, ..., ak) Return new T(a1, ..., ak) ; a different object is created each time. ReturnNull() Return a null pointer. ReturnPointee(ptr) Return the value pointed to by ptr . ReturnRef(variable) Return a reference to variable . ReturnRefOfCopy(value) Return a reference to a copy of value ; the copy lives as long as the action.
42. Actions Side Effects Assign(&variable, value) Assign value to variable. DeleteArg<N>() Delete the N -th (0-based) argument, which must be a pointer. SaveArg<N>(pointer) Save the N -th (0-based) argument to *pointer . SaveArgPointee<N>(pointer) Save the value pointed to by the N -th (0-based) argument to *pointer . SetArgReferee<N>(value) Assign value to the variable referenced by the N -th (0-based) argument. SetArgPointee<N>(value) Assign value to the variable pointed by the N -th (0-based) argument. SetArgumentPointee<N>(value) Same as SetArgPointee<N>(value) . Deprecated. Will be removed in v1.7.0. SetArrayArgument<N>(first, last) Copies the elements in source range [ first , last ) to the array pointed to by the N -th (0-based) argument, which can be either a pointer or an iterator. The action does not take ownership of the elements in the source range. SetErrnoAndReturn(error, value) Set errno to error and return value . Throw(exception) Throws the given exception, which can be any copyable value. Available since v1.1.0.
43.
44. Actions Default Action Note: due to technical reasons, DoDefault() cannot be used inside a composite action - trying to do so will result in a run-time error. Composite Actions Defining Actions The ACTION* macros cannot be used inside a function or class. DoDefault() Do the default action (specified by ON_CALL() or the built-in one). DoAll(a1, a2, ..., an) Do all actions a1 to an and return the result of an in each invocation. The first n - 1 sub-actions must return void. IgnoreResult(a) Perform action a and ignore its result. a must not return void. WithArg<N>(a) Pass the N -th (0-based) argument of the mock function to action a and perform it. WithArgs<N1, N2, ..., Nk>(a) Pass the selected (0-based) arguments of the mock function to action a and perform it. WithoutArgs(a) Perform action a without any arguments. ACTION(Sum) { return arg0 + arg1; } Defines an action Sum() to return the sum of the mock function's argument #0 and #1. ACTION_P(Plus, n) { return arg0 + n; } Defines an action Plus(n) to return the sum of the mock function's argument #0 and n . ACTION_Pk(Foo, p1, ..., pk) { statements; } Defines a parameterized action Foo(p1, ..., pk) to execute the given statements .
45. Cardinalities These are used in Times() to specify how many times a mock function will be called: AnyNumber() The function can be called any number of times. AtLeast(n) The call is expected at least n times. AtMost(n) The call is expected at most n times. Between(m, n) The call is expected between m and n (inclusive) times. Exactly(n) or n The call is expected exactly n times. In particular, the call should never happen when n is 0.
46.
47.
48.
49.
50. Flags --gmock_catch_leaked_mocks=0 Don't report leaked mock objects as failures. --gmock_verbose=LEVEL Sets the default verbosity level ( info , warning , or error ) of Google Mock messages.
51.
52.
53. Using Mocks in Tests If you want to use something other than Google Test (e.g. CppUnit or CxxTest) as your testing framework, just change the main() function in the previous section to: int main(int argc, char** argv) { // The following line causes Google Mock to throw an exception on failure, // which will be interpreted by your testing framework as a test failure. ::testing::GTEST_FLAG(throw_on_failure) = true; ::testing::InitGoogleMock(&argc, argv); ... whatever your testing framework requires ... } This approach has a catch: it makes Google Mock throw an exception from a mock object's destructor sometimes. With some compilers, this sometimes causes the test program to crash. You'll still be able to notice that the test has failed, but it's not a graceful failure. A better solution is to use Google Test's event listener API to report a test failure to your testing framework properly. You'll need to implement theOnTestPartResult() method of the event listener interface, but it should be straightforward. If this turns out to be too much work, we suggest that you stick with Google Test, which works with Google Mock seamlessly (in fact, it is technically part of Google Mock.). If there is a reason that you cannot use Google Test, please let us know.
56. Hellomain.c /* * hellomain.c */ #include <stdlib.h> #include <string> #include "helloworld.h" using namespace std; int main(void) { helloworld(); /* exiting with anything other than 0 means the test failed */ exit(EXIT_SUCCESS); }
57. Unittest.c for gtest 1/2 /* * unittest.c */ #include <stdlib.h> #include <string> #include "helloworld.h" #include <gtest/gtest.h> using namespace std; void init() { /* any initialization should be done here */ } /* This is an example test that should always pass. * See the GoogleTest documentation for more information * about writing tests. */ TEST(HelloWord, Test1) { EXPECT_EQ(helloworld(), string("Hello World!")); }
58. Unittest.c for gtest 2/2 /*============================================================ * You shouldn't need to modify anything below this line *============================================================ */ int runtests() { return RUN_ALL_TESTS(); } int main(int argc, char *argv[]) { ::testing::InitGoogleTest(&argc, argv); /* main() doesn't return RUN_ALL_TESTS() results since the standard Hudson CI server treats autotools's standard Makefile "check" target as a single build rather than discriminating between unit test builds and runs. If main() returned RUN_ALL_TESTS() failures, then the standard Hudson CI server would abort and never report the corresponding Junit XML failure reports. */ (void)runtests(); return 0; }
59. Unitmock.c for gmock 1/4 /* * unitmock.c */ #include <stdlib.h> #include <string> #include "helloworld.h" #include <gmock/gmock.h> #include <gtest/gtest.h> using namespace std; using ::testing::AtLeast; /* interface abstract class */ class Hello { public: virtual ~Hello() {} virtual void HelloWorld() = 0; }; /* Depended-On Component Mock Object class */ class MockHello : public Hello { public: MockHello() {} MOCK_METHOD0(HelloWorld, void()); };
60. Unitmock.c for gmock 2/4 /* System-Under-Test class */ class Sut : public Hello { public: Sut() {} Sut(Hello* hello) {h = hello;} virtual ~Sut() {} virtual void HelloWorld(); private: Hello* h; }; void Sut::HelloWorld() { h->HelloWorld(); return; } void init() { /* any initialization should be done here */ }
61. Unitmock.c for gmock 3/4 /* * This is an example test that should always pass. * See the GoogleTest documentation for more information * about writing tests. */ TEST(HelloWord, TestMock) { /* Mock Object instantiation */ MockHello doc; /* Mock Object expectation */ EXPECT_CALL(doc, HelloWorld()).Times(AtLeast(1)); /* Mock Object dependency injection installation */ Sut sut(&doc); /* Exercise Mock Object */ sut.HelloWorld(); } /*============================================================ * You shouldn't need to modify anything below this line *============================================================ */ int runtests() { return RUN_ALL_TESTS(); }
62. Unitmock.c for gmock 4/4 int main(int argc, char *argv[]) { ::testing::InitGoogleMock(&argc, argv); /* main() doesn't return RUN_ALL_TESTS() results since the standard Hudson CI server treats autotools's standard Makefile "check" target as a single build rather than discriminating between unit test builds and runs. If main() returned RUN_ALL_TESTS() failures, then the standard Hudson CI server would abort and never report the corresponding Junit XML failure reports. */ (void)runtests(); return 0; }
64. Yet another presentation about g{test/mock} http://accu.org/content/conf2010/GoogleTestGoogleMock_SebRose.zip Googletest and Googlemock C++ libraries by Seb Rose from IBM Google released the Googletest library for C++ in mid 2008 and it joined a long list of Unit Test frameworks. The developers had concentrated on making the framework powerful and highly portable and released it under a very relaxed open source license. The library is well thought out, and easy to pick up by anyone familiar with other popular unit testing frameworks. In early 2009 they followed this by releasing the Googlemock mocking library, which is the icing on the cake. C++ developers now have access to a library that provides many of the mocking features that users of languages that provide reflection have had for years. This session will give you an in depth tour of these libraries, pointing out their strengths and shortcomings. Familiarity with C++ is a precondition, but no knowledge of Unit Testing frameworks or TDD is necessary.
68. Generator The Google Mock class generator is an application that is part of cppclean. For more information about cppclean, see the README.cppclean file or visit http://code.google.com/p/cppclean/ cppclean requires Python 2.3.5 or later. If you don't have Python installed on your system, you will also need to install it. You can download Python from: http://www.python.org/download/releases/ To use the Google Mock class generator, you need to call it on the command line passing the header file and class for which you want to generate a Google Mock class. Make sure to install the scripts somewhere in your path. Then you can run the program. gmock_gen.py header-file.h [ClassName]... If no ClassNames are specified, all classes in the file are emitted. To change the indentation from the default of 2, set INDENT in the environment. For example to use an indent of 4 spaces: INDENT=4 gmock_gen.py header-file.h ClassName This version was made from SVN revision 281 in the cppclean repository. Known Limitations: Not all code will be generated properly. For example, when mocking templated classes, the template information is lost. You will need to add the template information manually. Not all permutations of using multiple pointers/references will be rendered properly. These will also have to be fixed manually.