SlideShare a Scribd company logo
Luca@gerritforge.com
http://www.gerritforge.com
Twitter: @gitenterprise
TDD
Dead or Alive?
Luca Milanesio
GerritForge
http://visionwidget.com/images/2010-4/0405/Wanted_Poster.jpg
Platinum Sponsor
2 .io
About me
• Luca Milanesio
Co-founder of GerritForge
• over 20 years of experience
in Agile Development
SCM and ALM worldwide
• Contributor to Jenkins
since 2007 (and previously Hudson)
• Git SCM mentor
for the Enterprise since 2009
• Contributor to Gerrit Code Review community since 2011
3 .io
Agenda
 Why?
 TDD-induced damage
 Evangelist vs. Professional
 Reboot
 Professional TDD
 Learning to write
4 .io
TDD is 20 years old
http://www.macqueen.us/smalltalkReport/ST/91_95/SMAL0402.PDF
5 .io
TDD has been widely adopted
http://www.indeed.com/jobtrends?q=test+driven+development&relative=1
6 .io
Hold on … what's that ?
http://www.indeed.com/jobtrends?q=test+driven+development&relative=1
7 .io
… and that ?
http://martinfowler.com/articles/is-tdd-dead/
8 .io
Test-induced design damage
By David Heinemeier Hansson on April 29, 2014
http://david.heinemeierhansson.com/2014/test-induced-design-damage.html
"Code that's hard to test in isolation is poorly designed", goes a common TDD maxim.
Isolation meaning free of dependent context and separated from collaborators, especially "slow" ones like database or file IO.
The prevalent definition of "unit" in unit testing (though not everyone agrees with this).
This is some times true. Some times finding it difficult to test points to a design smell. It may be tangled
responsibilities or whatever. But that's a far ways off from declaring that hard-to-unit-test code is always poorly designed, and
always in need of repair. That you cannot have well-designed code that is hard to unit test.
It's from this unfortunate maxim that much of the test-induced design
damage flows. Such damage is defined as changes to your code that either facilitates a) easier test-first, b) speedy
tests, or c) unit tests, but does so by harming the clarity of the code through — usually through needless
indirection and conceptual overhead. Code that is warped out of shape solely to
accommodate testing objectives.
9 .io
TDD EXAMPLE DAMAGE
ON A
LARGE PROJECT
https://www.flickr.com/photos/martinluff/5475631631
10 .io
Code metrics of one service
340 Java Classes
880 Tests
158 Mocks
99.5% Code Coverage
11 .io
TDD seniority and practices
Devs with two digits' years' experience
TDD applied with discipline from start
Code constantly covered by tests
Build time: 2 minutes (~ 130 msec per test)
12 .io
Test example
@Test
public void shouldGetNewDTOFromEntity() {
// Given
DTO expectedDTO = DTOFixture.getDefaultRewardWithOneVariant().build();
Reward entity = VariantRewardFixture.getDefaultRewardWithOneVariant().build();
// When
DTO variantDTO = entity.transformToDTO();
// Then
assertThat(variantDTO, is(not(nullValue())));
assertThat(variantDTO, is(reflectionEquals(expectedDTO)));
}
13 .io
Code example
public DTO transformToDTO() {
String id = getId() == null ? null : getId().toString();
DTO dto = DTO.forVariants();
dto.setId(id);
dto.setName(getName());
dto.setDescription(getDescription());
dto.setShortDescription(getShortDescription());
dto.setStatus(getStatus());
dto.setRewardItemType(getRewardItemType());
dto.setDeliveryMechanism(getDeliveryMechanism());
dto.setTermsAndConditions(getTermsAndConditions());
dto.setStockLimited(isStockLimited());
dto.setImages(transformImagesToDTOs(getImages()));
for (Variant variant : getVariants()) {
dto.addVariant(variant.transformToDTO());
}
return dto;
}
14 .io
THAT'S GOOD TDD
OR NOT?
http://icongal.com/gallery/icon/17045/256/thumbs_up_thumbs_up_vote_like
15 .io
Features velocity
For every new feature we did:
End-to-End user-journeys acceptance test
Service-to-Service integration test
Component-to-component integration tests
Unit tests (with mocks)
16 .io
… and their planning meeting
[TechLead]"How many points for this story ?"
[Devs] "2 .. 5 .. 5 .. 5"
[TechLead]"5 ? C'mon … for that small change?"
[Devs] "Change is trivial, but it will take some time to
amend all the tests and getting a green build"
17 .io
But with more quality?
 At the beginning yes 
 Project grew, tests base grew as well
 Breaking tests became the norm 
 Less frequent refactor, for not breaking tests
 Tech debt increased over time
