Unit Testing and TDD Flashcards
Unit Testing
Testing units in a system, in OOP this means individual classes and methods. Should account for most of the testing in a project and done by developers.
JUNIT
testing framework for java using Maven.
Anatomy of a Unit Test
Setup
Exercise
Verify
Teardown
Before and After Methods
- Setup and Teardown actions can be repetitive across tests.
- JUNIT provides easy ways of defining these
- Methods tagged with @BeforeEach will run before each test
- Same way with @AfterEach
- BeforeAll and AfterAll are the same
What makes a good unit test
- Descriptive name
- Tests one thing
- Always returns the same result
- Has no conditional logic
- Independent of other tests
- So understandable that it acts as documentation
What makes a bad unit test
- Interacts with external databases
- Communicates across a network
- Interacts with a file system
- Must be executed after specific tests
- Requires configuration of the environment
Code Coverage
Measure used to describe how much of the source code has been executed when the test suite runs. The goal is at least 80%.
Does 100% code coverage mean no bugs?
No, there might be unreachable code
Test Driven Development
Write enough code to pass the test
Benefits of TDD
- Driven by clear goals
- Safer Code
- Isolation of incorrect code
- Easily introduce new functionality
- Document the application as you go
Testing Doubles
Dealing with indirect inputs and outputs, an object in place of a real component for the purpose of running a test, includes; dummies, spies, stubs and mocks.
Dummy Objects
Degenerate form of test double, not used by the DOC or used in a limited manner. Usually an alternative to using null objects. Only exist to be passed around
Test Stubs
Replace a real component on which SUT depends. Delivers a pre-canned response and produces indirect input to force the execution of specific code paths.
Test Spies
More advanced form of stub, besides producing indirect inputs, spies can monitor and record indirect outputs. Test driver can verify with a spy that something has been produced.
Mock Objects
Powerful, do everything a stub or spy does but also verifies SUT behavior. Test driver tells the mock what sort of behavior is expected during the test, and the mock will verify that the behavior was observed. Using mocks requires proper layering of your system.
Setting up a Mock with Mockito
- Define TimeProvider Interface
- Write your SUT code
- Write your tests using mocks
You don’t need to create an interface for every item you want to mock, especially if the class you want to mock is not implemented.
Test Patterns
A design pattern is similar to a recipe where a solution to a common design problem is explained. Test patterns are the same way but in testing. Directly influence the system design.
Dependency Injection
Avoid hardcoding dependencies into the system, find a way to allow depended upon components to be set at runtime (Parameter, Constructor, Setter Injection)
Dependency Lookup
Design system in order to look up dependencies at runtime when their need arises. Usually a factory approach is taken. Tests can gain control of the factory to then control dependencies for testing purposes.