Slide 1

Slide 1 text

C++ Testing (how I do it) Testing Lab (Agile Aragón) March 9, 2013 Zaragoza - Spain David Alfonso @davidag

Slide 2

Slide 2 text

C++ compiled, multi-paradigm, static typing, high- performance apps,...

Slide 3

Slide 3 text

Types of tests Unit Tests, Integration Tests, Usability Tests (not many), Performance Tests,...

Slide 4

Slide 4 text

Open Source Tools Continuous Integration (BuildBot) xUnit Framework (Google Test & Mock) Static Analysis (cppcheck) Dynamic Analysis (valgrind) VCS (CVS & Git)

Slide 5

Slide 5 text

xUnit Frameworks ...a lot to choose from... Boost Test Library UnitTest++ CppUnit CppUnitLite

Slide 6

Slide 6 text

Google Test + Google Mock open source, multiplatform, easy to start with, powerful,...

Slide 7

Slide 7 text

Google Test state-based testing SUT

Slide 8

Slide 8 text

TEST(StackTest, IsEmptyInitially) { Stack s; ASSERT_EQ(0, s.size()); } TEST(StackTest, PushWorks) { Stack s; s.push(5); ASSERT_EQ(1, s.size()); } Test case

Slide 9

Slide 9 text

Google Mock interaction-based testing SUT A' B'

Slide 10

Slide 10 text

// SUT = Race TurtleMock turtle; EXPECT_CALL(turtle, Move(Gt(0))) .Times(AtLeast(1)) .WillOnce(Return(true)) .WillRepeatedly(Return(false) ); Race race(turtle); race.runOneStep();

Slide 11

Slide 11 text

// SUT = Race TurtleMock turtle; EXPECT_CALL(turtle, Move(Gt(0))) .Times(AtLeast(1)) .WillOnce(Return(true)) .WillRepeatedly(Return(false) ); Race race(turtle); race.runOneStep(); EXPECT_CALL(mock_obj, method(matchers)) .Times(cardinality) .WillOnce(action) .WillRepeatedly(action);

Slide 12

Slide 12 text

Techniques to put tests in place

Slide 13

Slide 13 text

New code Aim: Testable code SOLID & GRASP principles, design patterns, TDD, etc.

Slide 14

Slide 14 text

Dependency Injection programming against abstractions

Slide 15

Slide 15 text

// Constructor DI class Data { public: bool empty() = 0; int count() = 0; }; class ConcreteData : public Data {...}; class FakeData : public Data {...}; class Processor { public: Processor(Data* data); };

Slide 16

Slide 16 text

// Setter DI class Data { public: bool empty() = 0; int count() = 0; }; class ConcreteData : public Data {...}; class FakeData : public Data {...}; class Processor { public: Processor(); void SetData(Data* data) { d_ = d; }

Slide 17

Slide 17 text

// Template DI template class Processor { public: Processor(); private: T data_; }; // Production code Processor p; // Testing code Processor p;

Slide 18

Slide 18 text

Legacy code characterization tests, not too strict about FIRST principles of unit testing, I prefer to have classes in test harnesses

Slide 19

Slide 19 text

Decoupling dependencies using preprocessing and linking stages Legacy Code

Slide 20

Slide 20 text

// Preprocessing // DbRecord.cpp #include "DbRecord.h" #include "DbDefs.h" ... Mysql::connect(host); ... Legacy Code #ifdef TESTING Mysql::connect() {} #else #include "Mysql.h" #endif

Slide 21

Slide 21 text

// Preprocessing // DbRecord.cpp #include "Pre.h" #include "DbRecord.h" ... // DbRecordTests.cpp #include "Pre.h" #include "DbRecord.h" class MysqlStub { ... }; ... // Pre.h -> Different in tests // than in production code #define Mysql MysqlStub Legacy Code

Slide 22

Slide 22 text

// Linking // BFake.cpp class B { ... }; // ATests.cpp #include "A.h" // It will include "B.h" TEST(...) { } // Compile BFake.cpp instead of B.cpp Legacy Code

Slide 23

Slide 23 text

Accessing private methods and variables Sometimes you don't have a choice... Legacy Code

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

// Option 1: Review your design!!!

Slide 26

Slide 26 text

// Option 1: Review your design!!! // Option 2: Getters class A { public: const Obj& getObject() const { return obj; } private: Obj obj; };

Slide 27

Slide 27 text

// Option 1: Review your design!!! // Option 2: Getters // Option 3: Add testing functions class A { public: ... bool DoSomeCheckUsingPrivateStuff(); private: ... };

Slide 28

Slide 28 text

// Option 1: Review your design!!! // Option 2: Getters // Option 3: Add testing functions // Option 4: Make some friends :) class MyClass { private: // Google Test macro FRIEND_TEST(MyClassTest, MyMethod); };

Slide 29

Slide 29 text

// Option 1: Review your design!!! // Option 2: Getters // Option 3: Add testing functions // Option 4: Make some friends :) // Option 5: Redefine private/protected // MyClassTests.cpp #define private public #include "MyClass.h" MyClass my_class; my_class.private_method();

Slide 30

Slide 30 text

Thank you :)