In this session, we discussed approaches for working with legacy untested code in a safe way.
We saw how Approval Testing and Mutation Testing techniques can be combined to quickly build a robust suite of characterization tests that enables us to refactor with confidence.
https://www.meetup.com/Cork-Software-Craftsmanship-Meetup/events/262255659/
7. Refactoring
What? Restructuring code without changing its external behaviour.
Why? To make the code easier to change.
Paulo Clavijo @pclavijo
“Refactoring changes the programs in small steps. If you make a
mistake, it is easy to find the bug.” - Martin Fowler
“Refactoring is the choreography we use to move code from design
A to design B in a safe and efficient way” - Pedro Moreira Santos
Cork Software Crafters
9. “A characterization test (aka Golden Master Testing) is a means to describe the actual
behavior of an existing piece of software, and therefore protect existing behavior of
legacy code against unintended changes.” - Wikipedia
● Tests to enable refactoring.
● Protects existing behaviour.
● Often used with legacy untested code.
● Quickly results in high coverage.
Paulo Clavijo (@pclavijo)
Characterization Tests
Cork Software Crafters
10. Paulo Clavijo (@pclavijo)
Characterization Tests
Cork Software Crafters
Legacy code can be hard to test, we need to be creative writing our characterization tests
and make use of any output available. Think not just in responses from methods or APIs
also in other existing side-effects like logging statements, writes to databases, etc.
12. A test technique which compares the current output of your code with an "approved"
version. The approved version is created by initially examining the output of your code by
hand and approving the result. You can revisit the approved version and easily update it
when the requirements change.
Paulo Clavijo (@pclavijo)
Approval Tests
Cork Software Crafters
13. Don’t Tell Me ...
Show Me!
Paulo Clavijo (@pclavijo)Cork Software Crafters
14. Paulo Clavijo (@pclavijo)
Approval Tests
Cork Software Crafters
public class GreeterTest {
@Test
public void should_say_hello() {
// Arrange
Greeter greeter = new Greeter("John Doe");
// Act
String greeting = greeter.sayHello();
// Assert
assertThat(greeting).isEqualTo("Hello, John Doe!");
}
}
public class GreeterTest {
@Test
public void should_say_hello() {
// Arrange
Greeter greeter = new Greeter("John Doe");
// Act
String greeting = greeter.sayHello();
// Verify output against approved
Approvals.verify(greeting);
}
}
Assertion-based test Approval test
15. Tracing Coverage
Tracing mode enables accurate collection of the branch coverage, with the ability to track tests,
view coverage statistic, and get additional information on each covered line.
17. Coverage is a useful tool to find untested code.
Coverage is of little use as a numeric statement of how good your tests are.
The problem is that a high coverage can be easily achive with low quality tests.
● 100% coverage with a single test
● 100% coverage with tests without assertions
Paulo Clavijo @pclavijo
Tests focused on the implementation instead of
behaviours and business rules.
Cork Software Crafters
Coverage != Tests Quality
18. Mutation Testing can be a powerful technique to evaluate the quality of your unit tests.
Experiment with small manual mutations in the production code and verify if the tests
fail.
if (a && b ) {
…
}
if (a || b ) {
…
}
Paulo Clavijo @pclavijo
Cork Software Crafters
Mutation Testing
19. Automated Mutation Testing tools
Paulo Clavijo @pclavijo
Cork Software Crafters
Mutant for Ruby
Infection for PHP
MutMut for Python
...
for JS, TS, C# and Scalafor Java
Mutation Testing
23. Gilded Rose Kata
Your task is to add the new feature to our system so that we can begin selling a new
category of items.
● "Conjured" items degrade in Quality twice as fast as normal items
Feel free to make any changes to the UpdateQuality method and add any new code as
long as everything still works correctly. However, do not alter the Item class or Items
property.
github.com/Cork-Software-Craftsmanship-Community/GildedRose_Refactoring_Kata
https://github.com/emilybache/GildedRose-Refactoring-Kata
Cork Software Crafters Paulo Clavijo (@pclavijo)
24. Some advice
- Find the most idented piece of logic and start refactoring from the right.
- Try flattening conditional logic.
- A if statement can be removed if we add it to each of is nested statements.
- Remove inverted logic on conditional predicates.
- Make conditionals similar. Split conditionals (we will duplicate code during
some steps).
Cork Software Crafters Paulo Clavijo (@pclavijo)
25. Retrospective
● What went well?
● What problems did you encounter?
● What have you learned?
● What surprised you?
Paulo Clavijo (@pclavijo)Cork Software Crafters