SlideShare a Scribd company logo
1 of 129
1
@ClareMacraeUK CPPP Paris June 2019
Quickly Testing Legacy Code
Clare Macrae (She/Her)
CPPP Conference, Paris: 15 June 2019
2
@ClareMacraeUK CPPP Paris June 2019
@ClareMacraeUK
4
@ClareMacraeUK CPPP Paris June 2019
Contents
• Introduction
• Legacy Code
• Golden Master
• Approval Tests
• Example
• Resources
• Summary
5
@ClareMacraeUK CPPP Paris June 2019
6
@ClareMacraeUK CPPP Paris June 2019
7
@ClareMacraeUK CPPP Paris June 2019
18 months of remote pairing later…
8
@ClareMacraeUK CPPP Paris June 2019
Goal:
Share techniques for easier testing
in challenging scenarios
9
@ClareMacraeUK CPPP Paris June 2019
Contents
• Introduction
• Legacy Code
• Golden Master
• Approval Tests
• Example
• Resources
• Summary
10
@ClareMacraeUK CPPP Paris June 2019
Quickly Testing Legacy Code
11
@ClareMacraeUK CPPP Paris June 2019
12
@ClareMacraeUK CPPP Paris June 2019
What does Legacy Code really mean?
• Michael Feathers
–“code without unit tests”
• J.B. Rainsberger
–“profitable code that we feel afraid to change.”
• Kate Gregory
–“any code that you want to change, but are afraid to”
13
@ClareMacraeUK CPPP Paris June 2019
Typical Scenario
• I've inherited some
legacy code
• It's valuable
• I need to add feature
• Or fix bug
• How can I ever break
out of this loop?
Need to
change
the code
No tests
Not
designed
for testing
Needs
refactoring
to add
tests
Can’t
refactor
without
tests
14
@ClareMacraeUK CPPP Paris June 2019
Typical Scenario
•
•
•
•
•
Need to
change
the code
No tests
Not
designed
for testing
Needs
refactoring
to add
tests
Can’t
refactor
without
tests
Topics of
this talk
15
@ClareMacraeUK CPPP Paris June 2019
Assumptions
• Value of automated testing
• No worries about types of tests
– (unit, integration, regression)
16
@ClareMacraeUK CPPP Paris June 2019
Any existing tests?
17
@ClareMacraeUK CPPP Paris June 2019
What, no tests?
• If absolutely no tests…
• Stop now!
• Set one up!
• Existing framework
18
@ClareMacraeUK CPPP Paris June 2019
Popular Test Frameworks
Google Test
• Google's C++ test framework
• https://github.com/google/googletest
Catch
• Phil Nash’s test framework
• https://github.com/catchorg/Catch2
19
@ClareMacraeUK CPPP Paris June 2019
20
@ClareMacraeUK CPPP Paris June 2019
How good are your existing tests?
21
@ClareMacraeUK CPPP Paris June 2019
First evaluate your tests
• If you do have tests….
• Test the tests!
• In area you are changing
• Reliable?
22
@ClareMacraeUK CPPP Paris June 2019
Code Coverage
• Caution!
• Unexecuted code
• Techniques
• Debugger
• Code coverage tool
– What to measure?
23
@ClareMacraeUK CPPP Paris June 2019
100% Test Coverage
Or is it?
OpenCppCoverage does not show
branch/condition coverage.
24
@ClareMacraeUK CPPP Paris June 2019
BullseyeCoverage:
Unrolls If conditions
(line 10)
73% of conditions
covered
25
@ClareMacraeUK CPPP Paris June 2019
Mutation testing: Sabotage the code!
• Test the tests
• Small changes
• Re-run tests
• Fail: 
• Pass: 
26
@ClareMacraeUK CPPP Paris June 2019
Mutation testing approaches
• By hand,
– e.g. + to -
• By tool
– e.g. Mutate++
• https://github.com/nlohmann/mutate_cpp
– e.g. Mull – see CppCast episode 198, Alex Denisov
• https://cppcast.com/2019/05/alex-denisov/
• https://github.com/mull-project/mull
– Awesome Mutation Testing:
• https://github.com/theofidry/awesome-mutation-testing
27
@ClareMacraeUK CPPP Paris June 2019
If tests need improving…
And unit tests not viable…
28
@ClareMacraeUK CPPP Paris June 2019
Contents
• Introduction
• Legacy Code
• Golden Master
• Approval Tests
• Example
• Resources
• Summary
29
@ClareMacraeUK CPPP Paris June 2019
Quickly Testing Legacy Code
30
@ClareMacraeUK CPPP Paris June 2019
Key Phrase :
“Locking Down Current Behaviour”
31
@ClareMacraeUK CPPP Paris June 2019
Writing Unit Tests for Legacy Code
• Time-consuming
• What’s intended behaviour?
• Is there another way?
32
@ClareMacraeUK CPPP Paris June 2019
Alternative: Golden Master Testing
33
@ClareMacraeUK CPPP Paris June 2019
Golden Master Test Setup
Input
Data
Existing
Code
Save
“Golden
Master”
34
@ClareMacraeUK CPPP Paris June 2019
Golden Master Tests In Use
Input
Data
Updated
Code
Pass
Fail
Output
same?
Yes
No
35
@ClareMacraeUK CPPP Paris June 2019
Thoughts on Golden Master Tests
• Good to start testing legacy systems
• Poor Person’s Integration Tests
• Depends on ease of
– Capturing output
– Getting stable output
– Reviewing any differences
– Avoiding overwriting Golden Master by mistake!
• Doesn’t matter that it’s not a Unit Test
36
@ClareMacraeUK CPPP Paris June 2019
Contents
• Introduction
• Legacy Code
• Golden Master
• Approval Tests
• Example
• Resources
• Summary
37
@ClareMacraeUK CPPP Paris June 2019
Quickly Testing Legacy Code
38
@ClareMacraeUK CPPP Paris June 2019
One approach: “ApprovalTests”
• Llewellyn Falco’s convenient, powerful, flexible Golden Master implementation
• Supports many language
And now C++!
GO
Java
Lua
.NET
.Net.ASP
NodeJS
Objective-C
PHP
Perl
Python
Swift
39
@ClareMacraeUK CPPP Paris June 2019
ApprovalTests.cpp
• New C++ library for applying Llewellyn Falco’s “Approval Tests” approach
• For testing cross-platform C++ code (Windows, Linux, Mac)
• For legacy and green-field systems
• It’s on github
40
@ClareMacraeUK CPPP Paris June 2019
ApprovalTests.cpp
• Header-only
• Open source - Apache 2.0 licence
41
@ClareMacraeUK CPPP Paris June 2019
ApprovalTests.cpp
• Works with a range of testing frameworks
• Currently supports Catch1, Catch2, Google Test and Okra
42
@ClareMacraeUK CPPP Paris June 2019
Getting Started with Approvals in C++
43
@ClareMacraeUK CPPP Paris June 2019
StarterProject with Catch2
• https://github.com/approvals/ApprovalTests.cpp.StarterProject
• Download ZIP
44
@ClareMacraeUK CPPP Paris June 2019
Download it Yourself…
45
@ClareMacraeUK CPPP Paris June 2019
46
@ClareMacraeUK CPPP Paris June 2019
47
@ClareMacraeUK CPPP Paris June 2019
48
@ClareMacraeUK CPPP Paris June 2019
Naming Options
• About that version number in the download…
• Could just call it by your preferred convention:
ApprovalTests.h
ApprovalTests.hpp
• Or use a wrapper and keep the version number, e.g.:
// In ApprovalTests.hpp
#include "ApprovalTests.v.3.4.0.hpp"
49
@ClareMacraeUK CPPP Paris June 2019
Getting Started with Approvals in C++
50
@ClareMacraeUK CPPP Paris June 2019
How to use it: Catch2 Boilerplate
• Your main.cpp
// main.cpp:
#define APPROVALS_CATCH
#include "ApprovalTests.hpp"
51
@ClareMacraeUK CPPP Paris June 2019
How to use it: Catch2 Boilerplate
• Your main.cpp
// main.cpp:
#define APPROVALS_CATCH
#include "ApprovalTests.hpp"
52
@ClareMacraeUK CPPP Paris June 2019
How to use it: Catch2 Boilerplate
• Your main.cpp
// main.cpp:
#define APPROVALS_CATCH
#include "ApprovalTests.hpp"
53
@ClareMacraeUK CPPP Paris June 2019
Pure Catch2 Test
• A test file
#include "Catch.hpp"
// Catch-only test
TEST_CASE( "Sums are calculated" )
{
REQUIRE( 1 + 1 == 2 );
REQUIRE( 1 + 2 == 3 );
}
54
@ClareMacraeUK CPPP Paris June 2019
Pure Catch2 Test
• A test file
#include "Catch.hpp"
// Catch-only test
TEST_CASE( "Sums are calculated" )
{
REQUIRE( 1 + 1 == 2 );
REQUIRE( 1 + 2 == 3 );
}
55
@ClareMacraeUK CPPP Paris June 2019
Pure Catch2 Test
• A test file
#include "Catch.hpp"
// Catch-only test
TEST_CASE( "Sums are calculated" )
{
REQUIRE( 1 + 1 == 2 );
REQUIRE( 1 + 2 == 3 );
}
56
@ClareMacraeUK CPPP Paris June 2019
Approvals Catch2 Test
• A test file (Test02.cpp)
#include "ApprovalTests.hpp"
#include "Catch.hpp"
// Approvals test - test static value, for demo purposes
TEST_CASE( "TestFixedInput" )
{
Approvals::verify("SomenMulti-linenoutput");
}
57
@ClareMacraeUK CPPP Paris June 2019
Approvals Catch2 Test
• A test file (Test02.cpp)
#include "ApprovalTests.hpp"
#include "Catch.hpp"
// Approvals test - test static value, for demo purposes
TEST_CASE( "TestFixedInput" )
{
Approvals::verify("SomenMulti-linenoutput");
}
58
@ClareMacraeUK CPPP Paris June 2019
Approvals Catch2 Test
• A test file (Test02.cpp)
#include "ApprovalTests.hpp"
#include "Catch.hpp"
// Approvals test - test static value, for demo purposes
TEST_CASE( "TestFixedInput" )
{
Approvals::verify("SomenMulti-linenoutput");
}
59
@ClareMacraeUK CPPP Paris June 2019
Approvals Catch2 Test
• A test file (Test02.cpp)
#include "ApprovalTests.hpp"
#include "Catch.hpp"
// Approvals test - test static value, for demo purposes
TEST_CASE( "TestFixedInput" )
{
Approvals::verify("SomenMulti-linenoutput");
}
60
@ClareMacraeUK CPPP Paris June 2019
First run
• 1.
• 2. Differencing tool pops up (Araxis Merge, in this case)
61
@ClareMacraeUK CPPP Paris June 2019
Actual/Received Expected/Approved
62
@ClareMacraeUK CPPP Paris June 2019
Actual/Received Expected/Approved
63
@ClareMacraeUK CPPP Paris June 2019
Actual/Received Expected/Approved
64
@ClareMacraeUK CPPP Paris June 2019
Second run
• I approved the output
• Then we commit the test, and the approved file(s) to version control
• The diffing tool only shows up if:
– there is not (yet) an Approved file or
– the Received differs from the Approved
65
@ClareMacraeUK CPPP Paris June 2019
What’s going on here?
• It’s a very convenient form of Golden Master testing
• Objects being tested are stringified – that’s a requirement
• Captures snapshot of current behaviour
• Useful for locking down behaviour of existing code
– Not intended to replace Unit Tests
66
@ClareMacraeUK CPPP Paris June 2019
Example test directory
Test02.cpp
Test02.TestFixedInput.approved.txt
Test03CustomReporters.cpp
Test03CustomReporters.UseCustomReporter.approved.txt
Test03CustomReporters.UseQuietReporter.approved.txt
Test03CustomReporters.UseSpecificReporter.approved.txt
Test04ConsoleReporter.cpp
Test04ConsoleReporter.UseConsoleReporter.approved.txt
Test04ConsoleReporter.UseConsoleReporter.received.txt
67
@ClareMacraeUK CPPP Paris June 2019
How to use it: Catch2 Boilerplate
• Your main.cpp
#define APPROVALS_CATCH
#include "ApprovalTests.hpp“
// Put all approved and received files in "approval_tests/"
auto dir =
Approvals::useApprovalsSubdirectory("approval_tests");
68
@ClareMacraeUK CPPP Paris June 2019
Example test directory
Test02.cpp
Test03CustomReporters.cpp
Test04ConsoleReporter.cpp
approval_tests/
Test02.TestFixedInput.approved.txt
Test03CustomReporters.UseCustomReporter.approved.txt
Test03CustomReporters.UseQuietReporter.approved.txt
Test03CustomReporters.UseSpecificReporter.approved.txt
Test04ConsoleReporter.UseConsoleReporter.approved.txt
Test04ConsoleReporter.UseConsoleReporter.received.txt
74
@ClareMacraeUK CPPP Paris June 2019
Delving Deeper
75
@ClareMacraeUK CPPP Paris June 2019
Reference: Evolving User Guide
• https://github.com/approvals/ApprovalTests.cpp/tree/master/doc#top
76
@ClareMacraeUK CPPP Paris June 2019
Reference: Evolving User Guide
77
@ClareMacraeUK CPPP Paris June 2019
Reference: Evolving User Guide
78
@ClareMacraeUK CPPP Paris June 2019
Reference: Evolving User Guide
79
@ClareMacraeUK CPPP Paris June 2019
A note on Tools
• I’ll be using a variety of tools in the talk
• I’ll mention them as I go
• Slides of references at the end
80
@ClareMacraeUK CPPP Paris June 2019
How does this help with legacy code?
81
@ClareMacraeUK CPPP Paris June 2019
Applying this to legacy code
TEST_CASE("New test of legacy feature")
{
// Standard pattern:
// Wrap your legacy feature to test in a function call
// that returns some state that can be written to a text file
// for verification:
const LegacyThing result = doLegacyOperation();
Approvals::verify(result);
}
82
@ClareMacraeUK CPPP Paris June 2019
Implementation
class LegacyThing;
std::ostream &operator<<(std::ostream &os, const LegacyThing &result) {
// write interesting info from result here:
os << result…;
return os;
}
LegacyThing doLegacyOperation() {
// your implementation here..
return LegacyThing();
}
83
@ClareMacraeUK CPPP Paris June 2019
Feature: Consistency over machines
• Naming of output files
• Approved files version controlled
84
@ClareMacraeUK CPPP Paris June 2019
Feature: Consistency over Operating Systems
• Line-endings
85
@ClareMacraeUK CPPP Paris June 2019
Feature: Consistency over Languages
• Consistent concepts and nomenclature in all the implementations
86
@ClareMacraeUK CPPP Paris June 2019
Feature: Quick to write tests
TEST_CASE("verifyAllWithHeaderBeginEndAndLambda")
{
std::list<int> numbers{ 0, 1, 2, 3};
// Multiple convenience overloads of Approvals::verifyAll()
Approvals::verifyAll(
"Test Squares", numbers.begin(), numbers.end(),
[](int v, std::ostream& s) { s << v << " => " << v*v << 'n' ; });
}
87
@ClareMacraeUK CPPP Paris June 2019
Feature: Quick to get good coverage
TEST_CASE("verifyAllCombinationsWithLambda")
{
std::vector<std::string> strings{"hello", "world"};
std::vector<int> numbers{1, 2, 3};
CombinationApprovals::verifyAllCombinations<
std::vector<std::string>, // The type of element in our first input container
std::vector<int>, // The type of element in our second input container
std::string>( // The return type from testing one combination of inputs
// Lambda that acts on one combination of inputs, and returns the result to be approved:
[](std::string s, int i) { return s + " " + std::to_string(i); },
strings, // The first input container
numbers); // The second input container
}
88
@ClareMacraeUK CPPP Paris June 2019
All values in single output file:
(hello, 1) => hello 1
(hello, 2) => hello 2
(hello, 3) => hello 3
(world, 1) => world 1
(world, 2) => world 2
(world, 3) => world 3
89
@ClareMacraeUK CPPP Paris June 2019
Customisability: Reporters
• Reporters act on test failure
• Very simple but powerful abstraction
• Gives complete user control over how to inspect and act on a failure
• If you adopt Approvals, do review the supplied reporters for ideas
90
@ClareMacraeUK CPPP Paris June 2019
Feature: Change the Reporter in one test
TEST_CASE("Demo custom reporter")
{
std::vector<std::string> v{"hello", "world"};
Approvals::verifyAll(v, MyCustomReporter());
}
91
@ClareMacraeUK CPPP Paris June 2019
Feature: Change the default Reporter
// main.cpp - or in individual tests:
#include <memory>
auto disposer = Approvals::useAsDefaultReporter(
std::make_shared<Windows::AraxisMergeReporter>() );
auto disposer = Approvals::useAsDefaultReporter(
std::make_shared<GenericDiffReporter>(
"E:/Program Files/Araxis/Araxis Merge/Compare.exe") );
92
@ClareMacraeUK CPPP Paris June 2019
Feature: Change the default Reporter
// main.cpp - or in individual tests:
#include <memory>
auto disposer = Approvals::useAsDefaultReporter(
std::make_shared<Windows::AraxisMergeReporter>() );
auto disposer = Approvals::useAsDefaultReporter(
std::make_shared<GenericDiffReporter>(
"E:/Program Files/Araxis/Araxis Merge/Compare.exe") );
93
@ClareMacraeUK CPPP Paris June 2019
Feature: Change the default Reporter
// main.cpp - or in individual tests:
#include <memory>
auto disposer = Approvals::useAsDefaultReporter(
std::make_shared<Windows::AraxisMergeReporter>() );
auto disposer = Approvals::useAsDefaultReporter(
std::make_shared<GenericDiffReporter>(
"E:/Program Files/Araxis/Araxis Merge/Compare.exe") );
94
@ClareMacraeUK CPPP Paris June 2019
Feature: Don’t run GUIs on build servers
// main.cpp
auto disposer = Approvals::useAsFrontLoadedReporter(
BlockingReporter::onMachineNamed("MyCIMachineName") );
95
@ClareMacraeUK CPPP Paris June 2019
Feature: Convention over Configuration
• Fewer decisions for developers
• Users only specify unusual behaviours
96
@ClareMacraeUK CPPP Paris June 2019
Challenge: Golden Master is a log file
• Dates and times?
• Object addresses?
2019-01-29 15:27
97
@ClareMacraeUK CPPP Paris June 2019
Options for unstable output
• Introduce date-time abstraction?
• Customised comparison function?
• Or: strip dates from the log file
98
@ClareMacraeUK CPPP Paris June 2019
Tip: Rewrite output file
2019-01-29 15:27 [date-time-stamp]
99
@ClareMacraeUK CPPP Paris June 2019
Customisability: ApprovalWriter interface
class ApprovalWriter
{
public:
virtual std::string getFileExtensionWithDot() = 0;
virtual void write(std::string path) = 0;
virtual void cleanUpReceived(std::string receivedPath) = 0;
};
100
@ClareMacraeUK CPPP Paris June 2019
Flexibility gives non-obvious power
• Approval Tests approach is deceptively simple
• Is a lot more than Golden Master
• Reporter could:
– Convert numbers to picture for comparison
– Or Excel file
• ApprovalWriter could:
– Write out a hash value of contents of very large file
101
@ClareMacraeUK CPPP Paris June 2019
Contents
• Introduction
• Legacy Code
• Golden Master
• Approval Tests
• Example
• Resources
• Summary
102
@ClareMacraeUK CPPP Paris June 2019
Requirement
103
@ClareMacraeUK CPPP Paris June 2019
What I could do:
104
@ClareMacraeUK CPPP Paris June 2019
What I needed to do:
105
@ClareMacraeUK CPPP Paris June 2019
Sugar - sucrose
108
@ClareMacraeUK CPPP Paris June 2019
Sugar - sucrose
109
@ClareMacraeUK CPPP Paris June 2019
Sugar - sucrose
111
@ClareMacraeUK CPPP Paris June 2019
Approving Images
112
@ClareMacraeUK CPPP Paris June 2019
What I’m aiming for
TEST(PolyhedralGraphicsStyleApprovals, CUVXAT)
{
// CUVXAT identifies a crystal structure in the database
// For code, please download the slides
const QImage crystal_picture = loadEntry("CUVXAT");
verifyQImage(crystal_picture, *currentReporter());
}
113
@ClareMacraeUK CPPP Paris June 2019
Foundation of Approval tests
void FileApprover::verify(
ApprovalNamer& namer,
ApprovalWriter& writer,
const Reporter& reporter);
118
@ClareMacraeUK CPPP Paris June 2019
Useful feedback BeyondCompare 4
120
@ClareMacraeUK CPPP Paris June 2019
What? Re-running now gives random failures
Araxis Merge
121
@ClareMacraeUK CPPP Paris June 2019
BeyondCompare 4
122
@ClareMacraeUK CPPP Paris June 2019
123
@ClareMacraeUK CPPP Paris June 2019
124
@ClareMacraeUK CPPP Paris June 2019
125
@ClareMacraeUK CPPP Paris June 2019
126
@ClareMacraeUK CPPP Paris June 2019
127
@ClareMacraeUK CPPP Paris June 2019
Customisability: ApprovalComparator
class ApprovalComparator
{
public:
virtual ~ApprovalComparator() = default;
virtual bool contentsAreEquivalent(std::string receivedPath,
std::string approvedPath) const = 0;
};
128
@ClareMacraeUK CPPP Paris June 2019
Create custom QImage comparison class
// Allow differences in up to 1/255 of RGB values at each pixel, as saved in 32-bit images
// sometimes have a few slightly different pixels, which are not visible to the human eye.
class QImageApprovalComparator : public ApprovalComparator
{
public:
bool contentsAreEquivalent(std::string receivedPath, std::string approvedPath) const override
{
const QImage receivedImage(QString::fromStdString(receivedPath));
const QImage approvedImage(QString::fromStdString(approvedPath));
return compareQImageIgnoringTinyDiffs(receivedImage, approvedImage);
}
};
129
@ClareMacraeUK CPPP Paris June 2019
Register the custom comparison class
// Somewhere in main…
FileApprover::registerComparator(
".png",
std::make_shared<QImageApprovalComparator>());
130
@ClareMacraeUK CPPP Paris June 2019
Does the difference matter?
• Legacy code is often brittle
• Testing makes changes visible
• Then decide if change matters
• Fast feedback cycle for efficient development
131
@ClareMacraeUK CPPP Paris June 2019
Looking back
• User perspective
• Learned about own code
• Enabled unit tests for graphics problems
• Approvals useful even for temporary tests
132
@ClareMacraeUK CPPP Paris June 2019
ApprovalTests Customisation Points
• Reporter
• ApprovalWriter
• ApprovalComparator
• ApprovalNamer
• More documentation of these coming soon
133
@ClareMacraeUK CPPP Paris June 2019
Contents
• Introduction
• Legacy Code
• Golden Master
• Approval Tests
• Example
• Resources
• Summary
134
@ClareMacraeUK CPPP Paris June 2019
References: Tools Used
• Diffing
– Araxis Merge: https://www.araxis.com/merge/
– Beyond Compare: https://www.scootersoftware.com/
• Code Coverage
– OpenCppCoverage and Visual Studio Plugin: https://github.com/OpenCppCoverage
– BullseyeCoverage: https://www.bullseye.com/
135
@ClareMacraeUK CPPP Paris June 2019
Beautiful C++: Updating Legacy Code
• https://app.pluralsight.com/library/courses/cpp-updating-legacy-code/table-of-contents
136
@ClareMacraeUK CPPP Paris June 2019
The Legacy Code Programmer’s Toolbox
• https://leanpub.com/legacycode
• The Legacy Code Programmer's Toolbox: Practical skills for software professionals working
with legacy code, by Jonathan Boccara
137
@ClareMacraeUK CPPP Paris June 2019
Videos
https://youtu.be/aWiwDdx_rdo
138
@ClareMacraeUK CPPP Paris June 2019
Adam Tornhill’s Books
• Mining actionable information from historical code bases (by Adam Tornhill)
– Your Code as a Crime Scene
– Software Design X-Rays: Fix Technical Debt with Behavioural Code Analysis
139
@ClareMacraeUK CPPP Paris June 2019
Contents
• Introduction
• Legacy Code
• Golden Master
• Approval Tests
• Example
• Resources
• Summary
140
@ClareMacraeUK CPPP Paris June 2019
Adopting legacy code
• You can do it!
• Evaluate current tests
• Quickly improve coverage with Golden Master
• ApprovalTests.cpp makes that really easy
• Even for non-text types
141
@ClareMacraeUK CPPP Paris June 2019
ApprovalTests
• Powerful Golden Master tool
• verify(), verifyAll(), verifyAllCombinations()
• Adjust output files, after writing, to simplify comparison
142
@ClareMacraeUK CPPP Paris June 2019
ApprovalTests.cpp
• Not (always) a replacement for Unit Tests!
Golden
Master
Refactor
code
Add unit
tests
Archive
Approval
Tests?
143
@ClareMacraeUK CPPP Paris June 2019
Thank You: Any Questions?
• Example Code: https://github.com/claremacrae/cppp2019/
• Slides: https://www.slideshare.net/ClareMacrae
– (early next week)
• ApprovalTests.cpp
– https://github.com/approvals/ApprovalTests.cpp
– https://github.com/approvals/ApprovalTests.cpp.StarterProject

