Table of Contents

Preface

Who this book is for

What this book covers

To get the most out of this book

Download the example code files

Download the color images

Conventions used

Get in touch

Share Your Thoughts

Download a free PDF copy of this book

Part 1: How We Got to TDD

1

Building the Case for TDD

Writing code badly

Understanding why bad code is written

Recognizing bad code

Bad variable names

Bad function, method, and class names

Error-prone constructs

Coupling and cohesion

Decreasing team performance

Diminishing business outcomes

Summary

Questions and answers

Further reading

2

Using TDD to Create Good Code

Designing good quality code

Say what you mean, mean what you say

Take care of the details in private

Avoid accidental complexity

Revealing design flaws

Analyzing the benefits of writing tests before production code

Preventing logic flaws

Protecting against future defects

Documenting our code

Summary

Questions and answers

Further reading

3

Dispelling Common Myths about TDD

Writing tests slows me down

Understanding the benefits of slowing down

Overcoming objections to tests slowing us down

Tests cannot prevent every bug

Understanding why people say tests cannot catch every bug

Overcoming objections to not catching every bug

How do you know the tests are right?

Understanding the concerns behind writing broken tests

Providing reassurance that we test our tests

TDD guarantees good code

Understanding problem-inflated expectations

Managing your expectations of TDD

Our code is too complex to test

Understanding the causes of untestable code

Reframing the relationship between good design and simple tests

Managing legacy code without tests

I don’t know what to test until I write the code

Understanding the difficulty of starting with testing

Overcoming the need to write production code first

Summary

Questions and answers

Further reading

Part 2: TDD Techniques

4

Building an Application Using TDD

Technical requirements

Preparing our development environment

Installing the IntelliJ IDE

Setting up the Java project and libraries

Introducing the Wordz application

Describing the rules of Wordz

Exploring agile methods

Reading user stories – the building block of planning

Combining agile development with TDD

Summary

Questions and answers

Further reading

5

Writing Our First Test

Technical requirements

Starting TDD: Arrange-Act-Assert

Defining the test structure

Working backward from outcomes

Increasing workflow efficiency

Defining a good test

Applying the FIRST principles

Using one assert per test

Deciding on the scope of a unit test

Catching common errors

Asserting exceptions

Only testing public methods

Preserving encapsulation

Learning from our tests

A messy Arrange step

A messy Act step

A messy Assert step

Limitations of unit tests

Code coverage – an often-meaningless metric

Writing the wrong tests

Beginning Wordz

Summary

Questions and answers

6

Following the Rhythms of TDD

Technical requirements

Following the RGR cycle

Starting on red

Keep it simple – moving to green

Refactoring to clean code

Writing our next tests for Wordz

Summary

Questions and answers

Further reading

7

Driving Design – TDD and SOLID

Technical requirements

Test guide – we drive the design

SRP – simple building blocks

Too many responsibilities make code harder to work with

Ability to reuse code

Simplified future maintenance

Counter-example – shapes code that violates SRP

Applying SRP to simplify future maintenance

Organizing tests to have a single responsibility

DIP – hiding irrelevant details

Applying DI to the shapes code

LSP – swappable objects

Reviewing LSP usage in the shapes code

OCP – extensible design

Adding a new type of shape

ISP – effective interfaces

Reviewing ISP usage in the shapes code

Summary

Questions and answers

8

Test Doubles – Stubs and Mocks

Technical requirements

The problems collaborators present for testing

The challenges of testing unrepeatable behavior

The challenges of testing error handling

Understanding why these collaborations are challenging

The purpose of test doubles

Making the production version of the code

Using stubs for pre-canned results

When to use stub objects

Using mocks to verify interactions

Understanding when test doubles are appropriate

Avoiding the overuse of mock objects

Don’t mock code you don’t own

Don’t mock value objects

You can’t mock without dependency injection

Don’t test the mock

When to use mock objects

Working with Mockito – a popular mocking library

Getting started with Mockito

Writing a stub with Mockito

