About the author
Introduction
- Conventions
- Code of examples
- Errata
- Install the JDK
Book structure
1.Testing
- 1.1Automated tests
- 1.2Advantages of automated tests
- 1.3Test-Driven Development (TDD)
- 1.3.1Behavioral-Driven Development (BDD)
2.Eclipse
- 2.1Eclipse workspace
- Resource in Eclipse
- 2.2Perspectives and views
- 2.3Projects
- 2.3.1Importing an existing project
- 2.3.2Creating a new Java project
- 2.3.3Open projects and closed projects
- 2.3.4Automatic building
- 2.4IDE tools
- 2.4.1Content Assist
- 2.4.2Quick Fix
- 2.4.3Quick Assist
- 2.4.4Editable proposals
- 2.4.5The Source menu
- 2.5Eclipse Preferences
- 2.6Find Actions
- 2.7Eclipse Shortcuts
- 2.7.1Quick Search
- 2.8Eclipse Run configurations
- 2.9Browsing code
- 2.9.1Outline
- 2.9.2Navigate
- Camel Case
- 2.9.3Local History
- 2.10Code Mining
3.JUnit
- 3.1Structure of a test
- Test fixture
- 3.2A first example
- Do you spot any problems in the above test?
- 3.2.1Exception testing
- 3.2.2Other tests
- Code injection for package-private
- 3.2.3Revising
- Have we now tested everything correctly?
- 3.3External collaborators (dependencies)
- Dependency Injection
- 3.3.1Alternative implementations
- 3.4Testing private methods?
- 3.5Keep your tests clean and readable
- 3.5.1Beware of code duplication removal in tests
- 3.6Other testing libraries
- 3.6.1Using Hamcrest matchers
- 3.6.2Using AssertJ
- 3.7Keeping test code separate from main code
- 3.7.1Export a runnable JAR
- 3.8JUnit 5
4.TDD
- 4.1Introduction to TDD
- 4.1.1The Red-Green-Refactor cycle
- 4.1.2The three laws of TDD
- 4.1.3Remove duplication
- 4.2The Transformation Priority Premise
- 4.2.1A first example of TDD
- 4.3Three strategies for the green state
- 4.3.1The factorial example with TDD
- Remove redundant tests
- This is not a formal proof
- 4.4Small or big steps?
- 4.5Tests and induction (part 1)
- 4.6TDD with JUnit 4 Parameterized Tests
- 4.7TDD with JUnit 5 Parameterized Tests
- 4.8Testing abstract classes?
- 4.9Writing a test that succeeds
5.Code coverage
- 5.1JaCoCo and EclEmma
- 5.2How code coverage can help
- 5.3Code coverage percentage
6.Mutation Testing
- 6.1The first example with PIT
- Mutation testing requires a green suite.
- Bugs are likely to live in untested code
- 6.2Enabling additional mutators
- 6.3Further experiments with PIT
- 6.3.1Tests and induction (part 2)
- 6.3.2Mutations and iterative solutions
- 6.3.3Mutation testing on the MyStringUtils example
- 6.3.4Mutation testing on the Bank example
- 6.4Narrowing mutations
7.Maven
- 7.1Introduction to Maven
- 7.2Maven installation
- 7.3Let’s get started with a Maven archetype
- 7.3.1Create a Maven project from the command line
- 7.3.2Import a Maven project in Eclipse
- 7.3.3Create a Maven project from Eclipse using an archetype
- 7.4Structure of a Maven project
- 7.5Java settings
- 7.6Dependencies
- 7.6.1Maven coordinates (GAV)
- 7.6.2Dependencies in the POM
- 7.6.3SNAPSHOT
- 7.6.4Version ranges
- 7.7Eclipse m2e
- Output folders in a Maven project
- 7.8Properties
- 7.9Resources
- 7.9.1Layout of an Eclipse project
- 7.9.2Create a Maven project from Eclipse without an archetype
- 7.10The Eclipse m2e pom.xml multi-tab editor
- 7.11The bank example as a Maven project
- 7.12Build with Maven
- 7.12.1Maven lifecycles
- 7.12.2Run Maven from the command line
- 7.12.3Run Maven goals
- 7.12.4Run Maven from Eclipse
- 7.12.5Offline mode
- 7.12.6Updating dependencies
- 7.13Maven packaging
- 7.13.1Packaging “jar”
- 7.13.2Packaging “pom”
- 7.14Parent and modules
- 7.14.1Let’s create a parent project and a module project
- 7.14.2Effective POM
- 7.14.3Project aggregation and project inheritance
- 7.14.4Build a single module
- 7.14.5Dependency management
- 7.14.6Bill of Material (BOM)
- 7.14.7How Eclipse resolves the projects in the workspace
- 7.15Configuring a Maven plugin
- 7.15.1Configuring the Maven compiler plugin
- 7.15.2Generate source and javadoc jars
- 7.15.3Configuring the generated jar
- 7.15.4Creating a FatJar
- 7.15.5Plugin management
- 7.15.6Configuring the PIT Maven plugin
- 7.15.7Configuring the JaCoCo Maven plugin
- 7.16Maven profiles
- 7.16.1Don’t abuse profiles
- 7.17The bank example as a multi-module project
- 7.17.1The bank BOM
- 7.17.2The bank parent POM
- 7.17.3The bankaccount project
- 7.17.4The bank project
- 7.17.5The bank report project
- 7.17.6The bank app project
- 7.17.7The aggregator project
- 7.18JUnit 5 and Maven
- 7.19Maven deploy
- 7.20Maven wrapper
- 7.21Beyond Java 8
- 7.22Reproducibility in the build
8.Mocking
- 8.1Testing state and testing interactions
- 8.2Mockito: an overview
- 8.2.1Creating a mock
- 8.2.2Method stubbing
- 8.2.3Interaction verification
- 8.3Mockito: a tutorial
- The Repository pattern
- VerificationCollector
- 8.3.1Spy
- 8.3.2Spying and stubbing
- 8.3.3Stubbing and exceptions
- 8.3.4Subsequent stubbing
- 8.3.5Argument matchers
- 8.4Alternative ways of initializing mocks and other elements
- 8.5Mockito BDD style
- 8.6Mockito and JUnit 5
- 8.7Stubbing with answers
- 8.7.1Another example: Transactions
- 8.8Fakes
- 8.9What to mock
9.Git
- 9.1Let’s start experimenting with Git
- 9.1.1Create a git repository
- 9.1.2Git configuration
- Dealing with line endings
- 9.1.3States of the working tree
- 9.1.4Perform a commit
- 9.1.5Commit history
- 9.1.6Ignore files and directories
- 9.1.7Branches
- 9.1.8Reset
- 9.1.9Cherry-pick
- 9.1.10Stash
- 9.2Remote repositories
- 9.2.1Bare repository
- 9.2.2Adding a remote repository
- 9.2.3Initialize an empty remote repository
- 9.2.4Cloning a remote repository
- 9.2.5Push and fetch
- Forcing a push
- 9.2.6Rebasing
- 9.2.7Pull requests
- 9.3EGit (Git in Eclipse)
- 9.3.1Add an Eclipse project to a new Git repository
- 9.3.2The Git Repositories view
- 9.3.3Importing an existing project
- 9.3.4Branch operations
- 9.3.5Cloning from Eclipse
- 9.4GitHub
- 9.4.1Create a repository on GitHub
- 9.4.2GitHub pull requests
- 9.4.3Contributing to other projects
10.Continuous Integration
- 10.1Our running example
- 10.2GitHub Actions
- 10.2.1Caching dependencies
- 10.3Build matrix
- 10.3.1Building using different JDKs
- 10.3.2Building using different operating systems
- 10.3.3Configuring the build matrix
- 10.4Building pull requests
- 10.4.1Multiple workflows
- 10.5Storing artifacts
- 10.6Code coverage in CI
- 10.7Code coverage with Coveralls
- 10.7.1Using Coveralls from our computer
- 10.7.2Using Coveralls from GitHub Actions
- 10.7.3Coverage threshold
- 10.8Badges
- 10.9Reproducibility in CI
- 10.10Let’s revise our build process
- 10.11Automated dependency updates with Dependabot
- 10.12Further steps
11.Docker
- 11.1Let’s get started with Docker
- 11.2Run a server in a container
- 11.3Dockerize a Java application
- 11.3.1The Java application to dockerize
- 11.3.2The Dockerfile
- 11.4Windows containers
- 11.5Build the Docker image from Maven
- 11.6Using Docker in GitHub Actions
- 11.7Docker networks
- 11.8Docker compose
- 11.8.1Control startup order of container
- 11.9Docker in Eclipse
- 11.10Push to DockerHub
- 11.11Reproducibility in Docker
12.Integration tests
- 12.1Our running example
- 12.2Unit tests with databases
- 12.2.1Mock the MongoClient?
- 12.2.2Use an in-memory database
- 12.3Integration tests
- 12.3.1Source folder for integration tests
- 12.3.2Integration tests with Docker and Testcontainers
- 12.3.3Running integration tests with Maven
- 12.3.4Integration tests with Docker and Maven
- 12.3.5Running integration tests in GitHub Actions
- 12.4Unit or integration tests?
13.UI tests
- 13.1The running example
- 13.2UI unit tests
- AssertJ Swing in Linux
- AssertJ Swing in macOS
- 13.2.1Testing the GUI controls
- Don’t interact with the computer
- 13.2.2Implementing the StudentView interface
- 13.2.3Unit tests for the UI frame’s logic
- 13.3Running UI tests in GitHub Actions
- 13.4UI integration tests
- 13.5Multithreading
- 13.5.1Race conditions in the application
- 13.5.2Race conditions in the database
- 13.6Improvements
14.End-to-end tests
- 14.1The running example
- 14.2E2e tests for our application
- 14.3BDD with Cucumber
- 14.3.1Data tables
- 14.3.2Step decoupling
- 14.3.3High-level specifications
- 14.4Starting from the high-level specifications
- 14.5Change some low-level details
15.Code Quality
- 15.1Using SonarQube locally
- 15.2Analyze a project
- 15.2.1False positives and rule exclusion
- 15.2.2Analysis of test code
- 15.2.3Security hotspots
- 15.2.4Code coverage in SonarQube
- 15.3SonarCloud
- 15.4SonarLint (IDE integration)
16.Learning tests
- 16.1Dependency Injection with Google Guice
- 16.1.1Guice main concepts
- 16.1.2Singleton
- 16.1.3Field and method injection
- What to prefer
- 16.1.4Providers
- 16.1.5Binding annotations
- 16.1.6Overriding bindings
- 16.1.7Factories and AssistedInject
- 16.1.8Cyclic dependencies
- 16.1.9Provides
- 16.2Apply our learnings