More Related Content

Similar to Quickly testing legacy code cppp.fr 2019 - clare macrae

Quickly Testing Legacy Cpp Code - ACCU Cambridge 2019
Quickly Testing Legacy Cpp Code - ACCU Cambridge 2019Quickly Testing Legacy Cpp Code - ACCU Cambridge 2019
Quickly Testing Legacy Cpp Code - ACCU Cambridge 2019Clare Macrae
 
QA Fest 2019. Михаил Чуб. Test Automation Сonsultancy
QA Fest 2019. Михаил Чуб. Test Automation СonsultancyQA Fest 2019. Михаил Чуб. Test Automation Сonsultancy
QA Fest 2019. Михаил Чуб. Test Automation СonsultancyQAFest
 
Beacon Development
Beacon DevelopmentBeacon Development
Beacon DevelopmentMiro Cupak
 
Python testing like a pro by Keith Yang
Python testing like a pro by Keith YangPython testing like a pro by Keith Yang
Python testing like a pro by Keith YangPYCON MY PLT
 
Integrating Existing C++ Libraries into PySpark with Esther Kundin
Integrating Existing C++ Libraries into PySpark with Esther KundinIntegrating Existing C++ Libraries into PySpark with Esther Kundin
Integrating Existing C++ Libraries into PySpark with Esther KundinDatabricks
 
