Modern distributed architectures are increasingly composed of large numbers of decoupled, asynchronous components. In AWS, these components are plumbed together via services like SQS, SNS, Kinesis and S3 often integrated via small and frequent numbers of microservices or lambdas. But how do you test these architectures if they are cloud native?
It’s 2018, and we can do better than deploying the entire stack and running a battery of E2E tests against them.
In his talk, Matt will demonstrate how you can scale development of large-scale systems across teams, technology and process, and unlock the agility of your cloud-native architecture.
WARNING: there will be code (https://github.com/mefellows/serverless-testing-example)
5. 5
If you can’t build a good monolith you
shouldn’t be doing microservices
Architecture > Microservices
6. Entry criteria to
make µServices
● Ability to write a modular monolith
● Strong grasp on your domain model
● Ability to design loosely coupled services
○ = state + transactions
● Ability to scale and decouple teams
● Ability to deploy continuously
● A strong “DevOps” culture
● Be comfortable with decentralised,
complex systems + uncertainty
Architecture > Microservices
7. ...the µServices
ride
● Ability to write a modular monolith
● Strong grasp on your domain model
● Ability to design loosely coupled services
○ = state + transactions
● Ability to scale and decouple teams
● Ability to deploy continuously
● A strong “DevOps” culture
● Be comfortable with decentralised,
complex systems + uncertainty
Architecture > Microservices
8. ...the µServices
ride
● Ability to write a modular monolith
● Strong grasp on your domain model
● Ability to design loosely coupled services
○ = state + transactions
● Ability to scale and decouple teams
● Ability to deploy continuously
● A strong “DevOps” culture
● Be comfortable with decentralised,
complex systems + uncertainty
Architecture > Microservices
9. ...the µServices
ride
● Ability to write a modular monolith
● Strong grasp on your domain model
● Ability to design loosely coupled services
○ = state + transactions
● Ability to scale and decouple teams
● Ability to deploy continuously
● A strong “DevOps” culture
● Be comfortable with decentralised,
complex systems + uncertainty
Architecture > Microservices
10. WHAT WE ARE KNOWN FOR
10
Microservices
Evolution Drivers for levelling up
● Increase time-to-value
● Increase utilisation / cost
reduction
● Raise abstraction; focus on
composition
● Scale product teams
● Massively distributed,
real-time apps
● API contracts (e.g. OAS)
● Ubiquity of cloud computing
● Rise of containers
● Unreliable networking /
components
● Rise of the Service Mesh
● Improved observability
Architecture > Microservices
28. WHAT WE ARE KNOWN FOR
28
Options
● Multi-cloud = lowest
common denominator
● There is always a vendor
(even if it’s you!)
● You’ll never be completely
vendor agnostic
● Multi-cloud abstraction
● Avoid altogether
● Structure your code better
Challenges
Challenges > Vendor lock-in
29. WHAT WE ARE KNOWN FOR
29
Options
● Multi-cloud = lowest
common denominator
● There is always a vendor
(even if it’s you!)
● You’ll never be completely
vendor agnostic
● Multi-cloud abstraction
● Avoid altogether
● Structure your code better
Challenges
Challenges > Vendor lock-in
36. Summary
Architecture > Microservices
● Separate protocol handling from
business logic
● Business logic shouldn’t change with
introduction of a new protocol
● Port, Adapter and Business Logic are
independently testable
37. 37
How do you test locally?
Challenges > Testing Locally
38. WHAT WE ARE KNOWN FOR
38
Options
Challenges > Testing Locally
● Stub services (e.g. Localstack)
● Stub API (e.g. Moto)
● Multiple handlers
● Unit tests
40. WHAT WE ARE KNOWN FOR
40
Options
● Feature arms race
● Trustworthy?
● Integration style = slower
● All cloud providers?
● Stub services (e.g. Localstack)
● Stub API (e.g. Moto)
● Multiple handlers
● Unit tests
Challenges > Testing Locally
Challenges
41. WHAT WE ARE KNOWN FOR
41
Writing good unit tests
● Follow test pyramid
● Stub out AWS APIs
● Test your business logic
separately from any
serverless features (e.g.
lambda handler)
● Callback pyramid of death
● Tests are hard to write
● Your business logic knows
about AWS
● You have to stub multiple
services per test
● Large methods
● Confusing control flow
Challenges > Testing Locally > Unit Test
Code Smells
47. Summary
Architecture > Microservices
● Business logic should be tested
separately from port + adapter
● Majority of tests, should be fast unit
tests
● Stub AWS Services where required
● (Lambda) Handlers can be locally
integration tested with pre-canned JSON
events
50. WHAT WE ARE KNOWN FOR
50
Options
● Local integration testing
● Cloud env. integration testing
● Contract testing
Challenges > Async
51. WHAT WE ARE KNOWN FOR
51
Options
● Can’t run complete local
environment
● Many moving parts
● Problems with integration
testing...
● Local integration testing
● Cloud env. integration testing
● Contract testing
Challenges
Challenges > Async
52. WHAT WE ARE KNOWN FOR
52
Options
● Can’t run complete local
environment
● Many moving parts
● Problems with integration
testing...
● Local integration testing
● Cloud env. integration testing
● Contract testing
Challenges
Challenges > Async
57. WHAT WE ARE KNOWN FOR
57
Problems with automated e2e tests
● Slow
● Easy to break
● Hard to fix
● Scales badly across teams
● Lots of set up maintenance
● $$ potentially costly
Challenges > Async > Contract Tests
59. WHAT WE ARE KNOWN FOR
59
Test symmetry
Solved problems New problems
● Hard to keep both sides in
sync
● Fast feedback
● Few dependencies
● No dedicated environment
● Reliable
● Easy to debug
Challenges > Async > Contract Tests