18 .io
WHAT WENT WRONG?
https://www.flickr.com/photos/crystalflickr/145082274
19 .io
I AM NOT
TDD EVANGELIST
Evangelists are "relaying information about a particular set of
beliefs with the intention of converting the recipient"
http://en.wikipedia.org/wiki/Technology_evangelist
http://school.point2educate.com/wp-content/uploads/2014/03/Book-Red.png
20 .io
I AM
TDD PROFESSIONAL
Professionals are "members of the profession with the particular knowledge
and skills necessary to perform the role of that profession"
http://en.wikipedia.org/wiki/Professional
http://www.levantar.co.uk/images/images/Lean_Legal_Professional_Firms.jpg
21 .io
PROFESSIONAL TDD
REBOOT
http://png-2.findicons.com/files/icons/75/i_like_buttons_3a/512/perspective_button_standby.png
22 .io
Step 1 – TEST RED
Write the test, without any code written yet
RED: test fails
(compilation errors are considered failures as well)
23 .io
Step 2 – TEST GREEN
Make test work as quickly as possible
GREEN: test passes
(code satisfies the test assertions)
24 .io
Step 3 – CODE REFACTOR
Keep the test code unchanged
Rework the implementation to make it
clean, DRY, flexible
GREEN: new code passes the test
(reworked code behaves exactly as before)
25 .io
TEST
IS THE HEAD OF ALL
TDD CYCLE
http://www.improveit.mx/Imagenes/tdd_esquema_en.jpg
26 .io
TDD
ASSUMES THAT
TEST IS CORRECT
http://www.wisteriaformations.co.uk/articles/wp-content/uploads/2011/09/Company-Formation-15.jpg
27 .io
BUT WHAT IF
TEST
IS NOT 100%
CORRECT?
http://blogs.warwick.ac.uk/images/fsavva/2012/04/16/question-mark-man.jpg?maxWidth=500
28 .io
ANOTHER POSSIBLE
DIFFERENT REALITY
http://www.gamerzines.com/wp-content/uploads/2014/03/morpheus-chair.jpg
29 .io
Step 1 – TEST RED-ish
Write the [incorrect] test, no code exists yet
RED: fails, but maybe the test is wrong?
(nothing works, who can tell what is really wrong?)
30 .io
Step 2 – TEST GREEN-ish
Make test work as quickly as possible
GREEN: [incorrect] test passes
(is code correct or wrong? nobody really knows)
31 .io
Step 3 – CODE REFACTOR-ish
Keep the test code unchanged
Rework the implementation to make it
clean, DRY, flexible
GREEN: reworked code passes the tests
(was the code correct before?
Is the code still correct after?)
32 .io
?
What is TESTING?
How to TEST the length of a table?
Use your foot Or a RULER?
33 .io
How can I test the TEST?
How do you test a ruler?
?
Your thumb? Or a digital caliper?
34 .io
And how can I test the test of a TEST?
How do you test a digital caliper?
YOU DON'T
[One meter is express in terms of speed of light]
35 .io
Test and accuracy
TEST has to be
MORE ACCURATE
than CODE
36 .io
Test and confidence
TEST cannot be tested
but we have
CONFIDENCE to be
VALID
K =
299,792,458 m / s
37 .io
Can this test
@Test
public void shouldRedisplayEditFormWhenErrorAndUserKeyExists() {
boolean partnerTokenExists = true;
setupForRedisplayEditFormWhenError(partnerTokenExists);
ModelAndView mav = partnerController.update(RESOURCE_URI, mockUserPayload, mockBindingResult, mockSessionStatus);
verify(mockUserPayload, times(2)).getUserSupplyTypesCodes();
assertThat(mav.getViewName(), equalTo("administration/partners/edit"));
assertThat(mockUserPayload.getUserSupplyTypesCodes().size(), equalTo(1));
assertThat(mockUserPayload.getUserSupplyTypesCodes().iterator().next(), equalTo("Identity"));
verify(mockSessionStatus, never()).setComplete();
verify(mockCountryService, times(1)).getAllCountries();
verify(mockUserService, times(1)).getAllSupplyTypes();
}
private void setupForRedisplayEditFormWhenError(boolean partnerTokenExists) {
when(mockBindingResult.hasErrors()).thenReturn(true);
when(mockUserPayload.getTokensDefined()).thenReturn(partnerTokenExists);
when(mockUserPayload.getUserSupplyTypesCodes()).thenReturn(new HashSet<String>());
when(batchService.getAllByUser(anyString())).thenReturn(null);
UserRole partnerRole = new UserRole("PTN1");
partnerRole.setIssuingUser(true);
when(mockCurrencyManager.getUserRoles(any(String.class))).thenReturn(new UserRole());
Errors errors = new Errors();
when(mockValidationErrorsException.getViolations(any(ViolationSeverity.class))).thenReturn(errors);
doThrow(mockValidationErrorsException).when(mockUserService).updateUser(any(UserPayload.class), any(URI.class));
}
38 .io
Be more accurate than this code ?
@RequestMapping(value = "/edit", method = RequestMethod.POST)
public ModelAndView update(@RequestParam String resourceId,
@ModelAttribute(PARTNER) UserPayload partner,
BindingResult result, SessionStatus status) {
boolean isTokenExists = partner.getTokensDefined();
if (partner.getUserSupplyTypesCodes() == null) partner.setUserSupplyTypesCodes(new HashSet<String>());
if (isTokenExists) partner.getUserSupplyTypesCodes().add("Identity");
UserRole partnerRole = currencyManager.getUserRoles(partner.getCode());
if (partnerRole.isIssuingUser()) partner.getUserSupplyTypesCodes().add("Issuance");
if (partnerRole.isLiabilityUser()) partner.getUserSupplyTypesCodes().add("Liability");
try {
partnerService.updateUser(partner, URI.create(resourceId));
status.setComplete();
return new ModelAndView("redirect:/partners");
} catch (ValidationErrorsException e) {
SpringErrorBindingHelper.populateErrors(result, e.getViolations(ViolationSeverity.ERROR));
ModelAndView mav = new ModelAndView("administration/partners/edit");
partnerRole = currencyManager.getUserRoles(partner.getCode());
mav.addObject(PARTNER_ROLE, partnerRole);
mav.addObject(RESOURCE_ID, resourceId);
populateReferenceData(mav);
return mav;
}
}
39 .io
And this test?
"Sending two JSON records to the messages REST API" should {
"returns HTTP Status 200 and store two records to the messages repository" in {
// Given
val jsonRows = Json.parse(
"""[
|{ "id": "1234567890", "form": "SA300", "dispatchOn": "2013-11-22", "detailsId": "W0123456781234569"},
|{ "id": "1234567891", "form": "SA316A", "dispatchOn": "2013-11-23", "detailsId": "C0123456781234568"}
|]""".stripMargin)
// When
verifyStatusCode(doPut(resource(s"/messages"), jsonRows), 200)
// Then
val messages = await(messageRepository.findAll)
messages should have size 2
exactly(1, messages) should have (
'recipient("1234567890"),
'body("SA300", DetailsId("W0123456781234569")),
'dispatchOn(new LocalDate(2013, 11, 22))
)
exactly(1, messages) should have (
'recipient("1234567891"),
'body("SA316A", DetailsId("C0123456781234568")),
'validFrom(new LocalDate(2013, 11, 23))
)
}
}
40 .io
Compared to this code ?
def putMessages = Action.async(action.parser) {
implicit request =>
withJsonBody[List[PrintSuppressionNotification]] {
messages =>
if (messages == null || messages.isEmpty)
throw new BadRequestException("No messages supplied")
if (messages.size > maxMessages)
throw new RequestEntityTooLargeException(
s"${messages.size} items submitted, max $maxMessages allowed")
val results = mongo.insertAllUnique(messages.map(_.toMongo))
Future.sequence(results).map(_ => Results.Ok)
}
}
41 .io
Other projects' testimonials
"Today however, my team told me the tests are more complex
than the actual code. (This team is not the original team that wrote the code and unit tests. Therefore
some unit tests take them by surprise. This current team is more senior and disciplined.) In my opinion,
now that’s waste..."
Richard Jacobs at Sogeti (Sogeti Nederland B.V.)
http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf
42 .io
Accurate = Small
More code
=
more mistakes
Ideal size of a test? ~ 3 lines
Assumption, Action, Assertion
"Less is more"
[Ludwig Mies van der Rohe]
43 .io
Accurate = Readable
We can trust what we understand
Make your test easy to read
Anyone would understand and validate it
44 .io
Accurate = Explicit and repeatable
What You See is What Test Does
Again and again the same
No side-effects
No hidden logic in helper
No loops
No random values
45 .io
Accurate = Traceable to a requirement
When test fails,
what stops working?
Use business domain names
use business stories names
for objects, actions and results
46 .io
Accurate = Correct when fails
If I comment out a line of code,
does the test FAIL for the CORRECT reason?
Does the test returns an error (exception)
instead of a failure?
47 .io
WHOOPS!
MY TESTS ARE
INACCURATE,
WHAT SHOULD I DO?
48 .io
49 .io
INACCURATE TEST
IS WORSE THAN
NO TEST
50 .io
Are you telling me I should have less tests ?
Q [John Nolan]:
"The thing I've found about TDD is that its takes time to get
your tests set up and being naturally lazy I always want to write as little code as possible. The first thing I
seem do is test my constructor has set all the properties but is this overkill?
My question is to what level of granularity do you write you unit tests at?
..and is there a case of testing too much?"
A [Kent Beck]:
"I get paid for code that works, not for tests, so my philosophy is to test as
little as possible to reach a given level of confidence"
http://stackoverflow.com/questions/153234/how-deep-are-your-unit-tests/153565#153565
51 .io
REBUILDING
PROFESSIONAL TDD
https://www.flickr.com/photos/jdn/4817970175
52 .io
Experience over Rules
Writing CODE is MORE
than applying RULES
Reading CODE is MORE
than reading BOOKS
Common sense, Trial and Error
53 .io
The Sense of Time
Test too complex to write ?
Kill the test (if the code is clean)
Test takes too long to understand?
Kill the test (if the code is readable)
Time (with TDD) < Time (without TDD)
or you are doing something wrong!
54 .io
Cost / value trade-off
Writing tests costs money
Test marginal value > Test cost?
Is this code critical? Can it possibly fail?
Am I double-testing something covered?
Cost (with TDD) < Cost (without TDD)
or you are doing something wrong!
55 .io
How big is my code-base with TDD?
How many test / code lines I am writing?
Confidence on uncovered code?
Size (Test) < Size (Code)
Do not test code that cannot break
Test / code ratio
56 .io
Test Focus
Tests express WHAT to achieve
from user's perspective
Test WHAT can be measured
What can I measure on this?
public interface UserRepository {
void addUser(String username,
String first, String last);
}
57 .io
Code confidence
Code (not Test)
tells HOW system works
Code (with Test)
gives confidence of correctness
We are confident on what is
clear + readable + repeatable
58 .io
Writing code - Martin Fowler
"Any fool can write code that a computer can understand.
Good programmers write code that humans can understand.”
[Martin Fowler - 1999 - Refactoring: Improving the Design of Existing Code]
59 .io
Best writers in history – Ernest Hemingway
"In 1954, when Hemingway was awarded the Nobel Prize for
Literature, it was for his mastery of the art of narrative […] He
avoided complicated syntax. About 70 percent of the sentences are
simple sentences—a childlike syntax without subordination."
http://en.wikipedia.org/wiki/Ernest_Hemingway
60 .io
Reading = learning to Write
Code Review
Read A LOT of code
Read good code, read bad code
Comment, exchange ideas
Challenge solutions
https://www.flickr.com/photos/jdn/4817970175
61 .io
Write, experiment, throw waste
Write code, ask for feedback
Read your own code …
after days, weeks, months
Measure progress
Throw waste
Keep test and code clean, ALWAYS
62 .io
Professional TDD Summary
1. TDD practices are not enough
2. Experience over Rules
3. Trade-off test time/cost and code benefit
4. Tests is WHAT to achieve
5. Code is confidence on DESIGN
6. Read code to become a better writer
7. Plan to throw test waste away
63 .io
64 .io
TDD resources for reading and learning
 Is TDD dead hangouts series