Parser Breakout Session
Parser Breakout SessionParser Breakout Session
Parser Breakout SessionZhipeng Huang
 
JUnit 5 - from Lambda to Alpha and beyond
JUnit 5 - from Lambda to Alpha and beyondJUnit 5 - from Lambda to Alpha and beyond
JUnit 5 - from Lambda to Alpha and beyondSam Brannen
 
OpenChain Agenda 09-09-2019
OpenChain Agenda 09-09-2019OpenChain Agenda 09-09-2019
OpenChain Agenda 09-09-2019Shane Coughlan
 
ELUNA2014: Developing and Testing an open source web application
ELUNA2014: Developing and Testing an open source web applicationELUNA2014: Developing and Testing an open source web application
ELUNA2014: Developing and Testing an open source web applicationMichael Cummings
 
Write microservice in golang
Write microservice in golangWrite microservice in golang
Write microservice in golangBo-Yi Wu
 
Building the Pipeline of My Dreams
Building the Pipeline of My DreamsBuilding the Pipeline of My Dreams
Building the Pipeline of My DreamsGene Gotimer
 
Cpp Testing Techniques Tips and Tricks - Cpp Europe
Cpp Testing Techniques Tips and Tricks - Cpp EuropeCpp Testing Techniques Tips and Tricks - Cpp Europe
Cpp Testing Techniques Tips and Tricks - Cpp EuropeClare Macrae
 
