How John started to like TDD (instead of hating it) (Testcon, October'25)
icougil
13 views
124 slides
Oct 22, 2025
Slide 1 of 124
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
About This Presentation
Let me share a story about how John (a developer like any other) started to understand (and enjoy) writing Tests before the Production code.
We've all felt an inevitable "tedium" when writing tests, haven't we? If it's boring, if it's complicated or unnecessary? Isn't ...
Let me share a story about how John (a developer like any other) started to understand (and enjoy) writing Tests before the Production code.
We've all felt an inevitable "tedium" when writing tests, haven't we? If it's boring, if it's complicated or unnecessary? Isn't it? John thought so too, and, as much as he had heard about writing tests before production code, he had never managed to put it into practice, and even when he had tried, John had become even more frustrated at not understanding how to put it into practice outside of a few examples katas π€·ββοΈ
Listen to this story in which I will explain how John went from not understanding Test Driven Development (TDD) to being passionate about it... so much that now he doesn't want to work any other way π ! He must have found some benefits in practising it, right? He says he has more advantages than working in any other way (e.g., you'll find defects earlier, you'll have a faster feedback loop or your code will be easier to refactor), but I'd better explain it to you in the session, right? Ah! And if you think everything will be theoretical, no! Get ready to see code examples with Spring Boot.
PS: Think of John as a random person, as if he was even the speaker of this talk π !
---
Presentation shared at Testcon, October'25
How John started to like TDD (instead of hating it) October, 2025
Who am I? Nacho Cougil Principal Software Engineer at Dynatrace TDD & clean code fan Started to write in Java before Y2K Founder of the Barcelona Java Users Group ( BarcelonaJUG ) & co-founder of the Barcelona Developers Conference ( DevBcn ) former Java and JVM Barcelona Conference Java Champion Father, former mountain marathon runner π @ icougil icougil.bsky.social https://mastodon.social/@icougil This presentation
3
4
5
6 And at some point β¦ 6
Lack of testing 7
Long-lived branches 8
Make others wait (until your work is done) The task XXX is not finished βIs because <write here your excuse argument>β βWe were waiting to do Yβ¦ based on what you have to finish with Zβ βOur feature was based on your implementation around Xβ 9
New requests came in 10 Sometimes were⦠Interesting Incompatible Incomprehensible Not mature enough ⦠Too late
11 Complexity
Many things to take into account 12 Remember thatβ¦ βWhen you have to do X β¦ you must have a record in the Database with Yβ βActivate this flag in Z before running Aβ βRemember to write into Kafka B after doing Cβ βFor testing D we need a license for Eβ βF is incompatible with the version Gβ β¦
At the end⦠many reasons 17 Lack of testing Long-lived branches Make others wait New requests came in Complexity Many things to take into account Adapt to changes Invalid documentation Limited time Building tests was boring
18
19
20
21 Same problems again !?
22
Questions came to his mind 23 βThere are surely practices to improveβ βThere must be practices that should help minimizing the risksβ To share/deliver things faster and with small chunks To not having to keep many things in your mind To adapt to changes easily Have a better documentation Enjoy writing tests
Learn from others 24 Started attending meetupsβ¦ Someone mentioned many practices and concepts that he didnβt kn o w or he couldnβt practice Feedback-loop Simple design Small releases Pair-programming Refactoring Test D r iven Development (TDD)
Started to grew 25 Listening more Reading more books Practicing P ersonal projects Katas Writing less βsmart β code ο more β easy to read β code, easy to test code
Tried to applied at work⦠26 Katas VS real projects Deadlines & commitments Initial time investment Learning curve Maintenance challenges Legacy projects Code does not do what you expect Lack of documentation Non-testable designed solution Different ways of developing Complexity
Tried to applied at workβ¦ 27 Couldnβt make it β¦ ended up causing frustration
Until one day⦠28
29
30 1 2 3 Specify what you would like to implement Develop what the tests describes. No more no less TDD Anything we can leave better? Red Green Refactor
31 But, generalizing⦠INPUT PROCESS OUTPUT
32 But, generalizingβ¦
33
34 But, generalizing⦠INPUT PROCESS OUTPUT
35 But, how can we use TDD in a real-case scenario ?
Build a solution that retrieves the amount of resources (CPU usage, memory consumption, etc) being used by different services /endpoints A process must periodically check the resources being used from different services Weβll act as we're Java/backend developers π (using Spring Boot) to build an API 36 Letβs see an example π
37 ... Service 1 https://service1... DB Sync Resource Usages Process U sage resources Service 2 https://service2... List Resource Usages GET / resourceUsages POST / resourceUsages / sync:execute API π
38 https://github.com/icougil/resource_usage
From the DB to the external endpoint ( from the DB ο business logic ο endpoint ) From the process that connects to the services, to the DB and endpoint ( internal process ο to the DB / business logic ο endpoint ) From the external endpoint that triggers the process, to the DB ( endpoint ο business logic ο DB ) 39 Approaches
From the DB to the external endpoint ( from the DB ο business logic ο endpoint ) From the process that connects to the services, to the DB and endpoint ( internal process ο to the DB / business logic ο endpoint ) From the external endpoint that triggers the process, to the DB ( endpoint ο business logic ο DB ) 40 Approaches
41 1. From the DB to the external endpoint Business layer Use cases (Services) Presentation layer Controllers Repositories Data access Storage DB
42 1. From the DB to the external endpoint Time
43 Change DB model Change database structure 1. From the DB to the external endpoint Time
44 Implement save usage resources in a repository Change DB model Implement the repository to save the resource usage (guessing how β¦ π€ ) Change database structure 1. From the DB to the external endpoint Time Questions araised π€ I s it working as expected? no tests at all Will we have to change something? signatures will change?
45 Implement save usage resources in a repository Change DB model Business logic: list of usage resources to save Implement the repository to save the resource usage (guessing how β¦ π€ ) Change database structure Implement part of the business logic by saving a list of usage resources (guessing howβ¦ π€) 1. From the DB to the external endpoint Time Questions π€ I s it working as expected? Will we have to change something? Questions π€
46 Implement save usage resources in a repository Business logic: find all the services and connect to all of them, asking for their resource usage Change DB model Business logic: list of usage resources to save Implement the repository to save the resource usage (guessing how β¦ π€ ) Retrieve the list of existing services and for each one, connect to it and ask for their resource usage Change database structure Implement part of the business logic by saving a list of usage resources (guessing howβ¦ π€) 1. From the DB to the external endpoint Time Questions π€ Questions π€
47 Questions π€ I s it working as expected? Will we have to change something? How we will handle errors?
48 Implement save usage resources in a repository Business logic: find all the services and connect to all of them, asking for their resource usage Change DB model Business logic: list of usage resources to save Controller: implement the endpoint that triggers the sync between all services Implement the repository to save the resource usage (guessing how β¦ π€ ) Change database structure Implement part of the business logic by saving a list of usage resources (guessing howβ¦ π€) Implement the endpoint that triggers the synchronization for all services 1. From the DB to the external endpoint Time Retrieve the list of existing services and for each one, connect to it and ask for their resource usage Questions π€ Questions π€ Questions π€
49 Questions π€ I s it working as expected? Will we have to change something? (But at least, we can start triggering something manually π)
50 Implement save usage resources in a repository Business logic: find all the services and connect to all of them, asking for their resource usage Tests for the repository Change DB model Business logic: list of usage resources to save Controller: implement the endpoint that triggers the sync between all services Implement the repository to save the resource usage (guessing how β¦ π€ ) Test if the method we created for saving data works as expected Change database structure Implement part of the business logic by saving a list of usage resources (guessing howβ¦ π€) Implement the endpoint that triggers the synchronization for all services 1. From the DB to the external endpoint Time Retrieve the list of existing services and for each one, connect to it and ask for their resource usage Questions π€ Questions π€ Questions π€ Questions π€, but π
51 Finally !! π We are verifying something is working as expected !
52 Implement save usage resources in a repository Business logic: find all the services and connect to all of them, asking for their resource usage Tests for the repository Tests for the business logic Change DB model Business logic: list of usage resources to save Controller: implement the endpoint that triggers the sync between all services Implement the repository to save the resource usage (guessing how β¦ π€ ) Test if the method we created for saving data works as expected Change database structure Implement part of the business logic by saving a list of usage resources (guessing howβ¦ π€) Implement the endpoint that triggers the synchronization for all services Tests for retrieving all the information for all the services. Tests when something goes wrong (and probably add logic around it? π€) 1. From the DB to the external endpoint Time Retrieve the list of existing services and for each one, connect to it and ask for their resource usage Questions π€ Questions π€ Questions π€ Questions π€, but π Verifying β
53 Finally !! π We are verifying the business logic is working as expected !
54 Questions araised π€ What we should do here? Should we return an error and change the methods / Endpoint?
55 Implement save usage resources in a repository Business logic: find all the services and connect to all of them, asking for their resource usage Tests for the repository Tests for the business logic Change DB model Business logic: list of usage resources to save Controller: implement the endpoint that triggers the sync between all services Implement the repository to save the resource usage (guessing how β¦ π€ ) Test if the method we created for saving data works as expected Change database structure Implement part of the business logic by saving a list of usage resources (guessing howβ¦ π€) Implement the endpoint that triggers the synchronization for all services Tests for retrieving all the information for all the services. Tests when something goes wrong (and probably add logic around it? π€) 1. From the DB to the external endpoint Time Retrieve the list of existing services and for each one, connect to it and ask for their resource usage Questions π€ Questions π€ Questions π€ Questions π€, but π Verifying β Tests for the endpoint & Acceptance test Verifying β , but changes ? π€ Create Acceptance test to verify that the entire workflow works as expected. Define/implement the behavior when something goes wrong.
56 Finally we closed the loop ! π π Created the acceptance test for the happy path
57 Verifying some of the wrong scenarios π What about the wrong scenarios? π€
58 Wait, π€ letβs try now with a few more servicesβ¦ π₯π€¦ββοΈ
59 π₯π€¦ββοΈ Wait !? We found the overall solution does not work π₯π !? : we're forcing our clients to wait β³ for the overall process ?! ο timeouts π₯π (going to all the services and check their resource consumption) Redesign βΌ We will need to think about how to implement to handle them π€. Found issues ο The final solution is not working !? π₯π We will need to change our internal business logic π€ βΌοΈ
60 Implement save usage resources in a repository Business logic: find all the services and connect to all of them, asking for their resource usage Tests for the repository Tests for the business logic Change DB model Business logic: list of usage resources to save Controller: implement the endpoint that triggers the sync between all services Implement the repository to save the resource usage (guessing how β¦ π€ ) Test if the method we created for saving data works as expected Change database structure Implement part of the business logic by saving a list of usage resources (guessing how β¦ π€) Implement the endpoint that triggers the synchronization for all services Tests for retrieving all the information for all the services. Tests when something goes wrong (and probably add logic around it? π€) 1. From the DB to the external endpoint Time Retrieve the list of existing services and for each one, connect to it and ask for their resource usage Questions π€ Questions π€ Questions π€ Questions π€, but π Verifying β Verifying β , but changes ? π€ Verifying β , closed the loop π C hanges π€ Not working π₯π ο redesign βΌοΈ Create Acceptance test to verify that the entire workflow works as expected. Define/implement the behavior when something goes wrong. Tests for the endpoint & Acceptance test
61 1. From the DB to the external endpoint Time Questions π€ Questions π€ Questions π€ Questions π€, but π Verifying β Verifying β , but changes ? π€ Verifying β , closed the loop π C hanges π€ Not working π₯π ο redesign βΌοΈ Implement save usage resources in a repository Business logic: find all the services and connect to all of them, asking for their resource usage Tests for the repository Tests for the business logic Change DB model Business logic: list of usage resources to save Controller: implement the endpoint that triggers the sync between all services Tests for the endpoint & Acceptance test
1. From the DB to the external endpoint 62 It looks like we progressed from the very beginningβ¦ Simple process: we knew what we should do next (normally) We could share changes with the team ( git commit and push ) but with uncertainty β( no tests ). Doubts π€ to know if we were building things correctly ( building but not testing )
64 1. From the DB to the external endpoint 2. From the Business logic to the DB and external endpoint 3. From the external endpoint to the DB Process +/- easy to follow, but with doubts β Solution working Until the end of the time β Share/push code ββ (no tests) Trigger the code β React to changes ( feedback-loop ) β See the progress No progress until the end of the time β Risks of redesign High πΊ Summary
From the DB to the external endpoint ( from the DB ο business logic ο endpoint ) From the process that connects to the services, to the DB and endpoint ( internal process ο to the DB / business logic ο endpoint ) From the external endpoint that triggers the process, to the DB ( endpoint ο business logic ο DB ) 65 Approaches
66 Business layer Use cases (Services) Presentation layer Controllers Repositories Data access Storage DB 2. From the process that connects to the services, to the DB and endpoint
67 Time 2. From the process that connects to the services, to the DB and endpoint
68 Business logic: find all the services and connect to all of them, asking for their resource usage Retrieve the list of existing services and for each one, connect to it and ask for their resource usage Time 2. From the process that connects to the services, to the DB and endpoint
69 Questions π€ What should we do here? How can we continue? In which way? Should we create the methods we need β¦ and putting this βon holdβ ? How should we handle the errors? Will it work as expected?
70 Business logic: list of usage resources to save Business logic: find all the services and connect to all of them, asking for their resource usage Implement part of the business logic by saving a list of usage resources Retrieve the list of existing services and for each one, connect to it and ask for their resource usage 2. From the process that connects to the services, to the DB and endpoint Questions π€ / βstandbyβ β Questions π€ What should we do here? How can we continue? Should we create the methods we need β¦ and putting this βon holdβ ? Will it work as expected?
71 Business logic: list of usage resources to save Business logic: find all the services and connect to all of them, asking for their resource usage Implement save usage resources in a repository Implement part of the business logic by saving a list of usage resources Retrieve the list of existing services and for each one, connect to it and ask for their resource usage Implement the repository to save the resource usage Time 2. From the process that connects to the services, to the DB and endpoint Questions π€ / βstandbyβ β Questions π€ / βstandbyβ β
72 Questions π€ How can we trigger it? Will it work as expected?
73 Business logic: list of usage resources to save Change DB model Business logic: find all the services and connect to all of them, asking for their resource usage Implement save usage resources in a repository Implement part of the business logic by saving a list of usage resources Retrieve the list of existing services and for each one, connect to it and ask for their resource usage Implement the repository to save the resource usage Time Change database structure Questions π€ 2. From the process that connects to the services, to the DB and endpoint Questions π€ / βstandbyβ β Questions π€ / βstandbyβ β
74 Business logic: list of usage resources to save Change DB model Business logic: find all the services and connect to all of them, asking for their resource usage Implement save usage resources in a repository Controller: implement the endpoint that triggers the sync between all services Implement part of the business logic by saving a list of usage resources Retrieve the list of existing services and for each one, connect to it and ask for their resource usage Implement the repository to save the resource usage Implement the endpoint that triggers the synchronization for all services Time Change database structure Questions π€ 2. From the process that connects to the services, to the DB and endpoint Questions π€ / βstandbyβ β Questions π€ / βstandbyβ β Questions π€
75 Questions π€ I s it working as expected? Will we have to change something? (But at least, we can start triggering something manually π)
76 Business logic: list of usage resources to save Change DB model Business logic: find all the services and connect to all of them, asking for their resource usage Implement save usage resources in a repository Controller: implement the endpoint that triggers the sync between all services Implement part of the business logic by saving a list of usage resources Retrieve the list of existing services and for each one, connect to it and ask for their resource usage Implement the repository to save the resource usage Implement the endpoint that triggers the synchronization for all services Time Change database structure Questions π€ Questions π€ Questions π€, but π 2. From the process that connects to the services, to the DB and endpoint Questions π€ / βstandbyβ β Questions π€ / βstandbyβ β This scenario looks familiar β¦ π€
77 Implement save usage resources in a repository Business logic: find all the services and connect to all of them, asking for their resource usage Tests for the repository Tests for the business logic Change DB model Business logic: list of usage resources to save Controller: implement the endpoint that triggers the sync between all services Implement the repository to save the resource usage (guessing how β¦ π€ ) Test if the method we created for saving data works as expected Change database structure Implement part of the business logic by saving a list of usage resources (guessing howβ¦ π€) Implement the endpoint that triggers the synchronization for all services Tests for retrieving all the information for all the services. Tests when something goes wrong (and probably add logic around it? π€) 1. From the DB to the external endpoint Time Retrieve the list of existing services and for each one, connect to it and ask for their resource usage Questions π€ Questions π€ Questions π€ Questions π€, but π Verifying β Verifying β , but changes ? π€ Verifying β , closed the loop π C hanges π€ Not working π₯π ο redesign βΌοΈ Create Acceptance test to verify that the entire workflow works as expected. Define/implement the behavior when something goes wrong. Tests for the endpoint & Acceptance test
78 Business logic: list of usage resources to save Change DB model Tests for the repository Tests for the business logic Business logic: find all the services and connect to all of them, asking for their resource usage Implement save usage resources in a repository Controller: implement the endpoint that triggers the sync between all services Implement part of the business logic by saving a list of usage resources Test if the method we created for saving data works as expected Retrieve the list of existing services and for each one, connect to it and ask for their resource usage Implement the repository to save the resource usage Implement the endpoint that triggers the synchronization for all services Tests for retrieving all the information for all the services. Tests when something goes wrong (and probably add logic around it? π€) Time Change database structure Questions π€ Questions π€ Questions π€, but π Verifying β Verifying β , but changes ? π€ Verifying β , closed the loop π C hanges π€ Not working π₯π ο redesign βΌοΈ Create Acceptance test to verify that the entire workflow works as expected. Define/implement the behavior when something goes wrong. Tests for the endpoint & Acceptance test 2. From the process that connects to the services, to the DB and endpoint Questions π€ / βstandbyβ β Questions π€ / βstandbyβ β
79 Business logic: list of usage resources to save Change DB model Tests for the repository Tests for the business logic Business logic: find all the services and connect to all of them, asking for their resource usage Implement save usage resources in a repository Controller: implement the endpoint that triggers the sync between all services Implement part of the business logic by saving a list of usage resources Test if the method we created for saving data works as expected Retrieve the list of existing services and for each one, connect to it and ask for their resource usage Implement the repository to save the resource usage Implement the endpoint that triggers the synchronization for all services Tests for retrieving all the information for all the services. Tests when something goes wrong (and probably add logic around it? π€) Time Change database structure Questions π€ Questions π€ Questions π€, but π Verifying β Verifying β , but changes ? π€ Verifying β , closed the loop π C hanges π€ Not working π₯π ο redesign βΌοΈ Create Acceptance test to verify that the entire workflow works as expected. Define/implement the behavior when something goes wrong. Tests for the endpoint & Acceptance test 2. From the process that connects to the services, to the DB and endpoint Questions π€ / βstandbyβ β Questions π€ / βstandbyβ β
80 Business logic: list of usage resources to save Change DB model Tests for the repository Tests for the business logic Business logic: find all the services and connect to all of them, asking for their resource usage Implement save usage resources in a repository Controller: implement the endpoint that triggers the sync between all services Time Questions π€ Questions π€ Questions π€, but π Verifying β Verifying β , but changes ? π€ Verifying β , closed the loop π C hanges π€ Not working π₯π ο redesign βΌοΈ Tests for the endpoint & Acceptance test 2. From the process that connects to the services, to the DB and endpoint Questions π€ / βstandbyβ β Questions π€ / βstandbyβ β
2. From the process that connects to the services, to the DB and endpoint 81 It seems that starting from the business layer was not a good idea β¦ Process not clear π€: we didnβt know what we should do next ( continue with data access layer or the external endpoint ? ) Commits in red π΄ ? (build failure) Couldnβt share changes with the team ( git commit, no push ) (even worst than the previous approach) Doubts π€ to know if we were building things correctly ( building but not testing )
83 1. From the DB to the external endpoint 2. From the Business logic to the DB and external endpoint Process +/- easy to follow, but with doubts β Not clear β Solution working Until the end of the time β Until the end of the time β Share/push code ββ (no tests) β Trigger the code β β React to changes ( feedback-loop ) β β See the progress No progress until the end of the time β (even less than option 1.) β Risks of redesign High πΊ High πΊ Summary
From the DB to the external endpoint ( from the DB ο business logic ο endpoint ) From the process that connects to the services, to the DB and endpoint ( internal process ο to the DB / business logic ο endpoint ) From the external endpoint that triggers the process, to the DB ( endpoint ο business logic ο DB ) 84 Approaches
85 Business layer Use cases (Services) Presentation layer Controllers Repositories Data access Storage DB 3. From the external endpoint that triggers the process to the DB
86 Time 3. From the external endpoint that triggers the process to the DB
87 Test for the Acceptance tests Emergent / simple design Create the Acceptance test. Design the solution we expect to build. Time 3. From the external endpoint that triggers the process to the DB
88
89
90
91
92
93
94 Test for the Acceptance tests Emergent / simple design Create the Acceptance test. Design the solution we expect to build. Time Create the controller/endpoint Implement the minimum to solve the test Solve the Acceptance test Designing π§βπ¨ and building 3. From the external endpoint that triggers the process to the DB
122 1. From the DB to the external endpoint 2. From the Business logic to the DB and external endpoint 3. From the external endpoint to the DB Process +/- easy to follow, but with doubts β Not clear β Easy to follow π Solution working Until the end of the time β Until the end of the time β From the very beginning π Share/push code ββ (no tests) β Always (even with commits in π΄) Trigger the code β β β React to changes ( feedback-loop ) β β β See the progress No progress until the end of the time β (even less than option 1.) β β Risks of redesign High πΊ High πΊ Low π» Summary
Immediate / fast feedback loop 123 Weβd like to react super fast π to changes! If we have a problem, it is better to identify it as soon as we can We can trigger/activate things (as our clients will do) !
124 No unnecessary code Our tests serves as a guide/reference As we specify what we want to buildβ¦ Less things are implemented because β what ifβ We will build only what we specify Ensure that every step we take is in the right direction (no step is done without knowing it is mandatory)