http://martinfowler.com/articles/is-tdd-dead/
 Unit-testing and waste management
http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf
 Mockist vs. non-mockist TDD
http://martinfowler.com/articles/mocksArentStubs.html
65 .io
Code-review resources
 Guido Van Rossum about Code Review @Google
http://www.youtube.com/watch?v=CKjRt48rZGk
 Code Review @SAP
http://www.eclipsecon.org/2013/sites/eclipsecon.org.2013/files/CodeReview.pptx
 V. Subramaniam – About Code Review and Quality
http://www.agiledeveloper.com/presentations/caring_about_code_quality.pdf
Replay these slides: http://slideshare.net/lucamilanesio
Try Gerrit on-line: http://gerrithub.io/login
Learn Gerrit: http://gerrithub.io/book
Follow my Blog: http://gitenterprise.me
Learn more about code review
20% OFF Book discount for
33 Degree.org User Conference
Book CODE: dg7jnZ
eBook CODE: Wi86Zh

More Related Content

PPTX
Devoxx 2016 Using Jenkins, Gerrit and Spark for Continuous Delivery Analytics
PPTX
Speed up Continuous Delivery with BigData Analytics
PPTX
Zero-Downtime Gerrit Code Review Upgrade
PPTX
Gerrit jenkins-big data-continuous-delivery
PPTX
GerritHub.io - present, past, future
PPTX
Gerrit Code Review Analytics
PDF
GitLab webcast - Release 8.4
PPTX
GitLab 8.5 Highlights and Step-by-step tutorial
Devoxx 2016 Using Jenkins, Gerrit and Spark for Continuous Delivery Analytics
Speed up Continuous Delivery with BigData Analytics
Zero-Downtime Gerrit Code Review Upgrade
Gerrit jenkins-big data-continuous-delivery
GerritHub.io - present, past, future
Gerrit Code Review Analytics
GitLab webcast - Release 8.4
GitLab 8.5 Highlights and Step-by-step tutorial