AI assisted testing using postman and openAI.pdf
AI assisted testing using postman and openAI.pdfAI assisted testing using postman and openAI.pdf
AI assisted testing using postman and openAI.pdfsivaganeshsivakumar1
 
Spring Framework 3.2 - What's New
Spring Framework 3.2 - What's NewSpring Framework 3.2 - What's New
Spring Framework 3.2 - What's NewSam Brannen
 
Porting an MPI application to hybrid MPI+OpenMP with Reveal tool on Shaheen II
Porting an MPI application to hybrid MPI+OpenMP with Reveal tool on Shaheen IIPorting an MPI application to hybrid MPI+OpenMP with Reveal tool on Shaheen II
Porting an MPI application to hybrid MPI+OpenMP with Reveal tool on Shaheen IIGeorge Markomanolis
 
Github Copilot vs Amazon CodeWhisperer for Java developers at JCON 2023
Github Copilot vs Amazon CodeWhisperer for Java developers at JCON 2023Github Copilot vs Amazon CodeWhisperer for Java developers at JCON 2023
Github Copilot vs Amazon CodeWhisperer for Java developers at JCON 2023Vadym Kazulkin
 
"OpenCV: Current Status and Future Plans," a Presentation from OpenCV.org
"OpenCV: Current Status and Future Plans," a Presentation from OpenCV.org"OpenCV: Current Status and Future Plans," a Presentation from OpenCV.org
"OpenCV: Current Status and Future Plans," a Presentation from OpenCV.orgEdge AI and Vision Alliance
 

Similar to Quickly testing legacy code cppp.fr 2019 - clare macrae (20)

Quickly Testing Legacy Cpp Code - ACCU Cambridge 2019
Quickly Testing Legacy Cpp Code - ACCU Cambridge 2019Quickly Testing Legacy Cpp Code - ACCU Cambridge 2019
Quickly Testing Legacy Cpp Code - ACCU Cambridge 2019
 
QA Fest 2019. Михаил Чуб. Test Automation Сonsultancy
QA Fest 2019. Михаил Чуб. Test Automation СonsultancyQA Fest 2019. Михаил Чуб. Test Automation Сonsultancy
QA Fest 2019. Михаил Чуб. Test Automation Сonsultancy
 
Beacon Development
Beacon DevelopmentBeacon Development
Beacon Development
 
Python testing like a pro by Keith Yang
Python testing like a pro by Keith YangPython testing like a pro by Keith Yang
Python testing like a pro by Keith Yang
 
Integrating Existing C++ Libraries into PySpark with Esther Kundin
Integrating Existing C++ Libraries into PySpark with Esther KundinIntegrating Existing C++ Libraries into PySpark with Esther Kundin
Integrating Existing C++ Libraries into PySpark with Esther Kundin
 
Parser Breakout Session
Parser Breakout SessionParser Breakout Session
Parser Breakout Session
 
JUnit 5 - from Lambda to Alpha and beyond
JUnit 5 - from Lambda to Alpha and beyondJUnit 5 - from Lambda to Alpha and beyond
JUnit 5 - from Lambda to Alpha and beyond
 
OpenChain Agenda 09-09-2019
OpenChain Agenda 09-09-2019OpenChain Agenda 09-09-2019
OpenChain Agenda 09-09-2019
 
ELUNA2014: Developing and Testing an open source web application
ELUNA2014: Developing and Testing an open source web applicationELUNA2014: Developing and Testing an open source web application
ELUNA2014: Developing and Testing an open source web application
 
Write microservice in golang
Write microservice in golangWrite microservice in golang
Write microservice in golang
 
Building the Pipeline of My Dreams
Building the Pipeline of My DreamsBuilding the Pipeline of My Dreams
Building the Pipeline of My Dreams
 
Cpp Testing Techniques Tips and Tricks - Cpp Europe
Cpp Testing Techniques Tips and Tricks - Cpp EuropeCpp Testing Techniques Tips and Tricks - Cpp Europe
Cpp Testing Techniques Tips and Tricks - Cpp Europe
 
AI assisted testing using postman and openAI.pdf
AI assisted testing using postman and openAI.pdfAI assisted testing using postman and openAI.pdf
AI assisted testing using postman and openAI.pdf
 
Spring Framework 3.2 - What's New
Spring Framework 3.2 - What's NewSpring Framework 3.2 - What's New
Spring Framework 3.2 - What's New
 
Porting an MPI application to hybrid MPI+OpenMP with Reveal tool on Shaheen II
Porting an MPI application to hybrid MPI+OpenMP with Reveal tool on Shaheen IIPorting an MPI application to hybrid MPI+OpenMP with Reveal tool on Shaheen II
Porting an MPI application to hybrid MPI+OpenMP with Reveal tool on Shaheen II
 
Pywps
PywpsPywps
Pywps
 
PyWPS-4.0.0
PyWPS-4.0.0PyWPS-4.0.0
PyWPS-4.0.0
 
Github Copilot vs Amazon CodeWhisperer for Java developers at JCON 2023
Github Copilot vs Amazon CodeWhisperer for Java developers at JCON 2023Github Copilot vs Amazon CodeWhisperer for Java developers at JCON 2023
Github Copilot vs Amazon CodeWhisperer for Java developers at JCON 2023
 
