The primary goal of the microservice architecture is to enable the rapid, reliable delivery of software with DevOps. One of the pillars of DevOps is automated testing, yet many organizations attempt to adopt microservices while still doing manual testing. What’s more, the microservice architecture has its own distinctive automated testing challenges.
This presentation describes how to descend the testing pyramid and replace slow, brittle, end-to-end tests with faster, more reliable tests for individual services. You will learn how to write tests that ensure that service APIs evolve while preserving backward compatibility. You’ll learn how, by running these tests in a deployment pipeline, you will fully benefit from microservices.
7. @crichardson
The state of automated testing
today: Oops!
https://cdn.agilitycms.com/sauce-labs/white-papers/sauce-labs-state-of-testing-2018.pdf
😢
8. @crichardson
+
Marketplace is volatile, uncertain, complex
and ambiguous
+
Businesses must innovate faster
Deliver software rapidly, frequently and reliably
Software
9. Daily
Commits
Use DevOps & Continuous
Delivery/Deployment
A highly testable
and deployable architecture is
essential
ApplicationAutomated deployment pipeline
Production
Source code
repository
Automated testing is essential
10. @crichardson
The problem with a large,
complex monolith
Time
Maintainability
Testability
Deployability
Modularity
Evolvability
Size/
Complexity
-ilities required to be competitive
Risk of
disruption
11. The microservice architecture is
an architectural style
that structures an application as a
set of services
Each microservice is:
• highly maintainable and testable
• loosely coupled
• independently deployable
• organized around business capabilities
• owned by a small team
12. @crichardson
Autonomous service teams
Order
Service
Automated deployment pipeline
Source code repository
Kitchen
Service
Automated deployment pipeline
Source code repository
Delivery
Service
Automated deployment pipeline
Source code repository
Production
Orders Team
Kitchen Team
Delivery Team
13. @crichardson
Microservices enable DevOps
DevOps requires automated testing
Complexity of microservices requires good
automated testing
Using the Microservice Architecture
without automated testing
is self-defeating AND risky
http://bit.ly/msa-antipattern-flying-before-walking
14. @crichardson
What is a test?
Test
System
under test
(SUT)
Verifies behavior
• SUT = thing being tested = class … entire application
• Collection of tests = Test Suite
15. @crichardson
The testing pyramid and
microservices
Unit
Integration
Includes consumer-driven contract tests
Component
End to End
Classes within
service
A services adapters
An entire service
Multiple services or application
Brittle, Slow,
Costly
Reliable, Fast,
Cheap
16. Agenda
Overview of testing
microservices
Unit testing
Integration testing
Component testing
End to end testing
Testing in production Unit
testing Unit
Integration
Component
End to End
18. @crichardson
Business logic
Controller
POST /something
GET /something/id
Database
Database
adapter
Inbound
Message
Adapter
Repository
Service
Entity
Value object
Outbound
Message
Adapter
Unit test
Unit test
Unit test
Saga
<<Message Channel>>
<<Message Channel>>
Primary focus is
the business logic
“algorithms"
Unit testing
adapters is
sometimes useful
Maybe unit test
coordination logic
26. @crichardson
Contract testing example
Request from consumer
Response from service
Describes
Written by
API Gateway
Team API definition
by example
Order
Service
Proxy
Order
Controller
GET /orders/{id}
ProviderConsumer
28. @crichardson
Provider-side contract test
Class BaseHttp {
}
class HttpTest
extends
BaseHttp {…
Spring Cloud
Contract
Code
generates
Reads
Configures
with mock
OrderRepository
Order
Controller
Tests
Order
Repository
Must be
consistent
Verify API
structure matches
contracts
GET /orders/{id}
29. @crichardson
Assumption:
If consumer and provider are tested
independently with the same contracts
Consumer and provider can communicate
OrderService
Proxy
Order
Controller
Test Test
30. @crichardson
Agenda
Overview of testing microservices
Unit testing
Integration testing
Component testing
End to end testing
Testing in production
Unit
Integration
Component
End to End
31. Goal of component testing
Minimalist
Verify that the container is
deployable
Passes health check
…
VS.
Acceptance tests
Real world/user focussed
But avoid duplicating unit and
integration tests
Component
Test
Service
Verifies
behavior
In isolation
32. @crichardson
Test process (eg. JVM)
In-process component testing
In-memory
database
Test
Some Service
REST API
Outbound adapter, eg. Service Proxy
Mock IPC, e.g. RestTemplate/Messaging
Some other service
Messaging API
Configures mocks
38. @crichardson
Agenda
Overview of testing microservices
Unit testing
Integration testing
Component testing
End to end testing
Testing in production Unit
Integration
Component
End to End
39. @crichardson
End to End testing verifies
behavior of application
End to End
Test
FTGO application
Order
Service
Consumer
Service
…
https://docs.cucumber.io/gherkin/
41. About scenario-based end-to-
end testing
Typically, BDD user scenarios = original
requirements user focussed/real
world
Parallelization can accelerate testing
BUT
Duplicates tests lower down the
pyramid
Brittle, slow, complex
Potential bottleneck that delays getting
changes (e.g. bug fixes) into production
Use selectively based on risk
My Bank App
Given …
When …
Then …
Loan
Repayment
Calculator
Loan
Document
Generator
Slow External
Service
Bottleneck
42. @crichardson
Replace end-to-end tests with
per-service (component) tests
My Bank App
Given …
When …
Then …
Loan
Repayment
Calculator
Loan
Document
Generator
Slow External
Service
My Bank App
Loan
Repayment
Calculator
Loan
Document
Generator
Slow external
Service
Given …
When …
Then …
Given …
When …
Then …
Bottleneck only for
Loan Document
Generator
46. @crichardson
Testing in production*
Separate
Deployment - running in production
Release - available to users
Test code
Before releasing
When releasing
Automate for fast deployment, rollback and roll forward
* a.k.a. Validation in production
https://medium.com/@copyconstruct/testing-in-production-the-safe-way-18ca102d0ef1
47. Order Service
V1
Order Service
V2
Test deployed code before
releasing: e.g. Canary release
1.Deploy V2 alongside V1
2.Test V2
3.Route test traffic to V2
4.Release V2 to a small % of production
users
5.Monitor/test (latency, errors) - undo
rollout if errors
6. Increase % of production traffic going
to V2
7.Repeat until 100% of traffic going to V2
8.Eventually undeploy V1
Intelligent
traffic router
Order Service
V1
Order Service
V2
Monitoring system
48. Feature toggles/flags
A toggle controls which of several
code paths is used
Release toggle - allow incomplete
code to be safely committed/
deployed during trunk based
development
Ops toggles - enable Ops to
enable/disable features
Permissioning toggles - user
attribute features/experience
Experiment toggles - e.g. A/B
testing
https://martinfowler.com/articles/feature-toggles.html
49. @crichardson
Summary
Use the microservice architecture accelerate software delivery by
improving testability and deployability
Using microservices without automated testing is self-defeating AND risky
Accelerate the deployment pipeline by pushing testing as far down the
test pyramid as possible
End-to-end tests:
Use selectively
Replace with per-service tests as much as possible
Test in production for reliable deployments/releases