What's hot (20)

PPTX
GitLab 8.6 - Release Webcast
PPT
Flex and .NET Integration
ODP
Dev01 - Don't Reinvent the Wheel
PPTX
It's all about feedback - code review as a great tool in the agile toolbox
PDF
Occ iware docker-connector-demo-june-2015
PDF
Building GitLab
PDF
Github, Travis-CI and Perl
PDF
Build your own PaaS using Kubernetes and Deis — GDG DevFest NL
PDF
Using the GitHub App to Connect to Bitbucket
PPTX
Egit democamp-karlsruhe-2011-11-29
PDF
Git Branching for Agile Teams
PPTX
DevOps and Continuous Delivery Reference Architectures (including Nexus and o...
PDF
Automating Code Reviews for Salesforce Apps
PPTX
Egit democamp-darmstadt-2011-06-21
PPTX
Practical DevOps & Continuous Delivery – A Webinar to learn in depth on DevO...
PPTX
Ti weekopenshift
PPTX
Github copilot
PDF
Git Branching for Agile Teams
PDF
Principles of Iteration
PDF
Git with t for teams
GitLab 8.6 - Release Webcast
Flex and .NET Integration
Dev01 - Don't Reinvent the Wheel
It's all about feedback - code review as a great tool in the agile toolbox
Occ iware docker-connector-demo-june-2015
Building GitLab
Github, Travis-CI and Perl
Build your own PaaS using Kubernetes and Deis — GDG DevFest NL
Using the GitHub App to Connect to Bitbucket
Egit democamp-karlsruhe-2011-11-29
Git Branching for Agile Teams
DevOps and Continuous Delivery Reference Architectures (including Nexus and o...
Automating Code Reviews for Salesforce Apps
Egit democamp-darmstadt-2011-06-21
Practical DevOps & Continuous Delivery – A Webinar to learn in depth on DevO...
Ti weekopenshift
Github copilot
Git Branching for Agile Teams
Principles of Iteration
Git with t for teams
Ad

Viewers also liked (10)

PPTX
Mobile Application Lifecycle with Jekins, Trello and CollabNet TeamForge
PPTX
Gerrit Code Review: how to script a plugin with Scala and Groovy
PPTX
Git workshop 33degree 2011 krakow
PPTX
GitBlit plugin for Gerrit Code Review
PPTX
Visitor counter
PPTX
Gerrit is Getting Native with RPM, Deb and Docker
PPTX
Bidirect visitor counter
PPTX
Jenkins User Conference - Continuous Delivery on Mobile
PPTX
Gerrit Code Review with GitHub plugin
PDF
Project report on bidirectional visitor counter & home automation
Mobile Application Lifecycle with Jekins, Trello and CollabNet TeamForge
Gerrit Code Review: how to script a plugin with Scala and Groovy
Git workshop 33degree 2011 krakow
GitBlit plugin for Gerrit Code Review
Visitor counter
Gerrit is Getting Native with RPM, Deb and Docker
Bidirect visitor counter
Jenkins User Conference - Continuous Delivery on Mobile
Gerrit Code Review with GitHub plugin
Project report on bidirectional visitor counter & home automation
Ad

Similar to Is TDD dead or alive? (20)

PDF
What CS Class Didn't Teach About Testing
PPTX
{10.0} Test Driven Development.pptx
PDF
Test Driven Development (TDD)
PPTX
Test-Driven Development.pptx
PDF
Campbell & Readman - TDD It's Not Tester Driven Development - EuroSTAR 2012
PDF
So long, and thanks for all the tests (Scottish Developers 2014)
PDF
TDD CrashCourse Part2: TDD
PPTX
How John started to like TDD (instead of hating it) - Talent Arena (March '25)
PDF
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
PPTX
Software presentation
PPTX
TDD Training
PPTX
TeDevelopment Testing in Software Engineering
PPTX
TDD - Agile
PDF
CNUG TDD June 2014
PPTX
Test-Driven Development
PPTX
Understanding TDD - theory, practice, techniques and tips.
PPTX
Test Driven Development - a Practitioner’s Perspective
PDF
Test-Driven Development
PPT
TDD - Christchurch APN May 2012
What CS Class Didn't Teach About Testing
{10.0} Test Driven Development.pptx
Test Driven Development (TDD)
Test-Driven Development.pptx
Campbell & Readman - TDD It's Not Tester Driven Development - EuroSTAR 2012
So long, and thanks for all the tests (Scottish Developers 2014)
TDD CrashCourse Part2: TDD
How John started to like TDD (instead of hating it) - Talent Arena (March '25)
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Software presentation
TDD Training
TeDevelopment Testing in Software Engineering
TDD - Agile
CNUG TDD June 2014
Test-Driven Development
Understanding TDD - theory, practice, techniques and tips.
Test Driven Development - a Practitioner’s Perspective
Test-Driven Development
TDD - Christchurch APN May 2012

More from Luca Milanesio (18)

PDF
What's new in Gerrit Code Review v3.1 and beyond
PDF
Gerrit Analytics applied to Android source code
PDF
Cloud-native Gerrit Code Review
PPTX
Gerrit Code Review migrations step-by-step
PDF
Gerrit Code Review v3.2 and v3.3
PDF
ChronicleMap non-blocking cache for Gerrit v3.3
PDF
Gerrit Code Review multi-site
PDF
What's new in Gerrit Code Review 3.0
PDF
Gerrit User Summit 2019 Keynote
PDF
Gerrit multi-master / multi-site at GerritHub
PDF
GerritHub a true Gerrit migration story to v2.15
PDF
Gerrit User Summit 2018 - Keynote
PPTX
Jenkins plugin for Gerrit Code Review pipelines
PPTX
Gerrit User Summit 2017 Keynote
PPTX
How to keep Jenkins logs forever without performance issues
PPTX
Jenkins Pipeline on your Local Box to Reduce Cycle Time
PPTX
Jenkins world 2017 - Data-Driven CI Pipeline with Gerrit Code Review
PPTX
Stable master workflow with Gerrit Code Review
What's new in Gerrit Code Review v3.1 and beyond
Gerrit Analytics applied to Android source code
Cloud-native Gerrit Code Review
Gerrit Code Review migrations step-by-step
Gerrit Code Review v3.2 and v3.3
ChronicleMap non-blocking cache for Gerrit v3.3
Gerrit Code Review multi-site
What's new in Gerrit Code Review 3.0
Gerrit User Summit 2019 Keynote
Gerrit multi-master / multi-site at GerritHub
GerritHub a true Gerrit migration story to v2.15
Gerrit User Summit 2018 - Keynote
Jenkins plugin for Gerrit Code Review pipelines
Gerrit User Summit 2017 Keynote
How to keep Jenkins logs forever without performance issues
Jenkins Pipeline on your Local Box to Reduce Cycle Time
Jenkins world 2017 - Data-Driven CI Pipeline with Gerrit Code Review
Stable master workflow with Gerrit Code Review

Recently uploaded (20)

PDF
Classroom Observation Tools for Teachers
PDF
Supply Chain Operations Speaking Notes -ICLT Program
PPTX
PPT- ENG7_QUARTER1_LESSON1_WEEK1. IMAGERY -DESCRIPTIONS pptx.pptx
PDF
01-Introduction-to-Information-Management.pdf
PDF
102 student loan defaulters named and shamed – Is someone you know on the list?
PPTX
human mycosis Human fungal infections are called human mycosis..pptx
PDF
Origin of periodic table-Mendeleev’s Periodic-Modern Periodic table
PDF
O5-L3 Freight Transport Ops (International) V1.pdf
PPTX
Final Presentation General Medicine 03-08-2024.pptx
PPTX
Introduction_to_Human_Anatomy_and_Physiology_for_B.Pharm.pptx
PDF
Saundersa Comprehensive Review for the NCLEX-RN Examination.pdf
PPTX
BOWEL ELIMINATION FACTORS AFFECTING AND TYPES
PDF
Chapter 2 Heredity, Prenatal Development, and Birth.pdf
PPTX
PPH.pptx obstetrics and gynecology in nursing
PPTX
Cell Structure & Organelles in detailed.
PDF
Abdominal Access Techniques with Prof. Dr. R K Mishra
PPTX
Microbial diseases, their pathogenesis and prophylaxis
PDF
O7-L3 Supply Chain Operations - ICLT Program
PDF
Basic Mud Logging Guide for educational purpose
PDF
3rd Neelam Sanjeevareddy Memorial Lecture.pdf
Classroom Observation Tools for Teachers
Supply Chain Operations Speaking Notes -ICLT Program
PPT- ENG7_QUARTER1_LESSON1_WEEK1. IMAGERY -DESCRIPTIONS pptx.pptx
01-Introduction-to-Information-Management.pdf
102 student loan defaulters named and shamed – Is someone you know on the list?
human mycosis Human fungal infections are called human mycosis..pptx
Origin of periodic table-Mendeleev’s Periodic-Modern Periodic table
O5-L3 Freight Transport Ops (International) V1.pdf
Final Presentation General Medicine 03-08-2024.pptx
Introduction_to_Human_Anatomy_and_Physiology_for_B.Pharm.pptx
Saundersa Comprehensive Review for the NCLEX-RN Examination.pdf
BOWEL ELIMINATION FACTORS AFFECTING AND TYPES
Chapter 2 Heredity, Prenatal Development, and Birth.pdf
PPH.pptx obstetrics and gynecology in nursing
Cell Structure & Organelles in detailed.
Abdominal Access Techniques with Prof. Dr. R K Mishra
Microbial diseases, their pathogenesis and prophylaxis
O7-L3 Supply Chain Operations - ICLT Program
Basic Mud Logging Guide for educational purpose
3rd Neelam Sanjeevareddy Memorial Lecture.pdf

Is TDD dead or alive?

  • 1. Luca@gerritforge.com http://www.gerritforge.com Twitter: @gitenterprise TDD Dead or Alive? Luca Milanesio GerritForge http://visionwidget.com/images/2010-4/0405/Wanted_Poster.jpg Platinum Sponsor
  • 2. 2 .io About me • Luca Milanesio Co-founder of GerritForge • over 20 years of experience in Agile Development SCM and ALM worldwide • Contributor to Jenkins since 2007 (and previously Hudson) • Git SCM mentor for the Enterprise since 2009 • Contributor to Gerrit Code Review community since 2011
  • 3. 3 .io Agenda  Why?  TDD-induced damage  Evangelist vs. Professional  Reboot  Professional TDD  Learning to write
  • 4. 4 .io TDD is 20 years old http://www.macqueen.us/smalltalkReport/ST/91_95/SMAL0402.PDF
  • 5. 5 .io TDD has been widely adopted http://www.indeed.com/jobtrends?q=test+driven+development&relative=1
  • 6. 6 .io Hold on … what's that ? http://www.indeed.com/jobtrends?q=test+driven+development&relative=1
  • 7. 7 .io … and that ? http://martinfowler.com/articles/is-tdd-dead/
  • 8. 8 .io Test-induced design damage By David Heinemeier Hansson on April 29, 2014 http://david.heinemeierhansson.com/2014/test-induced-design-damage.html "Code that's hard to test in isolation is poorly designed", goes a common TDD maxim. Isolation meaning free of dependent context and separated from collaborators, especially "slow" ones like database or file IO. The prevalent definition of "unit" in unit testing (though not everyone agrees with this). This is some times true. Some times finding it difficult to test points to a design smell. It may be tangled responsibilities or whatever. But that's a far ways off from declaring that hard-to-unit-test code is always poorly designed, and always in need of repair. That you cannot have well-designed code that is hard to unit test. It's from this unfortunate maxim that much of the test-induced design damage flows. Such damage is defined as changes to your code that either facilitates a) easier test-first, b) speedy tests, or c) unit tests, but does so by harming the clarity of the code through — usually through needless indirection and conceptual overhead. Code that is warped out of shape solely to accommodate testing objectives.
  • 9. 9 .io TDD EXAMPLE DAMAGE ON A LARGE PROJECT https://www.flickr.com/photos/martinluff/5475631631
  • 10. 10 .io Code metrics of one service 340 Java Classes 880 Tests 158 Mocks 99.5% Code Coverage
  • 11. 11 .io TDD seniority and practices Devs with two digits' years' experience TDD applied with discipline from start Code constantly covered by tests Build time: 2 minutes (~ 130 msec per test)
  • 12. 12 .io Test example @Test public void shouldGetNewDTOFromEntity() { // Given DTO expectedDTO = DTOFixture.getDefaultRewardWithOneVariant().build(); Reward entity = VariantRewardFixture.getDefaultRewardWithOneVariant().build(); // When DTO variantDTO = entity.transformToDTO(); // Then assertThat(variantDTO, is(not(nullValue()))); assertThat(variantDTO, is(reflectionEquals(expectedDTO))); }
  • 13. 13 .io Code example public DTO transformToDTO() { String id = getId() == null ? null : getId().toString(); DTO dto = DTO.forVariants(); dto.setId(id); dto.setName(getName()); dto.setDescription(getDescription()); dto.setShortDescription(getShortDescription()); dto.setStatus(getStatus()); dto.setRewardItemType(getRewardItemType()); dto.setDeliveryMechanism(getDeliveryMechanism()); dto.setTermsAndConditions(getTermsAndConditions()); dto.setStockLimited(isStockLimited()); dto.setImages(transformImagesToDTOs(getImages())); for (Variant variant : getVariants()) { dto.addVariant(variant.transformToDTO()); } return dto; }
  • 14. 14 .io THAT'S GOOD TDD OR NOT? http://icongal.com/gallery/icon/17045/256/thumbs_up_thumbs_up_vote_like
  • 15. 15 .io Features velocity For every new feature we did: End-to-End user-journeys acceptance test Service-to-Service integration test Component-to-component integration tests Unit tests (with mocks)
  • 16. 16 .io … and their planning meeting [TechLead]"How many points for this story ?" [Devs] "2 .. 5 .. 5 .. 5" [TechLead]"5 ? C'mon … for that small change?" [Devs] "Change is trivial, but it will take some time to amend all the tests and getting a green build"
  • 17. 17 .io But with more quality?  At the beginning yes   Project grew, tests base grew as well  Breaking tests became the norm   Less frequent refactor, for not breaking tests  Tech debt increased over time
  • 18. 18 .io WHAT WENT WRONG? https://www.flickr.com/photos/crystalflickr/145082274
  • 19. 19 .io I AM NOT TDD EVANGELIST Evangelists are "relaying information about a particular set of beliefs with the intention of converting the recipient" http://en.wikipedia.org/wiki/Technology_evangelist http://school.point2educate.com/wp-content/uploads/2014/03/Book-Red.png
  • 20. 20 .io I AM TDD PROFESSIONAL Professionals are "members of the profession with the particular knowledge and skills necessary to perform the role of that profession" http://en.wikipedia.org/wiki/Professional http://www.levantar.co.uk/images/images/Lean_Legal_Professional_Firms.jpg
  • 22. 22 .io Step 1 – TEST RED Write the test, without any code written yet RED: test fails (compilation errors are considered failures as well)
  • 23. 23 .io Step 2 – TEST GREEN Make test work as quickly as possible GREEN: test passes (code satisfies the test assertions)
  • 24. 24 .io Step 3 – CODE REFACTOR Keep the test code unchanged Rework the implementation to make it clean, DRY, flexible GREEN: new code passes the test (reworked code behaves exactly as before)
  • 25. 25 .io TEST IS THE HEAD OF ALL TDD CYCLE http://www.improveit.mx/Imagenes/tdd_esquema_en.jpg
  • 26. 26 .io TDD ASSUMES THAT TEST IS CORRECT http://www.wisteriaformations.co.uk/articles/wp-content/uploads/2011/09/Company-Formation-15.jpg
  • 27. 27 .io BUT WHAT IF TEST IS NOT 100% CORRECT? http://blogs.warwick.ac.uk/images/fsavva/2012/04/16/question-mark-man.jpg?maxWidth=500
  • 28. 28 .io ANOTHER POSSIBLE DIFFERENT REALITY http://www.gamerzines.com/wp-content/uploads/2014/03/morpheus-chair.jpg
  • 29. 29 .io Step 1 – TEST RED-ish Write the [incorrect] test, no code exists yet RED: fails, but maybe the test is wrong? (nothing works, who can tell what is really wrong?)
  • 30. 30 .io Step 2 – TEST GREEN-ish Make test work as quickly as possible GREEN: [incorrect] test passes (is code correct or wrong? nobody really knows)
  • 31. 31 .io Step 3 – CODE REFACTOR-ish Keep the test code unchanged Rework the implementation to make it clean, DRY, flexible GREEN: reworked code passes the tests (was the code correct before? Is the code still correct after?)
  • 32. 32 .io ? What is TESTING? How to TEST the length of a table? Use your foot Or a RULER?
  • 33. 33 .io How can I test the TEST? How do you test a ruler? ? Your thumb? Or a digital caliper?
  • 34. 34 .io And how can I test the test of a TEST? How do you test a digital caliper? YOU DON'T [One meter is express in terms of speed of light]
  • 35. 35 .io Test and accuracy TEST has to be MORE ACCURATE than CODE
  • 36. 36 .io Test and confidence TEST cannot be tested but we have CONFIDENCE to be VALID K = 299,792,458 m / s
  • 37. 37 .io Can this test @Test public void shouldRedisplayEditFormWhenErrorAndUserKeyExists() { boolean partnerTokenExists = true; setupForRedisplayEditFormWhenError(partnerTokenExists); ModelAndView mav = partnerController.update(RESOURCE_URI, mockUserPayload, mockBindingResult, mockSessionStatus); verify(mockUserPayload, times(2)).getUserSupplyTypesCodes(); assertThat(mav.getViewName(), equalTo("administration/partners/edit")); assertThat(mockUserPayload.getUserSupplyTypesCodes().size(), equalTo(1)); assertThat(mockUserPayload.getUserSupplyTypesCodes().iterator().next(), equalTo("Identity")); verify(mockSessionStatus, never()).setComplete(); verify(mockCountryService, times(1)).getAllCountries(); verify(mockUserService, times(1)).getAllSupplyTypes(); } private void setupForRedisplayEditFormWhenError(boolean partnerTokenExists) { when(mockBindingResult.hasErrors()).thenReturn(true); when(mockUserPayload.getTokensDefined()).thenReturn(partnerTokenExists); when(mockUserPayload.getUserSupplyTypesCodes()).thenReturn(new HashSet<String>()); when(batchService.getAllByUser(anyString())).thenReturn(null); UserRole partnerRole = new UserRole("PTN1"); partnerRole.setIssuingUser(true); when(mockCurrencyManager.getUserRoles(any(String.class))).thenReturn(new UserRole()); Errors errors = new Errors(); when(mockValidationErrorsException.getViolations(any(ViolationSeverity.class))).thenReturn(errors); doThrow(mockValidationErrorsException).when(mockUserService).updateUser(any(UserPayload.class), any(URI.class)); }
  • 38. 38 .io Be more accurate than this code ? @RequestMapping(value = "/edit", method = RequestMethod.POST) public ModelAndView update(@RequestParam String resourceId, @ModelAttribute(PARTNER) UserPayload partner, BindingResult result, SessionStatus status) { boolean isTokenExists = partner.getTokensDefined(); if (partner.getUserSupplyTypesCodes() == null) partner.setUserSupplyTypesCodes(new HashSet<String>()); if (isTokenExists) partner.getUserSupplyTypesCodes().add("Identity"); UserRole partnerRole = currencyManager.getUserRoles(partner.getCode()); if (partnerRole.isIssuingUser()) partner.getUserSupplyTypesCodes().add("Issuance"); if (partnerRole.isLiabilityUser()) partner.getUserSupplyTypesCodes().add("Liability"); try { partnerService.updateUser(partner, URI.create(resourceId)); status.setComplete(); return new ModelAndView("redirect:/partners"); } catch (ValidationErrorsException e) { SpringErrorBindingHelper.populateErrors(result, e.getViolations(ViolationSeverity.ERROR)); ModelAndView mav = new ModelAndView("administration/partners/edit"); partnerRole = currencyManager.getUserRoles(partner.getCode()); mav.addObject(PARTNER_ROLE, partnerRole); mav.addObject(RESOURCE_ID, resourceId); populateReferenceData(mav); return mav; } }
  • 39. 39 .io And this test? "Sending two JSON records to the messages REST API" should { "returns HTTP Status 200 and store two records to the messages repository" in { // Given val jsonRows = Json.parse( """[ |{ "id": "1234567890", "form": "SA300", "dispatchOn": "2013-11-22", "detailsId": "W0123456781234569"}, |{ "id": "1234567891", "form": "SA316A", "dispatchOn": "2013-11-23", "detailsId": "C0123456781234568"} |]""".stripMargin) // When verifyStatusCode(doPut(resource(s"/messages"), jsonRows), 200) // Then val messages = await(messageRepository.findAll) messages should have size 2 exactly(1, messages) should have ( 'recipient("1234567890"), 'body("SA300", DetailsId("W0123456781234569")), 'dispatchOn(new LocalDate(2013, 11, 22)) ) exactly(1, messages) should have ( 'recipient("1234567891"), 'body("SA316A", DetailsId("C0123456781234568")), 'validFrom(new LocalDate(2013, 11, 23)) ) } }
  • 40. 40 .io Compared to this code ? def putMessages = Action.async(action.parser) { implicit request => withJsonBody[List[PrintSuppressionNotification]] { messages => if (messages == null || messages.isEmpty) throw new BadRequestException("No messages supplied") if (messages.size > maxMessages) throw new RequestEntityTooLargeException( s"${messages.size} items submitted, max $maxMessages allowed") val results = mongo.insertAllUnique(messages.map(_.toMongo)) Future.sequence(results).map(_ => Results.Ok) } }
  • 41. 41 .io Other projects' testimonials "Today however, my team told me the tests are more complex than the actual code. (This team is not the original team that wrote the code and unit tests. Therefore some unit tests take them by surprise. This current team is more senior and disciplined.) In my opinion, now that’s waste..." Richard Jacobs at Sogeti (Sogeti Nederland B.V.) http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf
  • 42. 42 .io Accurate = Small More code = more mistakes Ideal size of a test? ~ 3 lines Assumption, Action, Assertion "Less is more" [Ludwig Mies van der Rohe]
  • 43. 43 .io Accurate = Readable We can trust what we understand Make your test easy to read Anyone would understand and validate it
  • 44. 44 .io Accurate = Explicit and repeatable What You See is What Test Does Again and again the same No side-effects No hidden logic in helper No loops No random values
  • 45. 45 .io Accurate = Traceable to a requirement When test fails, what stops working? Use business domain names use business stories names for objects, actions and results
  • 46. 46 .io Accurate = Correct when fails If I comment out a line of code, does the test FAIL for the CORRECT reason? Does the test returns an error (exception) instead of a failure?
  • 47. 47 .io WHOOPS! MY TESTS ARE INACCURATE, WHAT SHOULD I DO?
  • 49. 49 .io INACCURATE TEST IS WORSE THAN NO TEST
  • 50. 50 .io Are you telling me I should have less tests ? Q [John Nolan]: "The thing I've found about TDD is that its takes time to get your tests set up and being naturally lazy I always want to write as little code as possible. The first thing I seem do is test my constructor has set all the properties but is this overkill? My question is to what level of granularity do you write you unit tests at? ..and is there a case of testing too much?" A [Kent Beck]: "I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence" http://stackoverflow.com/questions/153234/how-deep-are-your-unit-tests/153565#153565
  • 52. 52 .io Experience over Rules Writing CODE is MORE than applying RULES Reading CODE is MORE than reading BOOKS Common sense, Trial and Error
  • 53. 53 .io The Sense of Time Test too complex to write ? Kill the test (if the code is clean) Test takes too long to understand? Kill the test (if the code is readable) Time (with TDD) < Time (without TDD) or you are doing something wrong!
  • 54. 54 .io Cost / value trade-off Writing tests costs money Test marginal value > Test cost? Is this code critical? Can it possibly fail? Am I double-testing something covered? Cost (with TDD) < Cost (without TDD) or you are doing something wrong!
  • 55. 55 .io How big is my code-base with TDD? How many test / code lines I am writing? Confidence on uncovered code? Size (Test) < Size (Code) Do not test code that cannot break Test / code ratio
  • 56. 56 .io Test Focus Tests express WHAT to achieve from user's perspective Test WHAT can be measured What can I measure on this? public interface UserRepository { void addUser(String username, String first, String last); }
  • 57. 57 .io Code confidence Code (not Test) tells HOW system works Code (with Test) gives confidence of correctness We are confident on what is clear + readable + repeatable
  • 58. 58 .io Writing code - Martin Fowler "Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” [Martin Fowler - 1999 - Refactoring: Improving the Design of Existing Code]
  • 59. 59 .io Best writers in history – Ernest Hemingway "In 1954, when Hemingway was awarded the Nobel Prize for Literature, it was for his mastery of the art of narrative […] He avoided complicated syntax. About 70 percent of the sentences are simple sentences—a childlike syntax without subordination." http://en.wikipedia.org/wiki/Ernest_Hemingway
  • 60. 60 .io Reading = learning to Write Code Review Read A LOT of code Read good code, read bad code Comment, exchange ideas Challenge solutions https://www.flickr.com/photos/jdn/4817970175
  • 61. 61 .io Write, experiment, throw waste Write code, ask for feedback Read your own code … after days, weeks, months Measure progress Throw waste Keep test and code clean, ALWAYS
  • 62. 62 .io Professional TDD Summary 1. TDD practices are not enough 2. Experience over Rules 3. Trade-off test time/cost and code benefit 4. Tests is WHAT to achieve 5. Code is confidence on DESIGN 6. Read code to become a better writer 7. Plan to throw test waste away
  • 64. 64 .io TDD resources for reading and learning  Is TDD dead hangouts series http://martinfowler.com/articles/is-tdd-dead/  Unit-testing and waste management http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf  Mockist vs. non-mockist TDD http://martinfowler.com/articles/mocksArentStubs.html
  • 65. 65 .io Code-review resources  Guido Van Rossum about Code Review @Google http://www.youtube.com/watch?v=CKjRt48rZGk  Code Review @SAP http://www.eclipsecon.org/2013/sites/eclipsecon.org.2013/files/CodeReview.pptx  V. Subramaniam – About Code Review and Quality http://www.agiledeveloper.com/presentations/caring_about_code_quality.pdf
  • 66. Replay these slides: http://slideshare.net/lucamilanesio Try Gerrit on-line: http://gerrithub.io/login Learn Gerrit: http://gerrithub.io/book Follow my Blog: http://gitenterprise.me Learn more about code review 20% OFF Book discount for 33 Degree.org User Conference Book CODE: dg7jnZ eBook CODE: Wi86Zh