"OpenCV: Current Status and Future Plans," a Presentation from OpenCV.org
"OpenCV: Current Status and Future Plans," a Presentation from OpenCV.org"OpenCV: Current Status and Future Plans," a Presentation from OpenCV.org
"OpenCV: Current Status and Future Plans," a Presentation from OpenCV.org
 
MLSEC 2020
MLSEC 2020MLSEC 2020
MLSEC 2020
 

More from Clare Macrae

Testing Superpowers: Using CLion to Add Tests Easily
Testing Superpowers: Using CLion to Add Tests EasilyTesting Superpowers: Using CLion to Add Tests Easily
Testing Superpowers: Using CLion to Add Tests EasilyClare Macrae
 
Quickly and Effectively Testing Legacy c++ Code with Approval Tests mu cpp
Quickly and Effectively Testing Legacy c++ Code with Approval Tests   mu cppQuickly and Effectively Testing Legacy c++ Code with Approval Tests   mu cpp
Quickly and Effectively Testing Legacy c++ Code with Approval Tests mu cppClare Macrae
 
Quickly and Effectively Testing Legacy C++ Code with Approval Tests
Quickly and Effectively Testing Legacy C++ Code with Approval TestsQuickly and Effectively Testing Legacy C++ Code with Approval Tests
Quickly and Effectively Testing Legacy C++ Code with Approval TestsClare Macrae
 
How to use Approval Tests for C++ Effectively
How to use Approval Tests for C++ EffectivelyHow to use Approval Tests for C++ Effectively
How to use Approval Tests for C++ EffectivelyClare Macrae
 
C++ Testing Techniques Tips and Tricks - C++ London
C++ Testing Techniques Tips and Tricks - C++ LondonC++ Testing Techniques Tips and Tricks - C++ London
C++ Testing Techniques Tips and Tricks - C++ LondonClare Macrae
 
Quickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop ApplicationsQuickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop ApplicationsClare Macrae
 
Code samples that actually compile - Clare Macrae
Code samples that actually compile - Clare MacraeCode samples that actually compile - Clare Macrae
Code samples that actually compile - Clare MacraeClare Macrae
 
Quickly Testing Legacy C++ Code with Approval Tests
Quickly Testing Legacy C++ Code with Approval TestsQuickly Testing Legacy C++ Code with Approval Tests
Quickly Testing Legacy C++ Code with Approval TestsClare Macrae
 
Quickly Testing Legacy Code - ACCU York April 2019
Quickly Testing Legacy Code - ACCU York April 2019Quickly Testing Legacy Code - ACCU York April 2019
Quickly Testing Legacy Code - ACCU York April 2019Clare Macrae
 
Quickly testing legacy code
Quickly testing legacy codeQuickly testing legacy code
Quickly testing legacy codeClare Macrae
 
Escaping 5 decades of monolithic annual releases
Escaping 5 decades of monolithic annual releasesEscaping 5 decades of monolithic annual releases
Escaping 5 decades of monolithic annual releasesClare Macrae
 
CCDC’s (ongoing) Journey to Continuous Delivery - London Continuous Delivery ...
CCDC’s (ongoing) Journey to Continuous Delivery - London Continuous Delivery ...CCDC’s (ongoing) Journey to Continuous Delivery - London Continuous Delivery ...
CCDC’s (ongoing) Journey to Continuous Delivery - London Continuous Delivery ...Clare Macrae
 

More from Clare Macrae (12)

Testing Superpowers: Using CLion to Add Tests Easily
Testing Superpowers: Using CLion to Add Tests EasilyTesting Superpowers: Using CLion to Add Tests Easily
Testing Superpowers: Using CLion to Add Tests Easily
 
Quickly and Effectively Testing Legacy c++ Code with Approval Tests mu cpp
Quickly and Effectively Testing Legacy c++ Code with Approval Tests   mu cppQuickly and Effectively Testing Legacy c++ Code with Approval Tests   mu cpp
Quickly and Effectively Testing Legacy c++ Code with Approval Tests mu cpp
 
Quickly and Effectively Testing Legacy C++ Code with Approval Tests
Quickly and Effectively Testing Legacy C++ Code with Approval TestsQuickly and Effectively Testing Legacy C++ Code with Approval Tests
Quickly and Effectively Testing Legacy C++ Code with Approval Tests
 
How to use Approval Tests for C++ Effectively
How to use Approval Tests for C++ EffectivelyHow to use Approval Tests for C++ Effectively
How to use Approval Tests for C++ Effectively
 
C++ Testing Techniques Tips and Tricks - C++ London
C++ Testing Techniques Tips and Tricks - C++ LondonC++ Testing Techniques Tips and Tricks - C++ London
C++ Testing Techniques Tips and Tricks - C++ London
 
Quickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop ApplicationsQuickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop Applications
 
Code samples that actually compile - Clare Macrae
Code samples that actually compile - Clare MacraeCode samples that actually compile - Clare Macrae
Code samples that actually compile - Clare Macrae
 
Quickly Testing Legacy C++ Code with Approval Tests
Quickly Testing Legacy C++ Code with Approval TestsQuickly Testing Legacy C++ Code with Approval Tests
Quickly Testing Legacy C++ Code with Approval Tests
 
Quickly Testing Legacy Code - ACCU York April 2019
Quickly Testing Legacy Code - ACCU York April 2019Quickly Testing Legacy Code - ACCU York April 2019
Quickly Testing Legacy Code - ACCU York April 2019
 
Quickly testing legacy code
Quickly testing legacy codeQuickly testing legacy code
Quickly testing legacy code
 
Escaping 5 decades of monolithic annual releases
Escaping 5 decades of monolithic annual releasesEscaping 5 decades of monolithic annual releases
Escaping 5 decades of monolithic annual releases
 
CCDC’s (ongoing) Journey to Continuous Delivery - London Continuous Delivery ...
CCDC’s (ongoing) Journey to Continuous Delivery - London Continuous Delivery ...CCDC’s (ongoing) Journey to Continuous Delivery - London Continuous Delivery ...
CCDC’s (ongoing) Journey to Continuous Delivery - London Continuous Delivery ...
 

Recently uploaded

Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
cybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningcybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningVitsRangannavar
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number SystemsJheuzeDellosa
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfPower Karaoke
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 

Recently uploaded (20)

Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
cybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningcybersecurity notes for mca students for learning
cybersecurity notes for mca students for learning
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number Systems
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 

