Slide 1

Slide 1 text

Too many mocks killed the test What Hexagonal Architecture has changed Icons made by Icongeek26, Freepik from www.flaticon.com Jean-Marie Lamodière - Backend tech lead @jmlamodiere @swcraftlyon Slow Fast, Focus

Slide 2

Slide 2 text

WHY ? Locking Tests vs. TDD Development Locking Tests Development TDD +50% Icons made by Roundicons from www.flaticon.com “I mock almost nothing” - Kent Beck https://youtu.be/z9quxZsLcfo?t=1270

Slide 3

Slide 3 text

WHY ? Kurt Lewin Change Theory https://sanzubusinesstraining.com/kurt-lewin-change-model/ “...but everyone test like that” - Your colleagues

Slide 4

Slide 4 text

WHY ? Icons made by Freepik from www.flaticon.com Refactor locking tests https://github.com/JMLamodiere/tdd-demo-forumphp2020 POO, sync 2 demo projects Tests first https://github.com/JMLamodiere/tdd-demo-swcraftlyon-scala POO, async

Slide 5

Slide 5 text

WHY ? Icons made by Freepik from www.flaticon.com https://github.com/JMLamodiere/tdd-demo-forumphp2020 /Application /Command RegisterRunningSession RegisterRunningSessionHandler /Domain WeatherProvider(Interface) RunningSession RunningSessionRepo(Interface) /Infrastructure /Http HttpAccuWeatherProvider CurrentConditionDeserializer /Database PostgresRunningSessionRepo /Infrastructure /Symfony RunningSessionController RegisterRunningSessionDeserializer RunningSessionSerializer Technical Business Technical

Slide 6

Slide 6 text

WHY ? Icons made by Freepik from www.flaticon.com https://github.com/JMLamodiere/tdd-demo-swcraftlyon-scala /Application /Command RegisterRunningSession RegisterRunningSessionHandler /Domain WeatherProvider(Interface) RunningSession RunningSessionRepo(Interface) /Infrastructure /Http HttpAccuWeatherProvider /Database PostgresRunningSessionRepo /Infrastructure /AkkaHttp RunningSessionPostController JsonSupport Technical Business Technical

Slide 7

Slide 7 text

WHY ? ...But that’s DDD? No it’s hexagonal! https://afup.org/talks/3037-de-crud-a-ddd-comment-meetic-a-sauve-son-legacy 4k vues 😱

Slide 8

Slide 8 text

● A Functional Test describes a behaviour ● A Unit Test locks an implementation Prejudice #1 Icons made by Freepik from www.flaticon.com Could you review my PR before I write my Unit Tests ?

Slide 9

Slide 9 text

● A Functional Test describes a behaviour ● A Unit Test locks an implementation Prejudice #1 Icons made by Roundicons from www.flaticon.com All tests describe an expected public behaviour Only the audience and the size of the covered area vary Test Desiderata - Kent Beck : https://kentbeck.github.io/TestDesiderata/

Slide 10

Slide 10 text

“Unit Test” = 1 method of 1 class Prejudice #2 Icons made by Freepik from www.flaticon.com

Slide 11

Slide 11 text

“Unit Test” = 1 method of 1 class Prejudice #2 Icons made by Roundicons, Smashicons from www.flaticon.com Polysemy! Wrong debate... “A DeveloperTest is the correct name for what the industry generally calls a UnitTest” - Ward Cunningham The Unit Test trap : https://drpicox.medium.com/the-unit-test-trap-4a83e4012b17

Slide 12

Slide 12 text

● Test Pyramid = big Unit Test coverage ● Unit Test = mock other classes Prejudice #3 Icons made by Freepik from www.flaticon.com

Slide 13

Slide 13 text

● Test Pyramid = big Unit Test coverage ● Unit Test = mock other classes Prejudice #3 Icons made by Roundicons, Smashicons from www.flaticon.com Favor fast and focused tests. Ex: The Practical Test Pyramid : https://martinfowler.com/articles/practical-test-pyramid.html Slow Fast, Focus Sociable Unit Test UI component test Unit Tests on Adapters

Slide 14

Slide 14 text

Only functional tests have 3 steps: ● Given ● When ● Then Prejudice #4 Icons made by Freepik from www.flaticon.com

Slide 15

Slide 15 text

Only functional tests have 3 steps: ● Given ● When ● Then Prejudice #4 Icons made by Roundicons from www.flaticon.com All tests follow the narrative structure: ● Given = Arrange ● When = Act ● Then = Assert Setup Catalyst Resolution

Slide 16

Slide 16 text

Prejudice #5 Icons made by Freepik from www.flaticon.com Checking the number of calls to all mocked methods increases my confidence. ->expects($this->exactly(1))->method('xxx') ->shouldBeCalledTimes(1)

Slide 17

Slide 17 text