Writing a mock with Mockito

Blurring the distinction between stubs and mocks

Argument matchers – customizing behavior of test doubles

Driving error handling code with tests

Testing an error condition in Wordz

Summary

Questions and answers

Further reading

9

Hexagonal Architecture –Decoupling External Systems

Technical requirements

Why external systems are difficult

Environmental problems bring trouble

Accidentally triggering real transactions from tests

What data should we expect?

Operating system calls and system time

Challenges with third-party services

Dependency inversion to the rescue

Generalizing this approach to the hexagonal architecture

Overview of the hexagonal architecture’s components

The golden rule – the domain never connects directly to adapters

Why the hexagon shape?

Abstracting out the external system

Deciding what our domain model needs

Writing the domain code

Deciding what should be in our domain model

Using libraries and frameworks in the domain model

Deciding on a programming approach

Substituting test doubles for external systems

Replacing the adapters with test doubles

Unit testing bigger units

Unit testing entire user stories

Wordz – abstracting the database

Designing the repository interface

Designing the database and random numbers adapters

Summary

Questions and answers

Further reading

10

FIRST Tests and the Test Pyramid

Technical requirements

The test pyramid

Unit tests – FIRST tests

Integration tests

What should an integration test cover?

Testing database adapters

Testing web services

Consumer-driven contract testing

End-to-end and user acceptance tests

Acceptance testing tools

CI/CD pipelines and test environments

What is a CI/CD pipeline?

Why do we need continuous integration?

Why do we need continuous delivery?

Continuous delivery or continuous deployment?

Practical CI/CD pipelines

Test environments

Testing in production

Wordz – integration test for our database

Fetching a word from the database

Summary

Questions and answers

Further reading

11

Exploring TDD with Quality Assurance

TDD – its place in the bigger quality picture

Understanding the limits of TDD

No more need for manual testing?

Manual exploratory – discovering the unexpected

Code review and ensemble programming

User interface and user experience testing

Testing the user interface

Evaluating the user experience

Security testing and operations monitoring

Incorporating manual elements into CI/CD workflows

Summary

Questions and answers

Further reading

12

Test First, Test Later, Test Never

Adding tests first

Test-first is a design tool

Tests form executable specifications

Test-first provides meaningful code coverage metrics

Beware of making a code coverage metric a target

Beware of writing all tests upfront

Writing tests first helps with continuous delivery

We can always test it later, right?

Test-later is easier for a beginner to TDD

Test-later makes it harder to test every code path

Test-later makes it harder to influence the software design

Test-later may never happen

Tests? They’re for people who can’t write code!

What happens if we do not test during development?

Testing from the inside out

Testing from the outside in

Defining test boundaries with hexagonal architecture

Inside-out works well with the domain model

Outside-in works well with adapters

User stories can be tested across the domain model

Summary

Questions and answers

Further reading

Part 3: Real-World TDD

13

Driving the Domain Layer

Technical requirements

Starting a new game

Test-driving starting a new game

Tracking the progress of the game

Triangulating word selection

Playing the game

Designing the scoring interface

Triangulating game progress tracking

Ending the game

Responding to a correct guess

Triangulating the game over due to too many incorrect guesses

Triangulating response to guess after game over

Reviewing our design

Summary

Questions and answers

Further reading

14

Driving the Database Layer

Technical requirements

Installing the Postgres database

Creating a database integration test

Creating a database test with DBRider

Driving out the production code

Implementing the WordRepository adapter

Accessing the database

Implementing GameRepository

Summary

Questions and answers

Further reading

15

Driving the Web Layer

Technical requirements

Starting a new game

Adding required libraries to the project

Writing the failing test

Creating our HTTP server

Adding routes to the HTTP server

Connecting to the domain layer

Refactoring the start game code

Handling errors when starting a game

Fixing the unexpectedly failing tests

Playing the game

Integrating the application

Using the application

Summary

Questions and answers

Further reading

Index

Other Books You May Enjoy

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.15.147.20