is tdd dead or alive?

66
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 Platinum Sponsor

Upload: luca-milanesio

Post on 10-May-2015

1.023 views

Category:

Education


3 download

DESCRIPTION

Everyone knows about TDD nowadays, but do you feel you are spending more time testing than writing code ? Where is the point where tests become an impediment to the evolution of your project ? Instead of taking a religious approach to TDD (""you MUST ..."", ""good developers DO ...."", ""have you read the book XYZ on ..."") this is more a professional perspective, looking at how provide value using TDD as a powerful tool to focus on value and reducing waste. Mockist TDD has lead software to a even higher level of complexity, up to the point where looking at the tests lead to a much higher confusion rather than just reading the code. We will go through the TDD-related problem and real-life experiences in a very interactive talk, with a common goal to see what we can do now to make our tests more a tool for a better code rather than a karma for our development working life.

TRANSCRIPT

Page 1: Is TDD dead or alive?

[email protected]://www.gerritforge.comTwitter: @gitenterprise

TDDDead or Alive?

Luca Milanesio

GerritForge

http://visionwidget.com/images/2010-4/0405/Wanted_Poster.jpgPlatinum Sponsor

Page 2: Is TDD dead or alive?

2 .io

About me

Luca MilanesioCo-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

Page 3: Is TDD dead or alive?

3 .io

Agenda Why? TDD-induced damage Evangelist vs. Professional Reboot Professional TDD Learning to write

Page 4: Is TDD dead or alive?

4 .io

TDD is 20 years old

http://www.macqueen.us/smalltalkReport/ST/91_95/SMAL0402.PDF

Page 5: Is TDD dead or alive?

5 .io

TDD has been widely adopted

http://www.indeed.com/jobtrends?q=test+driven+development&relative=1

Page 6: Is TDD dead or alive?

6 .io

Hold on … what's that ?

http://www.indeed.com/jobtrends?q=test+driven+development&relative=1

?

Page 7: Is TDD dead or alive?

7 .io

… and that ?

http://martinfowler.com/articles/is-tdd-dead/

Page 8: Is TDD dead or alive?

8 .io

Test-induced design damageBy 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.

Page 9: Is TDD dead or alive?

9 .io

TDD EXAMPLE DAMAGE ON A

LARGE PROJECT

https://www.flickr.com/photos/martinluff/5475631631

Page 10: Is TDD dead or alive?

10 .io

Code metrics of one service

340 Java Classes880 Tests158 Mocks

99.5% Code Coverage

Page 11: Is TDD dead or alive?

11 .io

TDD seniority and practices

Devs with two digits' years' experienceTDD applied with discipline from start

Code constantly covered by testsBuild time: 2 minutes (~ 130 msec per

test)

Page 12: Is TDD dead or alive?

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))); }

Page 13: Is TDD dead or alive?

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; }

Page 14: Is TDD dead or alive?

14 .io

THAT'S GOOD TDDOR NOT?

http://icongal.com/gallery/icon/17045/256/thumbs_up_thumbs_up_vote_like

Page 15: Is TDD dead or alive?

15 .io

Features velocity

For every new feature we did:End-to-End user-journeys acceptance testService-to-Service integration testComponent-to-component integration testsUnit tests (with mocks)

Page 16: Is TDD dead or alive?

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"

Page 17: Is TDD dead or alive?

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

Page 18: Is TDD dead or alive?

18 .io

WHAT WENT WRONG?

https://www.flickr.com/photos/crystalflickr/145082274

Page 19: Is TDD dead or alive?

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

Page 20: Is TDD dead or alive?

20 .io

I AMTDD

PROFESSIONALProfessionals 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

Page 21: Is TDD dead or alive?

21 .io

PROFESSIONAL TDD

REBOOT

http://png-2.findicons.com/files/icons/75/i_like_buttons_3a/512/perspective_button_standby.png

Page 22: Is TDD dead or alive?

22 .io

Step 1 – TEST RED

Write the test, without any code written yetRED: test fails

(compilation errors are considered failures as well)

Page 23: Is TDD dead or alive?

23 .io

Step 2 – TEST GREEN

Make test work as quickly as possibleGREEN: test passes

(code satisfies the test assertions)

Page 24: Is TDD dead or alive?

24 .io

Step 3 – CODE REFACTOR

Keep the test code unchangedRework the implementation to make it

clean, DRY, flexibleGREEN: new code passes the test

(reworked code behaves exactly as before)

Page 25: Is TDD dead or alive?

25 .io

TESTIS THE HEAD

OF ALL TDD CYCLE

http://www.improveit.mx/Imagenes/tdd_esquema_en.jpg

Page 26: Is TDD dead or alive?

26 .io

TDD ASSUMES

THAT TEST IS

CORRECT

http://www.wisteriaformations.co.uk/articles/wp-content/uploads/2011/09/Company-Formation-15.jpg

Page 27: Is TDD dead or alive?

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

Page 28: Is TDD dead or alive?

28 .io

ANOTHER POSSIBLE DIFFERENT REALITY

http://www.gamerzines.com/wp-content/uploads/2014/03/morpheus-chair.jpg