Prejudice #5 Checking the number of calls to all mocked methods increases my confidence ->expects($this->exactly(1))->method('xxx') ->shouldBeCalledTimes(1) Icons made by Roundicons, Smashicons from www.flaticon.com ● Blurs the intent of the test ● Locks implementation details ● Impossible to write first

Slide 18

Slide 18 text

WHY ? What to test ? Subject Under Test (S.U.T.) Arguments (IN) Return value (OUT) Test Calls Collaborator (IN) Collaborator (OUT) Assert Stub : willReturn() Spy : shouldHaveBeenCalled() Given When Then Then

Slide 19

Slide 19 text

I must know the splitting between my classes before I write my tests Prejudice #6 Icons made by Freepik from www.flaticon.com

Slide 20

Slide 20 text

I must know the splitting between my classes before I write my tests Prejudice #6 Icons made by Roundicons from www.flaticon.com ● Prod classes splitting != test classes splitting ● Start with an area with a known boundary

Slide 21

Slide 21 text

WHY ? Icons made by Freepik from www.flaticon.com /Application /Command RegisterRunningSession RegisterRunningSessionHandler /Domain WeatherProvider(Interface) RunningSession RunningSessionRepo(Interface) /Infrastructure /Http HttpAccuWeatherProvider CurrentConditionDeserializer /Database PostgresRunningSessionRepo /Infrastructure /Symfony RunningSessionController RegisterRunningSessionDeserializer RunningSessionSerializer Technical Business Technical 1st test: area with a known boundary

Slide 22

Slide 22 text

Prejudice #7 Icons made by Freepik from www.flaticon.com If I don't mock my Entities / DTOs, too many tests will break if I add a field

Slide 23

Slide 23 text

Prejudice #7 Icons made by Roundicons from www.flaticon.com If I don't mock my Entities / DTOs, too many tests will break if I add a field ● Use test Factori(es) with optional fields ● Getter not covered ? I remove it

Slide 24

Slide 24 text

Prejudice #8 Icons made by Freepik from www.flaticon.com I can mock the libraries used on the Infrastructure side : ● Http : Guzzle… ● Database : Doctrine, Eloquent…

Slide 25

Slide 25 text

Prejudice #8 Icons made by Roundicons, Smashicons from www.flaticon.com I can mock the libraries used on the Infrastructure side : ● Http : Guzzle… ● Database : Doctrine, Eloquent… ● Coupled with the usage details of the lib ● Assumptions about the way it behaves ● Impossible to write first ● No confidence when upgrading the lib

Slide 26

Slide 26 text

WHY ? Infrastructure : Integration Tests Icons made by Freepik, Smashicons, Roundicons from www.flaticon.com QueryBuilder -> pure SQL MysqlRepository Docker mysql HttpRepository Wiremock Guzzle -> Symfony HttpClient Refactoring eg.

Slide 27

Slide 27 text

WHY ? “Don’t mock what you don’t own” Icons made by Freepik, Smashicons, Roundicons from www.flaticon.com /Application /Command RegisterRunningSession RegisterRunningSessionHandler /Domain WeatherProvider(Interface) RunningSession RunningSessionRepo(Interface) /Infrastructure /Http HttpAccuWeatherProvider CurrentConditionDeserializer /Database PostgresRunningSessionRepo Unit/Fast/Small tests Integration Mock No Mock!

Slide 28

Slide 28 text

Prejudice #9 Icons made by Freepik from www.flaticon.com Functional Test = necessarily end to end

Slide 29

Slide 29 text

Prejudice #9 Icons made by Roundicons, smashicons from www.flaticon.com Functional Test = necessarily end to end ● Slow ● Brittle ● Difficult to maintain ● Harder to write first ● Locks Infrastructure choices too soon Suggestion : mock Secondary Ports

Slide 30

Slide 30 text

WHY ? Icons made by Freepik from www.flaticon.com /Application /Command RegisterRunningSession RegisterRunningSessionHandler /Domain WeatherProvider(Interface) RunningSession RunningSessionRepo(Interface) /Infrastructure /Http HttpAccuWeatherProvider CurrentConditionDeserializer /Database PostgresRunningSessionRepo /Infrastructure /Symfony RunningSessionController RegisterRunningSessionDeserializer RunningSessionSerializer Suggestion Functional Integration

Slide 31

Slide 31 text

WHY ? Icons made by Freepik from www.flaticon.com Suggestion Functional Integration Outside-in Diamond 🔷 TDD - Thomas Pierrain http://tpierrain.blogspot.com/2021/03/outside-in-diamond-tdd-1-style-made.html

Slide 32

Slide 32 text

@jmlamodiere Thanks! Development Locking tests Development TDD +50% Icons made by Roundicons, Freepik from www.flaticon.com It’s your turn ! ● //Given //When //Then ● Even if I write a test afterwards, I only write what I would have been sure of before https://github.com/JMLamodiere/tdd-demo-forumphp2020 https://github.com/JMLamodiere/tdd-demo-swcraftlyon-scala @swcraftlyon