Tieto tdd from-dreams_to_reality_s.narkevicius_v.pozdniakov_2013 (1)
-
Upload
agile-lietuva -
Category
Technology
-
view
670 -
download
1
description
Transcript of Tieto tdd from-dreams_to_reality_s.narkevicius_v.pozdniakov_2013 (1)
© 2
013
Tie
to C
orpo
ratio
n
TDD – from dreams to realitySaulius Narkevičius. Viačeslav Pozdniakov.
© 2013 Tieto Corporation
Programming architect(~ 23 years of programing)
University lector
Assembler, …, Java, ...
Desktop / Web
UI / Middleware / Database
Waterfall / Agile / Whatever
Saulius Viačeslav
24 hours developer(~ 9 years of programing)
University lector
Scala, Haskell, Java, ...
Desktop / Web
Databases / Middleware
Agile / Whatever
© 2
013
Tie
to C
orpo
ratio
n
Three TDD steps
1. Failing test 2. Production code
3. Refactor
© 2013 Tieto Corporation
TDD dreamFast feedback
Drives simple code design
DocumentationKeeps
developers head “empty” –
everything is in code
Safety net for refactoring
© 2
013
Tie
to C
orpo
ratio
n
Super feature request:
“Calculate average of two integer values”
© 2
013
Tie
to C
orpo
ratio
n
int averageOf(int a, int b) { return (a + b) / 2; }
Java solution 20 seconds later
© 2
013
Tie
to C
orpo
ratio
n
1. Red – write a failing test @Test public void smokeTestAverage() { assertThat(averageOf(2, 4), is(3)); }
Does not compile – No averageOf() exists yet!
© 2
013
Tie
to C
orpo
ratio
n
2. Green – just enough production code
Test passes successfully
@Test public void smokeTestAverage() { assertThat(averageOf(2, 4), is(3)); }
int averageOf(int a, int b) { return 3; }
© 2
013
Tie
to C
orpo
ratio
n
3. Refactor – make code cleaner
Nothing to refactor yet
@Test public void smokeTestAverage() { assertThat(averageOf(2, 4), is(3)); }
int averageOf(int a, int b) { return 3; }
© 2
013
Tie
to C
orpo
ratio
n
Repeat: red, green, refactor
Hmm, code is really dumb…
@Test public void smokeTestAverage() { assertThat(averageOf(2, 4), is(3)); assertThat(averageOf(10, 20), is(15)); }
int averageOf(int a, int b) { return (a == 10) ? 15 : 3; }
© 2
013
Tie
to C
orpo
ratio
n
Let’s triangulate
Done!!! Took longer with tests :(
@Test public void smokeTestAverage() { assertThat(averageOf(2, 4), is(3)); assertThat(averageOf(10, 20), is(15)); assertThat(averageOf(-8, -16), is(-12)); }
int averageOf(int a, int b) { return (a + b) / 2; }
© 2
013
Tie
to C
orpo
ratio
n
Edge cases
FAILED: Expected 2147483647 but was -1
@Test public void edgeCasesForAverage() { assertThat(averageOf(MAX, MAX), is(MAX)); assertThat(averageOf(MIN, MIN), is(MIN)); }
int averageOf(int a, int b) { return (a + b) / 2; }
© 2
013
Tie
to C
orpo
ratio
n
Avoid overflow by using subtraction
Tests pass successfully
@Test public void edgeCasesForAverage() { assertThat(averageOf(MAX, MAX), is(MAX)); assertThat(averageOf(MIN, MIN), is(MIN)); }
int averageOf(int a, int b) { int high = (a > b ? a : b); int low = (a > b ? b : a); return low + ((high - low) / 2); }
© 2
013
Tie
to C
orpo
ratio
n
One more edge case
FAILED: Expected 0 but was -2147483648
@Test public void edgeCasesForAverage() { assertThat(averageOf(MAX, MAX), is(MAX)); assertThat(averageOf(MIN, MIN), is(MIN)); assertThat(averageOf(MIN, MAX), is(0)); }
int averageOf(int a, int b) { int high = (a > b ? a : b); int low = (a > b ? b : a); return low + ((high - low) / 2); }
When to stop?
© 2013 Tieto Corporation
When TDD shines
→ Clear requirements
→ Requirements do not change every hour
→ Sample tests are in place
→ Test execution is fast and one click away
→ Testing environment similar to production.
© 2013 Tieto Corporation
TDD in the real world
→ What to test?
→ Building data sets for tests
→ Sample tests to start from
→ Legacy code may not be testable
→ What not to test?
© 2013 Tieto Corporation
“What to test?” is a wrong question
→ We are not testing but specifying sample usage scenarios
→ What do you want to specify / describe?
→ Testing frameworks speak “Specs”:• RSpec, Cucumber, Jasmine, Concordion, ...
→ TDD thought leaders done this years ago:• Dan North, Dave Astels, Robert C Martin (a.k.a. Uncle Bob), ...
→ Naming is everything (see: Specification by Example)
© 2
013
Tie
to C
orpo
ratio
n
Sample test @Test public void testCreatBookWithFullData() { tester.login(); tester.startPage(BookEditPage.class); FormTester formTester = tester.newFormTester("newBookForm"); formTester.setValue("main.container:title", “Some book title"); formTester.setValue("main.container:author", “Some author"); formTester.setValue("main.container:year", "1999"); formTester.setValue("main.container:publisherPageUrl", "www.newBook.lt"); formTester.setValue("main.container:pages", "222"); formTester.setValue("main.container:publisherName", “Some publisher"); formTester.setValue("main.container:series", “Very interesting series"); formTester.setValue("main.container:originalName", “some original name"); formTester.submit("submit"); tester.assertRenderedPage(BookPage.class); tester.assertLabel("title", " Some book title"); tester.assertLabel("authorPanel:authors:0:author.link:author", "Some author"); tester.assertContains("some original name"); tester.assertLabel("years.link:year", "1999"); tester.assertLabel("publisher.link:publisher.name", "Some publisher"); tester.assertLabel("pages", "222");
}
Do not read this code
© 2
013
Tie
to C
orpo
ratio
n
Same test as spec
public void creating_new_book_scenario() { givenCurrentUserIsAnAdministrator(); Book newBook = createNewBook(); show(BookEditPage.class); fillFormFieldsWith(newBook);
submitForm();
expectCurrentPageIs(BookPage.class); expectCurrentPageDisplaysAttributesOf(newBook); }
© 2
013
Tie
to C
orpo
ratio
n
Data sets for specs // create or load from test DB
interface TypicalUsers { User admin(); User guest(); User reviewer(); User author(); } interface TypicalBooks { Book basicBook(); Book bookWithThreeAuthors(); Book bookWithReview(); }
© 2
013
Tie
to C
orpo
ratio
n
Sample spec for persistence @Test public void orm_mappings_are_ok () { loadAndPrintSomeEntitiesOf(Book.class); }
© 2
013
Tie
to C
orpo
ratio
n
Sample spec for UI @Test public void renders_successfully() { new WicketTester().startPage(NewClientPage.class); }
© 2
013
Tie
to C
orpo
ratio
n
Sample spec for business logic (WS)@Test public void extending_book_loan() { process(requestToBookLoanHandler(”extend_loan_request.xml")); expectResponse(”loan_approved_response.xml");}
© 2013 Tieto Corporation
Writing testable code
Is writing tests easy?
Yes, it is.
The art is in writing testable production code!
→ See short guide: “Writing Testable Code”
© 2013 Tieto Corporation
What not to specify: technical viewpoint
→Getters, setters and member variables
→One line functions
→GUI – make as thin and dumb as possible
→Frameworks – things you do not control
→Things which are hard to code - by trial and error.
© 2013 Tieto Corporation
What not to specify:process viewpoint
→Accelerated Agile – buzzword from Dan North
→Some ingredients of accelerated agile:• developers become domain experts• short iterations (days, hours) – less chance for bugs• deliver as soon as possible – even without specs• discover knowledge from real usage
→ Write specs for code which survived real usage
→Works for some projects
© 2
013
Tie
to C
orpo
ratio
n
TDD:from DREAMS to
REALITY
Think “specs”
not “tests”
Know what to specify
Use TDD wisely
Real specs come from real usage
Know what not to
specify
Simple smoke specs are a
good investment
Simplify writing specs by “Writing Testable Code”
© 2
013
Tie
to C
orpo
ratio
n
Questions?