Page 29: Is TDD dead or alive?

29 .io

Step 1 – TEST RED-ish

Write the [incorrect] test, no code exists yetRED: fails, but maybe the test is wrong?

(nothing works, who can tell what is really wrong?)

?

Page 30: Is TDD dead or alive?

30 .io

Step 2 – TEST GREEN-ish

Make test work as quickly as possibleGREEN: [incorrect] test passes

(is code correct or wrong? nobody really knows)

?

Page 31: Is TDD dead or alive?

31 .io

Step 3 – CODE REFACTOR-ish

Keep the test code unchangedRework the implementation to make it

clean, DRY, flexibleGREEN: reworked code passes the tests

(was the code correct before? Is the code still correct after?)

?

Page 32: Is TDD dead or alive?

32 .io

?

What is TESTING?

How to TEST the length of a table?

Use your foot Or a RULER?

Page 33: Is TDD dead or alive?

33 .io

How can I test the TEST?

How do you test a ruler?

?

Your thumb?

Or a digital caliper?

Page 34: Is TDD dead or alive?

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]

Page 35: Is TDD dead or alive?

35 .io

Test and accuracy

TEST has to be MORE ACCURATE

than CODE

Page 36: Is TDD dead or alive?

36 .io

Test and confidence

TEST cannot be testedbut we have

CONFIDENCE to beVALID

K = 299,792,458 m / s

Page 37: Is TDD dead or alive?

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));

}

Page 38: Is TDD dead or alive?

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; } }

Page 39: Is TDD dead or alive?

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)) ) }}

Page 40: Is TDD dead or alive?

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) } }

Page 41: Is TDD dead or alive?

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

Page 42: Is TDD dead or alive?

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]

Page 43: Is TDD dead or alive?

43 .io

Accurate = Readable

We can trust what we understandMake your test easy to read

Anyone would understand and validate it

Page 44: Is TDD dead or alive?

44 .io

Accurate = Explicit and repeatable

What You See is What Test DoesAgain and again the same

No side-effects No hidden logic in helper

No loopsNo random values

Page 45: Is TDD dead or alive?

45 .io

Accurate = Traceable to a requirement

When test fails,what stops working?

Use business domain namesuse business stories names

for objects, actions and results

Page 46: Is TDD dead or alive?

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?

Page 47: Is TDD dead or alive?

47 .io

WHOOPS!MY TESTS ARE INACCURATE,

WHAT SHOULD I DO?

Page 48: Is TDD dead or alive?

48 .io

Page 49: Is TDD dead or alive?

49 .io

INACCURATE TESTIS WORSE THAN

NO TEST

Page 50: Is TDD dead or alive?

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

Page 51: Is TDD dead or alive?

51 .io

REBUILDINGPROFESSIONAL TDD

https://www.flickr.com/photos/jdn/4817970175

Page 52: Is TDD dead or alive?

52 .io

Experience over Rules

Writing CODE is MORE than applying RULES

Reading CODE is MORE than reading BOOKS

Common sense, Trial and Error

Page 53: Is TDD dead or alive?

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!

Page 54: Is TDD dead or alive?

54 .io

Cost / value trade-off

Writing tests costs moneyTest 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!

Page 55: Is TDD dead or alive?

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

Page 56: Is TDD dead or alive?

56 .io

Test Focus

Tests express WHAT to achievefrom 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);}

Page 57: Is TDD dead or alive?

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

Page 58: Is TDD dead or alive?

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]

Page 59: Is TDD dead or alive?

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

Page 60: Is TDD dead or alive?

60 .io

Reading = learning to Write

Code ReviewRead A LOT of code

Read good code, read bad code

Comment, exchange ideasChallenge solutions

https://www.flickr.com/photos/jdn/4817970175

Page 61: Is TDD dead or alive?

61 .io

Write, experiment, throw waste

Write code, ask for feedbackRead your own code …

after days, weeks, monthsMeasure progress

Throw wasteKeep test and code clean, ALWAYS

Page 62: Is TDD dead or alive?

62 .io

Professional TDD Summary

1. TDD practices are not enough2. Experience over Rules3. Trade-off test time/cost and code benefit4. Tests is WHAT to achieve5. Code is confidence on DESIGN6. Read code to become a better writer7. Plan to throw test waste away

Page 63: Is TDD dead or alive?

63 .io

Page 64: Is TDD dead or alive?

64 .io

TDD resources for reading and learning Is TDD dead hangouts series

http://martinfowler.com/articles/is-tdd-dead/

Unit-testing and waste managementhttp://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf

Mockist vs. non-mockist TDDhttp://martinfowler.com/articles/mocksArentStubs.html

Page 65: Is TDD dead or alive?

65 .io

Code-review resources

Guido Van Rossum about Code Review @Googlehttp://www.youtube.com/watch?v=CKjRt48rZGk

Code Review @SAPhttp://www.eclipsecon.org/2013/sites/eclipsecon.org.2013/files/CodeReview.pptx

V. Subramaniam – About Code Review and Qualityhttp://www.agiledeveloper.com/presentations/caring_about_code_quality.pdf

Page 66: Is TDD dead or alive?

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