Author(s): Alex Garcia, Viktor Farcic
Edition: 2
Publisher: Packt
Year: 2018
Cover
Title Page
Copyright and Credits
Packt Upsell
Contributors
Table of Contents
Preface
Chapter 1: Why Should I Care for Test-Driven Development?
Why TDD?
Understanding TDD
Red-Green-Refactor
Speed is the key
It's not about testing
Testing
Black-box testing
White-box testing
The difference between quality checking and quality assurance
Better tests
Mocking
Executable documentation
No debugging
Summary
Chapter 2: Tools, Frameworks, and Environments
Git
Virtual machines
Vagrant
Docker
Build tools
The integrated development environment
The IDEA demo project
Unit-testing frameworks
JUnit
TestNG
Hamcrest and AssertJ
Hamcrest
AssertJ
Code coverage tools
JaCoCo
Mocking frameworks
Mockito
EasyMock
Extra power for mocks
User interface testing
Web-testing frameworks
Selenium
Selenide
Behavior-driven development
JBehave
Cucumber
Summary
Chapter 3: Red-Green-Refactor – From Failure Through Success until Perfection
Setting up the environment with Gradle and JUnit
Setting up Gradle/Java project in IntelliJ IDEA
The Red-Green-Refactor process
Writing a test
Running all the tests and confirming that the last one is failing
Writing the implementation code
Running all the tests
Refactoring
Repeating
Tic-Tac-Toe game requirements
Developing Tic-Tac-Toe
Requirement 1 – placing pieces
Test – board boundaries I
Implementation
Test – board boundaries II
Implementation
Test – occupied spot
Implementation
Refactoring
Requirement 2 – adding two-player support
Test – X plays first
Implementation
Test – O plays right after X
Implementation
Test – X plays right after O
Requirement 3 – adding winning conditions
Test – by default there's no winner
Implementation
Test – winning condition I
Implementation
Refactoring
Test – winning condition II
Implementation
Test – winning condition III
Implementation
Test – winning condition IV
Implementation
Refactoring
Requirement 4 – tie conditions
Test – handling a tie situation
Implementation
Refactoring
Code coverage
More exercises
Summary
Chapter 4: Unit Testing – Focusing on What You Do and Not on What Has Been Done
Unit testing
What is unit testing?
Why unit testing?
Code refactoring
Why not use unit tests exclusively?
Unit testing with TDD
TestNG
The @Test annotation
The @BeforeSuite, @BeforeTest, @BeforeGroups, @AfterGroups, @AfterTest, and @AfterSuite annotations
The @BeforeClass and @AfterClass annotations
The @BeforeMethod and @AfterMethod annotations
The @Test(enable = false) annotation argument
The @Test(expectedExceptions = SomeClass.class) annotation argument
TestNG versus JUnit summary
Remote-controlled ship requirements
Developing the remote-controlled ship
Project setup
Helper classes
Requirement – starting point and orientation
Specification – keeping position and direction in memory
Implementation
Refactoring
Requirement – forward and backward moves
Specification – moving forward
Implementation
Specification – moving backward
Implementation
Requirement – rotating the ship
Specification – turning left
Implementation
Specification – turning right
Implementation
Requirement – commands
Specification – single commands
Implementation
Specification – combined commands
Implementation
Requirement – representing spheric maps
Specification – planet information
Implementation
Refactoring
Specification – dealing with map boundaries
Implementation
Requirement – detecting obstacles
Summary
Chapter 5: Design – If It's Not Testable, It's Not Designed Well
Why should we care about design?
Design principles
You Ain't Gonna Need It
Don't Repeat Yourself
Keep it simple, stupid
Occam's razor
SOLID principles
Connect 4
Requirements
Test-last implementation of Connect 4
Requirement 1 – the game's board
Requirement 2 – introducing discs
Requirement 3 – player shifts
Requirement 4 – the game's output
Requirement 5 – win conditions (I)
Requirement 6 – win condition (II)
Requirement 7 – win condition (III)
Requirement 8 – win condition (IV)
The TDD or test-first implementation
Hamcrest
Requirement 1 – the game's board
Requirement 2 – introducing discs
Requirement 3 – player shifts
Requirement 4 – the game's output
Requirement 5 – win condition (I)
Requirement 6 – win condition (II)
Requirement 7 – win condition (III)
Requirement 8 – win condition (IV)
Final considerations
Summary
Chapter 6: Mocking – Removing External Dependencies
Mocking
Why mocks?
Terminology
Mock objects
Mockito
Tic-Tac-Toe v2 requirements
Developing Tic-Tac-Toe v2
Requirement 1 – store moves
Specification – DB name
Implementation
Specification – a name for the Mongo collection
Implementation
Refactoring
Specification – adding items to the Mongo collection
Implementation
Specification – adding operation feedback
Implementation
Refactoring
Specification – error handling
Implementation
Specification – clear state between games
Implementation
Specification – drop operation feedback
Implementation
Specification – error handling
Implementation
Requirement 2 – store every turn
Specification – creating new collection
Implementation
Specification refactoring
Specification – storing current move
Implementation
Specification – error handling
Implementation
Specification – alternate players
Implementation
Exercises
Integration tests
Tests separation
The integration test
Summary
Chapter 7: TDD and Functional Programming – A Perfect Match
Setting up the environment
Optional – dealing with uncertainty
Example of Optional
Functions revisited
Kata – Reverse Polish Notation
Requirements
Requirement – handling invalid input
Requirement – single operations
Requirement – complex operations
Streams
filter
map
flatMap
reduce
Summary
Chapter 8: BDD – Working Together with the Whole Team
Different specifications
Documentation
Documentation for coders
Documentation for non-coders
Behavior-driven development
Narrative
Scenarios
The book store BDD story
JBehave
JBehave runner
Pending steps
Selenium and Selenide
JBehave steps
Final validation
Summary
Chapter 9: Refactoring Legacy Code – Making It Young Again
Legacy code
Legacy code example
Other ways to recognize legacy code
A lack of dependency injection
The legacy code change algorithm
Applying the legacy code change algorithm
Identifying change points
Finding test points
Breaking dependencies
Writing tests
The kata exercise
Legacy kata
Description
Technical comments
Adding a new feature
Black-box or spike testing
Preliminary investigation
How to find candidates for refactoring
Introducing the new feature
Applying the legacy code algorithm
Writing end-to-end test cases
Automating the test cases
Injecting the BookRepository dependency
Extract and override call
Parameterizing a constructor
Adding a new feature
Removing the primitive obsession with status as int
Summary
Chapter 10: Feature Toggles – Deploying Partially Done Features to Production
Continuous integration, delivery, and deployment
Feature Toggles
A Feature Toggle example
Implementing the Fibonacci service
Working with the template engine
Summary
Chapter 11: Putting It All Together
TDD in a nutshell
Best practices
Naming conventions
Processes
Development practices
Tools
Summary
Chapter 12: Leverage TDD by Implementing Continuous Delivery
Case study – Awesome Gambling Corp
Exploring the codebase
Release procedure
Deployments to production
Conclusions
Possible improvements
Increasing test coverage
Implementing continuous integration
Towards continuous delivery
Jenkins installation
Automating builds
First execution
What is next?
This is just the beginning
This does not have to be the end
Summary
Other Books You May Enjoy
Index