These are the slides from my talk at the Norwegian Developer conference in Oslo 2013 on why unit testing is not necessarily the best way to test our code.
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Unit Tests are Overrated (NDCOslo 2013)
1. Unit Tests are Overrated
Lars-Erik Kindblad
Senior Consultant
Twitter: @kindblad
2. Unit Testing Misconceptions
1. Unit tests can talk to a database, web service etc.
Not true: That’s integration tests. A unit test tests a class or method in isolation using
stubs or mocks.
When people say that unit testing is great they might actually mean integration testing
2. Unit tests ensure that a system works 100%
Not true: A unit test is not an end-to-end test. It only verifies that the class is working in
isolation, it does not verify that it works and integrates with other classes
3. Unit tests allow for safe refactoring
Not true: Unit tests are too detailed tests. Small refactoring such as splitting a class in two
forces the unit tests to be changed
4. Unit tests improve the code quality
Not true: Unit tests don’t automatically improve code quality. There are a lot of bad unit
tested code
5. Unit tests reduce the technical debt
Not true: Very hard to write good unit tests. Big chance that the technical debt increases
3. Unit Testing Misconceptions
6. 100% unit test coverage means the system is bug free
Not true: Code coverage only tells us what was executed by our unit tests, not if it was
executed correctly
int Foo(int a, int b) { return a / b; }
would need more than one test to be verified 100% but one test is enough to get 100%
code coverage
7. Unit testing can replace the QA resources
Not true:
Developers are really bad at finding bugs
Unit tests can have bugs
The requirements could have been misunderstood and implemented wrongly
8. Unit tests are the documentation
Not true: Most developer trust their code more than their unit tests. The code itself should
be self documenting
4. A Better Way – Use Case Testing
Integration tests that focuses on the use cases
Business Layer
Infrastructure Layer (DAL)
Presentation/
Services Layer
Endpoints
Database Web Service
Filesystem SMTP Service Bus
Class Class
Class
Class
Use Case Tests Assert on:
Result from the presentation/services
layer
Endpoints result or that the endpoints
have received the messages
Advantage:
Tests at a higher level than unit tests
Safe and fast to refactor
Only have to update the tests when the
functionality changes
Verifies the quality from top to
bottom, from the start of the use case
to the end
Can write the tests based on the QA
test cases
5. 1. Challenge – Testing the Presentation Layer
A lot of changes happens all the time – the tests must be updated
continually
A lot of infrastructure setup and concerns makes it hard to test
6. Solution
Add a Use Case Layer for delivery mechanism indepent use cases
Advantage:
No dependencies to ASP.NET, WPF
or WP.
100% testable through DTO’s
Most critical functionality are verified
Disadvantage:
The presentation layer is not verified
The Use Cases Layer and the layers below are
most critical, a serious error can corrupt the
system
Use Cases Layer
Business Layer
Infrastructure Layer
Presentation Layer
Use Case Tests
Data Transfer Objects
Endpoints
7. 2. Challenge – Test Data & Verification
Data at the endpoints changes constantly
Breaks the tests
Impossible to verify the result
10. 3. Challenge - Non-Controllable Endpoints
Don’t have access to delete and create testdata at the endpoint
Not possible to verify the result at the endpoint
Cannot verify our use case
11. Business Logic
Use Cases
Tests
Database
SMTP
Server
Solution
Create a copy of the existing endpoint to use it for testing only
Replace the endpoint with a fake endpoint using dependency inversion
& the Onion Architecture to verify the flow of the use case
- ICustomerRepository
- IEmailSender
- FakeEmailSender
- CustomerRepository
- EmailSender
13. 4. Challenge - Slow Tests
Takes too long to run
Solution:
Better to have slow tests that verify the quality 100% than fast tests that do
not
Replace the endpoints with fake in-memory endpoints
14. Test Strategy
The test strategy for my current project:
1. Write use case tests to verify the end-to-end quality
Important to test both the success- and the fail scenarios
2. Write unit tests or integration tests to test complex logic and algorithms
such as calculations
3. When using fake endpoints for testing: Write integration tests to verify
that the basics of the non-fake implementations work.
Every project is different = Define your own test strategy!