Quickly testing legacy code cppp.fr 2019 - clare macrae

  • 1. 1 @ClareMacraeUK CPPP Paris June 2019 Quickly Testing Legacy Code Clare Macrae (She/Her) CPPP Conference, Paris: 15 June 2019
  • 2. 2 @ClareMacraeUK CPPP Paris June 2019 @ClareMacraeUK
  • 3. 4 @ClareMacraeUK CPPP Paris June 2019 Contents • Introduction • Legacy Code • Golden Master • Approval Tests • Example • Resources • Summary
  • 6. 7 @ClareMacraeUK CPPP Paris June 2019 18 months of remote pairing later…
  • 7. 8 @ClareMacraeUK CPPP Paris June 2019 Goal: Share techniques for easier testing in challenging scenarios
  • 8. 9 @ClareMacraeUK CPPP Paris June 2019 Contents • Introduction • Legacy Code • Golden Master • Approval Tests • Example • Resources • Summary
  • 9. 10 @ClareMacraeUK CPPP Paris June 2019 Quickly Testing Legacy Code
  • 11. 12 @ClareMacraeUK CPPP Paris June 2019 What does Legacy Code really mean? • Michael Feathers –“code without unit tests” • J.B. Rainsberger –“profitable code that we feel afraid to change.” • Kate Gregory –“any code that you want to change, but are afraid to”
  • 12. 13 @ClareMacraeUK CPPP Paris June 2019 Typical Scenario • I've inherited some legacy code • It's valuable • I need to add feature • Or fix bug • How can I ever break out of this loop? Need to change the code No tests Not designed for testing Needs refactoring to add tests Can’t refactor without tests
  • 13. 14 @ClareMacraeUK CPPP Paris June 2019 Typical Scenario • • • • • Need to change the code No tests Not designed for testing Needs refactoring to add tests Can’t refactor without tests Topics of this talk
  • 14. 15 @ClareMacraeUK CPPP Paris June 2019 Assumptions • Value of automated testing • No worries about types of tests – (unit, integration, regression)
  • 15. 16 @ClareMacraeUK CPPP Paris June 2019 Any existing tests?
  • 16. 17 @ClareMacraeUK CPPP Paris June 2019 What, no tests? • If absolutely no tests… • Stop now! • Set one up! • Existing framework
  • 17. 18 @ClareMacraeUK CPPP Paris June 2019 Popular Test Frameworks Google Test • Google's C++ test framework • https://github.com/google/googletest Catch • Phil Nash’s test framework • https://github.com/catchorg/Catch2
  • 19. 20 @ClareMacraeUK CPPP Paris June 2019 How good are your existing tests?
  • 20. 21 @ClareMacraeUK CPPP Paris June 2019 First evaluate your tests • If you do have tests…. • Test the tests! • In area you are changing • Reliable?
  • 21. 22 @ClareMacraeUK CPPP Paris June 2019 Code Coverage • Caution! • Unexecuted code • Techniques • Debugger • Code coverage tool – What to measure?
  • 22. 23 @ClareMacraeUK CPPP Paris June 2019 100% Test Coverage Or is it? OpenCppCoverage does not show branch/condition coverage.
  • 23. 24 @ClareMacraeUK CPPP Paris June 2019 BullseyeCoverage: Unrolls If conditions (line 10) 73% of conditions covered
  • 24. 25 @ClareMacraeUK CPPP Paris June 2019 Mutation testing: Sabotage the code! • Test the tests • Small changes • Re-run tests • Fail:  • Pass: 
  • 25. 26 @ClareMacraeUK CPPP Paris June 2019 Mutation testing approaches • By hand, – e.g. + to - • By tool – e.g. Mutate++ • https://github.com/nlohmann/mutate_cpp – e.g. Mull – see CppCast episode 198, Alex Denisov • https://cppcast.com/2019/05/alex-denisov/ • https://github.com/mull-project/mull – Awesome Mutation Testing: • https://github.com/theofidry/awesome-mutation-testing
  • 26. 27 @ClareMacraeUK CPPP Paris June 2019 If tests need improving… And unit tests not viable…
  • 27. 28 @ClareMacraeUK CPPP Paris June 2019 Contents • Introduction • Legacy Code • Golden Master • Approval Tests • Example • Resources • Summary
  • 28. 29 @ClareMacraeUK CPPP Paris June 2019 Quickly Testing Legacy Code
  • 29. 30 @ClareMacraeUK CPPP Paris June 2019 Key Phrase : “Locking Down Current Behaviour”
  • 30. 31 @ClareMacraeUK CPPP Paris June 2019 Writing Unit Tests for Legacy Code • Time-consuming • What’s intended behaviour? • Is there another way?
  • 31. 32 @ClareMacraeUK CPPP Paris June 2019 Alternative: Golden Master Testing
  • 32. 33 @ClareMacraeUK CPPP Paris June 2019 Golden Master Test Setup Input Data Existing Code Save “Golden Master”
  • 33. 34 @ClareMacraeUK CPPP Paris June 2019 Golden Master Tests In Use Input Data Updated Code Pass Fail Output same? Yes No
  • 34. 35 @ClareMacraeUK CPPP Paris June 2019 Thoughts on Golden Master Tests • Good to start testing legacy systems • Poor Person’s Integration Tests • Depends on ease of – Capturing output – Getting stable output – Reviewing any differences – Avoiding overwriting Golden Master by mistake! • Doesn’t matter that it’s not a Unit Test
  • 35. 36 @ClareMacraeUK CPPP Paris June 2019 Contents • Introduction • Legacy Code • Golden Master • Approval Tests • Example • Resources • Summary
  • 36. 37 @ClareMacraeUK CPPP Paris June 2019 Quickly Testing Legacy Code
  • 37. 38 @ClareMacraeUK CPPP Paris June 2019 One approach: “ApprovalTests” • Llewellyn Falco’s convenient, powerful, flexible Golden Master implementation • Supports many language And now C++! GO Java Lua .NET .Net.ASP NodeJS Objective-C PHP Perl Python Swift
  • 38. 39 @ClareMacraeUK CPPP Paris June 2019 ApprovalTests.cpp • New C++ library for applying Llewellyn Falco’s “Approval Tests” approach • For testing cross-platform C++ code (Windows, Linux, Mac) • For legacy and green-field systems • It’s on github
  • 39. 40 @ClareMacraeUK CPPP Paris June 2019 ApprovalTests.cpp • Header-only • Open source - Apache 2.0 licence
  • 40. 41 @ClareMacraeUK CPPP Paris June 2019 ApprovalTests.cpp • Works with a range of testing frameworks • Currently supports Catch1, Catch2, Google Test and Okra
  • 41. 42 @ClareMacraeUK CPPP Paris June 2019 Getting Started with Approvals in C++
  • 42. 43 @ClareMacraeUK CPPP Paris June 2019 StarterProject with Catch2 • https://github.com/approvals/ApprovalTests.cpp.StarterProject • Download ZIP
  • 43. 44 @ClareMacraeUK CPPP Paris June 2019 Download it Yourself…
  • 47. 48 @ClareMacraeUK CPPP Paris June 2019 Naming Options • About that version number in the download… • Could just call it by your preferred convention: ApprovalTests.h ApprovalTests.hpp • Or use a wrapper and keep the version number, e.g.: // In ApprovalTests.hpp #include "ApprovalTests.v.3.4.0.hpp"
  • 48. 49 @ClareMacraeUK CPPP Paris June 2019 Getting Started with Approvals in C++
  • 49. 50 @ClareMacraeUK CPPP Paris June 2019 How to use it: Catch2 Boilerplate • Your main.cpp // main.cpp: #define APPROVALS_CATCH #include "ApprovalTests.hpp"
  • 50. 51 @ClareMacraeUK CPPP Paris June 2019 How to use it: Catch2 Boilerplate • Your main.cpp // main.cpp: #define APPROVALS_CATCH #include "ApprovalTests.hpp"
  • 51. 52 @ClareMacraeUK CPPP Paris June 2019 How to use it: Catch2 Boilerplate • Your main.cpp // main.cpp: #define APPROVALS_CATCH #include "ApprovalTests.hpp"
  • 52. 53 @ClareMacraeUK CPPP Paris June 2019 Pure Catch2 Test • A test file #include "Catch.hpp" // Catch-only test TEST_CASE( "Sums are calculated" ) { REQUIRE( 1 + 1 == 2 ); REQUIRE( 1 + 2 == 3 ); }
  • 53. 54 @ClareMacraeUK CPPP Paris June 2019 Pure Catch2 Test • A test file #include "Catch.hpp" // Catch-only test TEST_CASE( "Sums are calculated" ) { REQUIRE( 1 + 1 == 2 ); REQUIRE( 1 + 2 == 3 ); }
  • 54. 55 @ClareMacraeUK CPPP Paris June 2019 Pure Catch2 Test • A test file #include "Catch.hpp" // Catch-only test TEST_CASE( "Sums are calculated" ) { REQUIRE( 1 + 1 == 2 ); REQUIRE( 1 + 2 == 3 ); }
  • 55. 56 @ClareMacraeUK CPPP Paris June 2019 Approvals Catch2 Test • A test file (Test02.cpp) #include "ApprovalTests.hpp" #include "Catch.hpp" // Approvals test - test static value, for demo purposes TEST_CASE( "TestFixedInput" ) { Approvals::verify("SomenMulti-linenoutput"); }
  • 56. 57 @ClareMacraeUK CPPP Paris June 2019 Approvals Catch2 Test • A test file (Test02.cpp) #include "ApprovalTests.hpp" #include "Catch.hpp" // Approvals test - test static value, for demo purposes TEST_CASE( "TestFixedInput" ) { Approvals::verify("SomenMulti-linenoutput"); }
  • 57. 58 @ClareMacraeUK CPPP Paris June 2019 Approvals Catch2 Test • A test file (Test02.cpp) #include "ApprovalTests.hpp" #include "Catch.hpp" // Approvals test - test static value, for demo purposes TEST_CASE( "TestFixedInput" ) { Approvals::verify("SomenMulti-linenoutput"); }
  • 58. 59 @ClareMacraeUK CPPP Paris June 2019 Approvals Catch2 Test • A test file (Test02.cpp) #include "ApprovalTests.hpp" #include "Catch.hpp" // Approvals test - test static value, for demo purposes TEST_CASE( "TestFixedInput" ) { Approvals::verify("SomenMulti-linenoutput"); }
  • 59. 60 @ClareMacraeUK CPPP Paris June 2019 First run • 1. • 2. Differencing tool pops up (Araxis Merge, in this case)
  • 60. 61 @ClareMacraeUK CPPP Paris June 2019 Actual/Received Expected/Approved
  • 61. 62 @ClareMacraeUK CPPP Paris June 2019 Actual/Received Expected/Approved
  • 62. 63 @ClareMacraeUK CPPP Paris June 2019 Actual/Received Expected/Approved
  • 63. 64 @ClareMacraeUK CPPP Paris June 2019 Second run • I approved the output • Then we commit the test, and the approved file(s) to version control • The diffing tool only shows up if: – there is not (yet) an Approved file or – the Received differs from the Approved
  • 64. 65 @ClareMacraeUK CPPP Paris June 2019 What’s going on here? • It’s a very convenient form of Golden Master testing • Objects being tested are stringified – that’s a requirement • Captures snapshot of current behaviour • Useful for locking down behaviour of existing code – Not intended to replace Unit Tests
  • 65. 66 @ClareMacraeUK CPPP Paris June 2019 Example test directory Test02.cpp Test02.TestFixedInput.approved.txt Test03CustomReporters.cpp Test03CustomReporters.UseCustomReporter.approved.txt Test03CustomReporters.UseQuietReporter.approved.txt Test03CustomReporters.UseSpecificReporter.approved.txt Test04ConsoleReporter.cpp Test04ConsoleReporter.UseConsoleReporter.approved.txt Test04ConsoleReporter.UseConsoleReporter.received.txt
  • 66. 67 @ClareMacraeUK CPPP Paris June 2019 How to use it: Catch2 Boilerplate • Your main.cpp #define APPROVALS_CATCH #include "ApprovalTests.hpp“ // Put all approved and received files in "approval_tests/" auto dir = Approvals::useApprovalsSubdirectory("approval_tests");
  • 67. 68 @ClareMacraeUK CPPP Paris June 2019 Example test directory Test02.cpp Test03CustomReporters.cpp Test04ConsoleReporter.cpp approval_tests/ Test02.TestFixedInput.approved.txt Test03CustomReporters.UseCustomReporter.approved.txt Test03CustomReporters.UseQuietReporter.approved.txt Test03CustomReporters.UseSpecificReporter.approved.txt Test04ConsoleReporter.UseConsoleReporter.approved.txt Test04ConsoleReporter.UseConsoleReporter.received.txt
  • 68. 74 @ClareMacraeUK CPPP Paris June 2019 Delving Deeper
  • 69. 75 @ClareMacraeUK CPPP Paris June 2019 Reference: Evolving User Guide • https://github.com/approvals/ApprovalTests.cpp/tree/master/doc#top
  • 70. 76 @ClareMacraeUK CPPP Paris June 2019 Reference: Evolving User Guide
  • 71. 77 @ClareMacraeUK CPPP Paris June 2019 Reference: Evolving User Guide
  • 72. 78 @ClareMacraeUK CPPP Paris June 2019 Reference: Evolving User Guide
  • 73. 79 @ClareMacraeUK CPPP Paris June 2019 A note on Tools • I’ll be using a variety of tools in the talk • I’ll mention them as I go • Slides of references at the end
  • 74. 80 @ClareMacraeUK CPPP Paris June 2019 How does this help with legacy code?
  • 75. 81 @ClareMacraeUK CPPP Paris June 2019 Applying this to legacy code TEST_CASE("New test of legacy feature") { // Standard pattern: // Wrap your legacy feature to test in a function call // that returns some state that can be written to a text file // for verification: const LegacyThing result = doLegacyOperation(); Approvals::verify(result); }
  • 76. 82 @ClareMacraeUK CPPP Paris June 2019 Implementation class LegacyThing; std::ostream &operator<<(std::ostream &os, const LegacyThing &result) { // write interesting info from result here: os << result…; return os; } LegacyThing doLegacyOperation() { // your implementation here.. return LegacyThing(); }
  • 77. 83 @ClareMacraeUK CPPP Paris June 2019 Feature: Consistency over machines • Naming of output files • Approved files version controlled
  • 78. 84 @ClareMacraeUK CPPP Paris June 2019 Feature: Consistency over Operating Systems • Line-endings
  • 79. 85 @ClareMacraeUK CPPP Paris June 2019 Feature: Consistency over Languages • Consistent concepts and nomenclature in all the implementations
  • 80. 86 @ClareMacraeUK CPPP Paris June 2019 Feature: Quick to write tests TEST_CASE("verifyAllWithHeaderBeginEndAndLambda") { std::list<int> numbers{ 0, 1, 2, 3}; // Multiple convenience overloads of Approvals::verifyAll() Approvals::verifyAll( "Test Squares", numbers.begin(), numbers.end(), [](int v, std::ostream& s) { s << v << " => " << v*v << 'n' ; }); }
  • 81. 87 @ClareMacraeUK CPPP Paris June 2019 Feature: Quick to get good coverage TEST_CASE("verifyAllCombinationsWithLambda") { std::vector<std::string> strings{"hello", "world"}; std::vector<int> numbers{1, 2, 3}; CombinationApprovals::verifyAllCombinations< std::vector<std::string>, // The type of element in our first input container std::vector<int>, // The type of element in our second input container std::string>( // The return type from testing one combination of inputs // Lambda that acts on one combination of inputs, and returns the result to be approved: [](std::string s, int i) { return s + " " + std::to_string(i); }, strings, // The first input container numbers); // The second input container }
  • 82. 88 @ClareMacraeUK CPPP Paris June 2019 All values in single output file: (hello, 1) => hello 1 (hello, 2) => hello 2 (hello, 3) => hello 3 (world, 1) => world 1 (world, 2) => world 2 (world, 3) => world 3
  • 83. 89 @ClareMacraeUK CPPP Paris June 2019 Customisability: Reporters • Reporters act on test failure • Very simple but powerful abstraction • Gives complete user control over how to inspect and act on a failure • If you adopt Approvals, do review the supplied reporters for ideas
  • 84. 90 @ClareMacraeUK CPPP Paris June 2019 Feature: Change the Reporter in one test TEST_CASE("Demo custom reporter") { std::vector<std::string> v{"hello", "world"}; Approvals::verifyAll(v, MyCustomReporter()); }
  • 85. 91 @ClareMacraeUK CPPP Paris June 2019 Feature: Change the default Reporter // main.cpp - or in individual tests: #include <memory> auto disposer = Approvals::useAsDefaultReporter( std::make_shared<Windows::AraxisMergeReporter>() ); auto disposer = Approvals::useAsDefaultReporter( std::make_shared<GenericDiffReporter>( "E:/Program Files/Araxis/Araxis Merge/Compare.exe") );
  • 86. 92 @ClareMacraeUK CPPP Paris June 2019 Feature: Change the default Reporter // main.cpp - or in individual tests: #include <memory> auto disposer = Approvals::useAsDefaultReporter( std::make_shared<Windows::AraxisMergeReporter>() ); auto disposer = Approvals::useAsDefaultReporter( std::make_shared<GenericDiffReporter>( "E:/Program Files/Araxis/Araxis Merge/Compare.exe") );
  • 87. 93 @ClareMacraeUK CPPP Paris June 2019 Feature: Change the default Reporter // main.cpp - or in individual tests: #include <memory> auto disposer = Approvals::useAsDefaultReporter( std::make_shared<Windows::AraxisMergeReporter>() ); auto disposer = Approvals::useAsDefaultReporter( std::make_shared<GenericDiffReporter>( "E:/Program Files/Araxis/Araxis Merge/Compare.exe") );
  • 88. 94 @ClareMacraeUK CPPP Paris June 2019 Feature: Don’t run GUIs on build servers // main.cpp auto disposer = Approvals::useAsFrontLoadedReporter( BlockingReporter::onMachineNamed("MyCIMachineName") );
  • 89. 95 @ClareMacraeUK CPPP Paris June 2019 Feature: Convention over Configuration • Fewer decisions for developers • Users only specify unusual behaviours
  • 90. 96 @ClareMacraeUK CPPP Paris June 2019 Challenge: Golden Master is a log file • Dates and times? • Object addresses? 2019-01-29 15:27
  • 91. 97 @ClareMacraeUK CPPP Paris June 2019 Options for unstable output • Introduce date-time abstraction? • Customised comparison function? • Or: strip dates from the log file
  • 92. 98 @ClareMacraeUK CPPP Paris June 2019 Tip: Rewrite output file 2019-01-29 15:27 [date-time-stamp]
  • 93. 99 @ClareMacraeUK CPPP Paris June 2019 Customisability: ApprovalWriter interface class ApprovalWriter { public: virtual std::string getFileExtensionWithDot() = 0; virtual void write(std::string path) = 0; virtual void cleanUpReceived(std::string receivedPath) = 0; };
  • 94. 100 @ClareMacraeUK CPPP Paris June 2019 Flexibility gives non-obvious power • Approval Tests approach is deceptively simple • Is a lot more than Golden Master • Reporter could: – Convert numbers to picture for comparison – Or Excel file • ApprovalWriter could: – Write out a hash value of contents of very large file
  • 95. 101 @ClareMacraeUK CPPP Paris June 2019 Contents • Introduction • Legacy Code • Golden Master • Approval Tests • Example • Resources • Summary
  • 96. 102 @ClareMacraeUK CPPP Paris June 2019 Requirement
  • 97. 103 @ClareMacraeUK CPPP Paris June 2019 What I could do:
  • 98. 104 @ClareMacraeUK CPPP Paris June 2019 What I needed to do:
  • 99. 105 @ClareMacraeUK CPPP Paris June 2019 Sugar - sucrose
  • 100. 108 @ClareMacraeUK CPPP Paris June 2019 Sugar - sucrose
  • 101. 109 @ClareMacraeUK CPPP Paris June 2019 Sugar - sucrose
  • 102. 111 @ClareMacraeUK CPPP Paris June 2019 Approving Images
  • 103. 112 @ClareMacraeUK CPPP Paris June 2019 What I’m aiming for TEST(PolyhedralGraphicsStyleApprovals, CUVXAT) { // CUVXAT identifies a crystal structure in the database // For code, please download the slides const QImage crystal_picture = loadEntry("CUVXAT"); verifyQImage(crystal_picture, *currentReporter()); }
  • 104. 113 @ClareMacraeUK CPPP Paris June 2019 Foundation of Approval tests void FileApprover::verify( ApprovalNamer& namer, ApprovalWriter& writer, const Reporter& reporter);
  • 105. 118 @ClareMacraeUK CPPP Paris June 2019 Useful feedback BeyondCompare 4
  • 106. 120 @ClareMacraeUK CPPP Paris June 2019 What? Re-running now gives random failures Araxis Merge
  • 107. 121 @ClareMacraeUK CPPP Paris June 2019 BeyondCompare 4
  • 113. 127 @ClareMacraeUK CPPP Paris June 2019 Customisability: ApprovalComparator class ApprovalComparator { public: virtual ~ApprovalComparator() = default; virtual bool contentsAreEquivalent(std::string receivedPath, std::string approvedPath) const = 0; };
  • 114. 128 @ClareMacraeUK CPPP Paris June 2019 Create custom QImage comparison class // Allow differences in up to 1/255 of RGB values at each pixel, as saved in 32-bit images // sometimes have a few slightly different pixels, which are not visible to the human eye. class QImageApprovalComparator : public ApprovalComparator { public: bool contentsAreEquivalent(std::string receivedPath, std::string approvedPath) const override { const QImage receivedImage(QString::fromStdString(receivedPath)); const QImage approvedImage(QString::fromStdString(approvedPath)); return compareQImageIgnoringTinyDiffs(receivedImage, approvedImage); } };
  • 115. 129 @ClareMacraeUK CPPP Paris June 2019 Register the custom comparison class // Somewhere in main… FileApprover::registerComparator( ".png", std::make_shared<QImageApprovalComparator>());
  • 116. 130 @ClareMacraeUK CPPP Paris June 2019 Does the difference matter? • Legacy code is often brittle • Testing makes changes visible • Then decide if change matters • Fast feedback cycle for efficient development
  • 117. 131 @ClareMacraeUK CPPP Paris June 2019 Looking back • User perspective • Learned about own code • Enabled unit tests for graphics problems • Approvals useful even for temporary tests
  • 118. 132 @ClareMacraeUK CPPP Paris June 2019 ApprovalTests Customisation Points • Reporter • ApprovalWriter • ApprovalComparator • ApprovalNamer • More documentation of these coming soon
  • 119. 133 @ClareMacraeUK CPPP Paris June 2019 Contents • Introduction • Legacy Code • Golden Master • Approval Tests • Example • Resources • Summary
  • 120. 134 @ClareMacraeUK CPPP Paris June 2019 References: Tools Used • Diffing – Araxis Merge: https://www.araxis.com/merge/ – Beyond Compare: https://www.scootersoftware.com/ • Code Coverage – OpenCppCoverage and Visual Studio Plugin: https://github.com/OpenCppCoverage – BullseyeCoverage: https://www.bullseye.com/
  • 121. 135 @ClareMacraeUK CPPP Paris June 2019 Beautiful C++: Updating Legacy Code • https://app.pluralsight.com/library/courses/cpp-updating-legacy-code/table-of-contents
  • 122. 136 @ClareMacraeUK CPPP Paris June 2019 The Legacy Code Programmer’s Toolbox • https://leanpub.com/legacycode • The Legacy Code Programmer's Toolbox: Practical skills for software professionals working with legacy code, by Jonathan Boccara
  • 123. 137 @ClareMacraeUK CPPP Paris June 2019 Videos https://youtu.be/aWiwDdx_rdo
  • 124. 138 @ClareMacraeUK CPPP Paris June 2019 Adam Tornhill’s Books • Mining actionable information from historical code bases (by Adam Tornhill) – Your Code as a Crime Scene – Software Design X-Rays: Fix Technical Debt with Behavioural Code Analysis
  • 125. 139 @ClareMacraeUK CPPP Paris June 2019 Contents • Introduction • Legacy Code • Golden Master • Approval Tests • Example • Resources • Summary
  • 126. 140 @ClareMacraeUK CPPP Paris June 2019 Adopting legacy code • You can do it! • Evaluate current tests • Quickly improve coverage with Golden Master • ApprovalTests.cpp makes that really easy • Even for non-text types
  • 127. 141 @ClareMacraeUK CPPP Paris June 2019 ApprovalTests • Powerful Golden Master tool • verify(), verifyAll(), verifyAllCombinations() • Adjust output files, after writing, to simplify comparison
  • 128. 142 @ClareMacraeUK CPPP Paris June 2019 ApprovalTests.cpp • Not (always) a replacement for Unit Tests! Golden Master Refactor code Add unit tests Archive Approval Tests?
  • 129. 143 @ClareMacraeUK CPPP Paris June 2019 Thank You: Any Questions? • Example Code: https://github.com/claremacrae/cppp2019/ • Slides: https://www.slideshare.net/ClareMacrae – (early next week) • ApprovalTests.cpp – https://github.com/approvals/ApprovalTests.cpp – https://github.com/approvals/ApprovalTests.cpp.StarterProject

Editor's Notes

  1. I’ll tweet the location of slides (and perhaps sample code) later today
  2. Google test: Very powerful tool Can be a pain to add to your builds Catch: As powerful as Google Test Distributed as a Single Header Much easier to incorporate in to builds
  3. https://pragprog.com/book/lotdd/modern-c-programming-with-test-driven-development Uses Google Mock and Google Test Has a very useful chapter on dealing with Legacy Code, with worked examples.
  4. Note of caution: knowing that a line of code is executed tells nothing about if it was tested! Still useful to see totally un-tested code Techniques Run in debugger with breakpoints, to see what lines are reached Run through code coverage tool to at least see what lines are executed But what do you measure?
  5. Another phrase for the Golden Master output is “Known Good” output.
  6. https://commons.wikimedia.org/wiki/File:Sugar_2xmacro.jpg
  7. These kinds of diagrams will probably be familiar to many from school chemistry lessons They say there are Carbon, Oxygen and Hydrogen atoms in this “molecule”. The lines represent the bonds between the atoms. There are lots of conventions built in to this, such as the hydrogens here are collapsed down to the labels.
  8. Chemistry software uses standard conventions for to colour-code by element. So Oxygen is often drawn as red. We can see some kind of shape here, but what really is the shape of the sucrose molecule.
  9. Now by changing the display style, we start to see more of the shape.
  10. In fact, a crystal of sucrose is built from a potentially infinite set of repeating molecules.