Unit Testing & GoogleTest Guide
Unit Testing & GoogleTest Guide
System UI
API/
Integration/
Component/
Unit
Test Suite Design
● Objectives
– Functional correctness
– Nonfunctional attributes (performance, ...)
● Components – The Automated Testing Pyramid
System UI
API/
Integration/
Component/
Unit
Test Suite Design
● Objectives
– Functional correctness
– Nonfunctional attributes (performance, ...)
● Components – The Automated Testing Pyramid
System UI
API/
Integration/
Component/
Unit
Test Suite Design
● Objectives
– Functional correctness
– Nonfunctional attributes (performance, ...)
● Components – The Automated Testing Pyramid
System UI
API/
Integration/
Component/
Unit
Test Suite Design
● Objectives
– Functional correctness
– Nonfunctional attributes (performance, ...)
● Components – The Automated Testing Pyramid
Integrated
System UI
API/
Integration/
Component/
Isolated Unit
Test Suite Design
● Objectives
– Functional correctness
– Nonfunctional attributes (performance, ...)
● Components – The Automated Testing Pyramid
Integrated Slow
System UI
API/
Integration/
Component/
Isolated Unit Fast
Test Suite Design
● Objectives
– Functional correctness
– Nonfunctional attributes (performance, ...)
● Components – The Automated Testing Pyramid
Integrated Slow
System UI
API/
Integration/
Component/
Isolated Unit Fast
Levels of Testing
● Many different levels of testing can be considered:
– Unit Tests
– Integration Tests
– System Tests
– Acceptance Tests
– …
10
Levels of Testing
● Many different levels of testing can be considered:
– Unit Tests
– Integration Tests
– System Tests
– Acceptance Tests
– …
● The simplest of these is Unit Testing
– Testing the smallest possible fragments of a program
11
Unit Testing
● Try to ensure that the functionality of each component works in
isolation
12
Unit Testing
● Try to ensure that the functionality of each component works in
isolation
– Unit Test a car:
Wheels work. Steering wheel works....
13
Unit Testing
● Try to ensure that the functionality of each component works in
isolation
– Unit Test a car:
Wheels work. Steering wheel works....
– Integration Test a car:
Steering wheel turns the wheels....
14
Unit Testing
● Try to ensure that the functionality of each component works in
isolation
– Unit Test a car:
Wheels work. Steering wheel works....
– Integration Test a car:
Steering wheel turns the wheels....
– System Test a car:
Driving down the highway with the air conditioning on works...
15
Unit Testing
● Try to ensure that the functionality of each component works in
isolation
– Unit Test a car:
Wheels work. Steering wheel works....
– Integration Test a car:
Steering wheel turns the wheels....
– System Test a car:
Driving down the highway with the air conditioning on works....
● Not testing how well things are glued together.
16
Unit Testing
● Try to ensure that the functionality of each component works in
isolation
– Unit Test a car:
Wheels work. Steering wheel works....
– Integration Test a car:
Steering wheel turns the wheels....
– System Test a car:
Driving down the highway with the air conditioning on works....
● Not testing how well things are glued together.
● In practice, there is a lot more debate on this than you might expect
17
Unit Testing
● Try to ensure that the functionality of each component works in
isolation
– Unit Test a car:
Wheels work. Steering wheel works....
– Integration Test a car:
Steering wheel turns the wheels....
– System Test a car:
Driving down the highway with the air conditioning on works....
● Not testing how well things are glued together.
● In practice, there is a lot more debate on this than you might expect
– Degrees of isolation
18
Unit Testing
● Try to ensure that the functionality of each component works in
isolation
– Unit Test a car:
Wheels work. Steering wheel works....
– Integration Test a car:
Steering wheel turns the wheels....
– System Test a car:
Driving down the highway with the air conditioning on works....
● Not testing how well things are glued together.
● In practice, there is a lot more debate on this than you might expect
– Degrees of isolation
– Big & Small vs Unit & Integration
19
Unit Testing
● Try to ensure that the functionality of each component works in
isolation
– Unit Test a car:
Wheels work. Steering wheel works....
– Integration Test a car:
Steering wheel turns the wheels....
– System Test a car:
Driving down the highway with the air conditioning on works....
● Not testing how well things are glued together.
● In practice, there is a lot more debate on this than you might expect
–
The rapid feedback advantage
Degrees of isolation
– Big & Smallof vs
unitUnit
tests persists for refactoring,
& Integration
– ... but there are judgement calls. 20
Unit Tests
● A dual view:
– They specify the expected behavior of individual components
21
Unit Tests
● A dual view:
– They specify the expected behavior of individual components
– An executable specification
22
Unit Tests
● A dual view:
– They specify the expected behavior of individual components
– An executable specification
● Can even be built first & used to guide development
– Usually called Test Driven Development
23
Unit Tests
● A dual view:
– They specify the expected behavior of individual components
– An executable specification
● Can even be built first & used to guide development
– Usually called Test Driven Development
24
Unit Tests
● Some guiding principles:
– Focus on one component in isolation
– Be simple to set up & run
– Be easy to understand
25
Unit Tests
● Some guiding principles:
– Focus on one component in isolation
– Be simple to set up & run
– Be easy to understand
● Usually managed by some automating framework ....
26
GoogleTest
● Increasingly used framework for C++
– Not dissimilar from JUnit, which you have already seen.
27
GoogleTest
● Increasingly used framework for C++
– Not dissimilar from JUnit, which you have already seen.
● Test cases are written as functions:
TEST(TriangleTest, isEquilateral) {
Triangle tri{2,2,2};
EXPECT_TRUE(tri.isEquilateral());
}
28
GoogleTest
● Increasingly used framework for C++
– Not dissimilar from JUnit, which you have already seen.
● Test cases are written as functions:
TEST(TriangleTest, isEquilateral) {
Triangle tri{2,2,2};
EXPECT_TRUE(tri.isEquilateral());
}
30
GoogleTest
● Increasingly used framework for C++
– Not dissimilar from JUnit, which you have already seen.
● Test cases are written as functions:
The second argument
names individual test cases.
TEST(TriangleTest, isEquilateral) {
Triangle tri{2,2,2};
EXPECT_TRUE(tri.isEquilateral());
}
31
GoogleTest
● Increasingly used framework for C++
– Not dissimilar from JUnit, which you have already seen.
● Test cases are written as functions:
TEST(TriangleTest, isEquilateral) {
Triangle tri{2,2,2};
EXPECT_TRUE(tri.isEquilateral());
}
EXPECT and ASSERT macros
provide correctness oracles.
32
GoogleTest
● Increasingly used framework for C++
– Not dissimilar from JUnit, which you have already seen.
● Test cases are written as functions:
TEST(TriangleTest, isEquilateral) {
Triangle tri{2,2,2};
EXPECT_TRUE(tri.isEquilateral());
}
ASSERT oracles terminate the program when they fail.
EXPECT oracles allow the program to continue running. 33
GoogleTest
● Increasingly used framework for C++
– Not dissimilar from JUnit, which you have already seen.
● Test cases are written as functions.
● TEST() cases are automatically registered with GoogleTest and are
executed by the test driver.
34
GoogleTest
● Increasingly used framework for C++
– Not dissimilar from JUnit, which you have already seen.
● Test cases are written as functions.
● TEST() cases are automatically registered with GoogleTest and are
executed by the test driver.
● Some tests require common setUp & tearDown
– Group them into test fixtures
– A fresh fixture is created for each test
35
GoogleTest
● Increasingly used framework for C++
– Not dissimilar from JUnit, which you have already seen.
● Test cases are written as functions.
● TEST() cases are automatically registered with GoogleTest and are
executed by the test driver.
● Some tests require common setUp & tearDown
– Group them into test fixtures
– A fresh fixture is created for each test
– Fixtures enable using the same configuration for multiple tests
36
GoogleTest - Fixtures
class StackTest : public ::testing::Test {
protected:
void SetUp() override {
s1.push(1);
s2.push(2);
s2.push(3);
}
Stack<int> s1;
Stack<int> s2;
};
Derive from the fixture base class 37
GoogleTest - Fixtures
class StackTest : public ::testing::Test {
protected:
void SetUp() override {
s1.push(1);
s2.push(2);
s2.push(3);
}
Stack<int> s1;
Stack<int> s2;
}; SetUp() will be called before
all tests using the fixture 38
GoogleTest - Fixtures
class StackTest : public ::testing::Test {
protected:
void SetUp() override {
s1.push(1);
s2.push(2);
s2.push(3);
}
Stack<int> s1;
Stack<int> s2;
}; TearDown() will be called after
all tests using the fixture 39
GoogleTest - Fixtures
TEST_F(StackTest, popOfOneIsEmpty) {
s1.pop();
EXPECT_EQ(0, s1.size());
}
40
GoogleTest - Fixtures
TEST_F(StackTest, popOfOneIsEmpty) {
s1.pop();
EXPECT_EQ(0, s1.size());
}
41
GoogleTest - Fixtures
TEST_F(StackTest, popOfOneIsEmpty) {
s1.pop();
EXPECT_EQ(0, s1.size());
} {
StackTest t;
t.SetUp();
t.popOfOneIsEmpty();
Behaves like t.TearDown();
}
42
GoogleTest - Fixtures
TEST_F(StackTest, popOfOneIsEmpty) {
s1.pop();
EXPECT_EQ(0, s1.size());
}
43
GoogleTest - Fixtures
TEST_F(StackTest, popOfOneIsEmpty) {
s1.pop();
EXPECT_EQ(0, s1.size());
}
expected
value
44
GoogleTest - Fixtures
TEST_F(StackTest, popOfOneIsEmpty) {
s1.pop();
EXPECT_EQ(0, s1.size());
}
expected observed
value value
45
GoogleTest
● Increasingly used framework for C++
– Not dissimilar from JUnit, which you have already seen.
● Test cases are written as functions.
● TEST() cases are automatically registered with GoogleTest and are
executed by the test driver.
● Some tests require common setUp & tearDown
● Many different assertions and expectations available
ASSERT_TRUE(condition); EXPECT_TRUE(condition);
ASSERT_FALSE(condition); EXPECT_FALSE(condition);
ASSERT_EQ(expected,actual);
ASSERT_NE(val1,val2);
ASSERT_LT(val1,val2);
EXPECT_EQ(expected,actual);
EXPECT_NE(val1,val2);
EXPECT_LT(val1,val2);
…
ASSERT_LE(val1,val2); EXPECT_LE(val1,val2); 46
ASSERT_GT(val1,val2); EXPECT_GT(val1,val2);
ASSERT_GE(val1,val2); EXPECT_GE(val1,val2);
GoogleTest
● Increasingly used framework for C++
– Not dissimilar from JUnit, which you have already seen.
● Test cases are written as functions.
● TEST() cases are automatically registered with GoogleTest and are
executed by the test driver.
● Some tests require common setUp & tearDown
● Many different assertions and expectations available
● More information available online
– github.com/google/googletest/blob/master/googletest/docs/Primer.md
– github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md
47
Designing a Unit Test
● Common structure
Designing a Unit Test
● Common structure
TEST_CASE("empty") {
Environment env;
ExprTree tree;
CHECK(!result.has_value());
}
Designing a Unit Test
● Common structure
TEST_CASE("empty") {
Environment env;
ExprTree tree;
CHECK(!result.has_value());
}
CHECK(!result.has_value());
}
Designing a Unit Test
● Common structure
TEST_CASE("empty") {
Environment env;
ExprTree tree; Run the scenario
auto result = evaluate(tree, env);
CHECK(!result.has_value());
}
Designing a Unit Test
● Common structure
TEST_CASE("empty") {
Environment env;
ExprTree tree;
CHECK(!result.has_value());
} Check the outcome
Designing a Unit Test
● Common structure
TEST_CASE("empty") {
Environment env;
ExprTree tree;
CHECK(!result.has_value());
}
DBConnection
Designing a Unit Test
● Common structure
● Tests should run in isolation
struct Frob {
Frob(Connection& inConn)
: conn{inConn}
{ }
Connection& conn; Dependency injection allows
}; the user of a class to
control its behavior
Connection
DBConnection FakeConnection
Designing a Unit Test
● Common structure
● Tests should run in isolation
struct Frob { TEST_CASE("better test 1") {
Frob(Connection& inConn) FakeDB db;
: conn{inConn} FakeConnection conn = db.connect();
{ } Frob frob{conn};
Connection& conn; ...
}; }
Connection
DBConnection FakeConnection
Designing a Unit Test
● Common structure
● Tests should run in isolation
struct Frob { TEST_CASE("better test 1") {
Frob(Connection& inConn) FakeDB db;
: conn{inConn} FakeConnection conn = db.connect();
{ } Frob frob{conn};
Connection& conn; ...
}; }
Connection
68
Common Patterns (Ammonn & Offutt)
● Checking State
– Final State
● Prepare initial state
● Run test
● Check final state
– Pre and Post conditions
● Check initial state as well as final state
69
Common Patterns (Ammonn & Offutt)
● Checking State
– Final State
● Prepare initial state
● Run test
● Check final state
– Pre and Post conditions
● Check initial state as well as final state
– Relative effects
● Check final state relative to some initial state
70
Common Patterns (Ammonn & Offutt)
● Checking State
– Final State
● Prepare initial state
● Run test
● Check final state
– Pre and Post conditions
● Check initial state as well as final state
– Relative effects
● Check final state relative to some initial state
– Round trips
● Check behavior on transform/inverse transform pairs
71
Common Patterns (Ammonn & Offutt)
● Checking State
– Final State
● Prepare initial state
● Run test
● Check final state
– Pre and Post conditions
● Check initial state as well as final state
– Relative effects
● Check final state relative to some initial state These have become
– Round trips
fundamental for
testing hard software
● Check behavior on transform/inverse transform pairs
72
Common Patterns (Ammonn & Offutt)
● Checking Interactions/Behavior
– Use mocks
73
Common Patterns (Ammonn & Offutt)
● Checking Interactions/Behavior
– Use mocks
● Testing 'fakes' that verify expected interactions
● http://martinfowler.com/articles/mocksArentStubs.html
● http://googletesting.blogspot.ca/2013/03/testing-on-toilet-testing-state-vs.html
74
Common Patterns (Ammonn & Offutt)
● Checking Interactions/Behavior
– Use mocks
● Testing 'fakes' that verify expected interactions
● http://martinfowler.com/articles/mocksArentStubs.html
● http://googletesting.blogspot.ca/2013/03/testing-on-toilet-testing-state-vs.html
75
Common Patterns (Ammonn & Offutt)
● Checking Interactions/Behavior
– Use mocks
● Testing 'fakes' that verify expected interactions
● http://martinfowler.com/articles/mocksArentStubs.html
● http://googletesting.blogspot.ca/2013/03/testing-on-toilet-testing-state-vs.html
77
Testability
● What makes testing hard?
– Not just difficult to get adequacy
– What makes it difficult to write tests?
● Dependencies
– Connections between classes
78
Testability
● What makes testing hard?
– Not just difficult to get adequacy
– What makes it difficult to write tests?
● Dependencies
– Connections between classes
– Singletons
79
Testability
● What makes testing hard?
– Not just difficult to get adequacy
– What makes it difficult to write tests?
● Dependencies
– Connections between classes
– Singletons
– Nondeterminism
80
Testability
● What makes testing hard?
– Not just difficult to get adequacy
– What makes it difficult to write tests?
● Dependencies
– Connections between classes
– Singletons
– Nondeterminism
– Static binding (mitigated by parametric polymorphism)
81
Testability
● What makes testing hard?
– Not just difficult to get adequacy
– What makes it difficult to write tests?
● Dependencies
– Connections between classes
– Singletons
– Nondeterminism
– Static binding
– Mixing construction & application logic
– ...
82
Testability
● What makes testing hard?
– Not just difficult to get adequacy
– What makes it difficult to write tests?
● Dependencies
– Connections between classes
– Singletons
– Nondeterminism
– Static binding
– Mixing construction & application logic
– ...
But solutions exist!
You can design code to be testable! 83
Testability (by example)
● Next week (?) we will work together to improve some difficult to test
code....
84
Testability
● Keys things to notice:
– Mocks & stubs allow us to isolate components under test
85
Testability
● Keys things to notice:
– Mocks & stubs allow us to isolate components under test
– Dependency Injection allows us to use mocks and stubs as necessary
86
Testability
● Keys things to notice:
– Mocks & stubs allow us to isolate components under test
– Dependency Injection allows us to use mocks and stubs as necessary
– But doing this can lead to a lot more work and boilerplate code when
written by hand
87
Testability
● Keys things to notice:
– Mocks & stubs allow us to isolate components under test
– Dependency Injection allows us to use mocks and stubs as necessary
– But doing this can lead to a lot more work and boilerplate code when
written by hand
90
Mocking Framework Example
● Frameworks exist that can automate the boilerplate behind:
– Mocking
e.g. GoogleMock, Mockito, etc.
91
Mocking Framework Example
● Frameworks exist that can automate the boilerplate behind:
– Mocking
● e.g. GoogleMock, Mockito, etc.
– Dependency Injection
e.g. Google Guice, Pico Container, etc.
92
Using GoogleMock
● Steps:
1) Derive a mock class from the class you wish to fake
93
class Thing {
Using GoogleMock public:
virtual int foo(int x);
virtual void bar(int y);
● Steps: };
1) Derive a mock class from the class you wish to fake
94
class Thing {
Using GoogleMock public:
virtual int foo(int x);
virtual void bar(int y);
● Steps: };
1) Derive a mock class from the class you wish to fake
95
class Thing {
Using GoogleMock public:
virtual int foo(int x);
virtual void bar(int y);
● Steps: };
1) Derive a mock class from the class you wish to fake
2) Replace virtual calls with uses of MOCK_METHOD().
96
Using GoogleMock
● Steps:
1) Derive a mock class from the class you wish to fake
2) Replace virtual calls with uses of MOCK_METHOD().
3) Use the mock class in your tests.
97
Using GoogleMock
● Steps:
1) Derive a mock class from the class you wish to fake
2) Replace virtual calls with uses of MOCK_METHOD().
3) Use the mock class in your tests.
4) Specify expectations before use via EXPECT_CALL().
● What arguments? How many times? In what order?
InSequence dummy;
EXPECT_CALL(mockThing, foo(Ge(20)))
.Times(2)
.WillOnce(Return(100))
.WillOnce(Return(200));
EXPECT_CALL(mockThing, bar(Lt(5))); 98
Using GoogleMock
● Steps:
1) Derive a mock class from the class you wish to fake
2) Replace virtual calls with uses of MOCK_METHOD().
3) Use the mock class in your tests.
4) Specify expectations before use via EXPECT_CALL().
●
This is part of the Arrange
What arguments? How many times? In what order?
in AAA.
InSequence dummy;
EXPECT_CALL(mockThing, foo(Ge(20)))
.Times(2)
.WillOnce(Return(100))
.WillOnce(Return(200));
EXPECT_CALL(mockThing, bar(Lt(5))); 99
Using GoogleMock
● Steps:
1) Derive a mock class from the class you wish to fake
2) Replace virtual calls with uses of MOCK_METHOD().
3) Use the mock class in your tests.
4) Specify expectations before use via EXPECT_CALL().
● What arguments? How many times? In what order?
5) Expectations are automatically checked in the destructor of the mock.
100
Using GoogleMock
● Precisely specifying mock behavior
InSequence dummy;
EXPECT_CALL(mockThing, foo(Ge(20)))
.Times(2) // Can be omitted here
.WillOnce(Return(100))
.WillOnce(Return(200));
EXPECT_CALL(mockThing, bar(Lt(5)));
101
Using GoogleMock
● Precisely specifying mock behavior
InSequence dummy;
EXPECT_CALL(mockThing, foo(Ge(20)))
.Times(2) // Can be omitted here
.WillOnce(Return(100))
.WillOnce(Return(200));
EXPECT_CALL(mockThing, bar(Lt(5)));
102
Using GoogleMock
● Precisely specifying mock behavior
InSequence dummy;
EXPECT_CALL(mockThing, foo(Ge(20)))
.Times(2) // Can be omitted here
.WillOnce(Return(100))
.WillOnce(Return(200));
EXPECT_CALL(mockThing, bar(Lt(5)));
103
Using GoogleMock
● Precisely specifying mock behavior
InSequence dummy;
EXPECT_CALL(mockThing, foo(Ge(20)))
.Times(2) // Can be omitted here
.WillOnce(Return(100))
.WillOnce(Return(200));
EXPECT_CALL(mockThing, bar(Lt(5)));
104
Using GoogleMock
● Precisely specifying mock behavior
InSequence dummy;
EXPECT_CALL(mockThing, foo(Ge(20)))
.Times(2) // Can be omitted here
.WillOnce(Return(100))
.WillOnce(Return(200));
EXPECT_CALL(mockThing, bar(Lt(5)));
105
Using GoogleMock
● Precisely specifying mock behavior
InSequence dummy;
EXPECT_CALL(mockThing, foo(Ge(20)))
.Times(2) // Can be omitted here
.WillOnce(Return(100))
.WillOnce(Return(200));
Complex behaviors canbar(Lt(5)));
EXPECT_CALL(mockThing, be checked
using these basic pieces.
106
Using GoogleMock
● Note, GoogleMock can use the same process for creating
both stubs and mocks as well as test fakes in the middle.
107
Using GoogleMock
● Note, GoogleMock can use the same process for creating
both stubs and mocks as well as test fakes in the middle.
● A mock will check that a function is called in the right ways.
108
Using GoogleMock
● Note, GoogleMock can use the same process for creating
both stubs and mocks as well as test fakes in the middle.
● A mock will check that a function is called in the right ways.
● A stub will prevent interaction with external resources and possibly
return fake data.
109
Using GoogleMock
● Note, GoogleMock can use the same process for creating
both stubs and mocks as well as test fakes in the middle.
● A mock will check that a function is called in the right ways.
● A stub will prevent interaction with external resources and possibly
return fake data.
111
Using GoogleMock
● How would I stub out a database connection?
struct Frob {
Frob(Connection& inConn)
: conn{inConn}
{ }
Connection& conn;
int doThing() {
…
x = conn.readValue();
…
}
};
112
Using GoogleMock
● How would I stub out a database connection?
struct Frob {
Frob(Connection& inConn) TEST(FrobTests, doesThing) {
: conn{inConn} FakeDBConnection conn;
{ } EXPECT_CALL(conn, readValue())
Connection& conn; .WillOnce(Return(5));
115
Using GoogleMock
● How would I check (mock) writing to a database connection?
struct Frob {
Frob(Connection& inConn)
: conn{inConn}
{ }
Connection& conn;
int doThing() {
…
conn.writeValue(x);
…
}
};
116
Using GoogleMock
● How would I check (mock) writing to a database connection?
struct Frob {
Frob(Connection& inConn)
: conn{inConn}
TEST(FrobTests, doesThing) {
{ }
FakeDBConnection conn;
Connection& conn;
EXPECT_CALL(conn, writeValue(Eq(42)));
int doThing() {
Frob frob{conn};
…
auto result = frob.doThing();
conn.writeValue(x);
}
…
}
};
117
Using GoogleMock
● How would I check (mock) writing to a database connection?
struct Frob {
Frob(Connection& inConn)
: conn{inConn}
TEST(FrobTests, doesThing) {
{ }
FakeDBConnection conn;
Connection& conn; Arrange
EXPECT_CALL(conn, writeValue(Eq(42)));
int doThing() {
Act Frob frob{conn};
…
auto result = frob.doThing();
conn.writeValue(x);
}
…
}
};
118
Using GoogleMock
● How would I check (mock) writing to a database connection?
struct Frob {
Frob(Connection& inConn)
: conn{inConn}
TEST(FrobTests, doesThing) {
{ }
FakeDBConnection conn;
Connection& conn; Arrange
EXPECT_CALL(conn, writeValue(Eq(42)));
int doThing() {
Act Frob frob{conn};
…
auto result = frob.doThing();
conn.writeValue(x);
}
…
}
}; Assert
119
Summary
● Unit testing provides a way to automate much of the testing process.
120
Summary
● Unit testing provides a way to automate much of the testing process.
● Testing small components bootstraps confidence in the system on
confidence in its constituents.
121
Summary
● Unit testing provides a way to automate much of the testing process.
● Testing small components bootstraps confidence in the system on
confidence in its constituents.
● Tests can verify state or behaviors.
122
Summary
● Unit testing provides a way to automate much of the testing process.
● Testing small components bootstraps confidence in the system on
confidence in its constituents.
● Tests can verify state or behaviors.
● Software must be designed for testing (or designed by testing)
123