SlideShare ist ein Scribd-Unternehmen logo
1 von 33
Downloaden Sie, um offline zu lesen
03 BARCELONA
David Ródenas, PhD
TDD Course
TDD TECHNIQUES
@drpicox
How to tdd?
London vs. Chicago


Step Tests


Craftspeople Recipe


Refactor


Fragile Tests
TDD TECHNIQUES
@drpicox
LONDON VS CHICAGO
TDD TECHNIQUES 3
@drpicox
@drpicox
London School of TDD: Mockists


use spies to verify implementation


higher coupling


Chicago School of TDD: Statists


depend on results, not on implementation details


our objective
LONDON VS CHICAGO TDD
4
TDD TECHNIQUES — LONDON VS CHICAGO
@drpicox
@drpicox
LONDON EXAMPLE
5
TDD TECHNIQUES — LONDON VS CHICAGO
@drpicox
@drpicox
CHICAGO EXAMPLE
6
TDD TECHNIQUES — LONDON VS CHICAGO
@drpicox
STEP TESTS
TDD TECHNIQUES 7
@drpicox
@drpicox
Test that has no business value


Test that helps us to construct the code


Test that we
f
inally remove
STEP TEST
8
TDD TECHNIQUES — STEP TEST
import org.junit.jupiter.api.Test;


public class BowlingGameTest {


@Test


public void create_game() {


var g = new Game();


}


@Test


public void roll_a_ball() {


var g = new Game();


g.roll(0);


}


}
@drpicox
CRAFTSPEOPLE RECIPE
TDD TECHNIQUES 9
@drpicox
@drpicox
1. First test


2. Step tests


3. Remove UI/API references


4. Refactor


5. Business value


A. Bonus: Use tables
CRAFTSPEOPLE RECIPE
10
TDD TECHNIQUES — CRAFTSPEOPLE
@drpicox
@drpicox
Write
f
irst the test that gives you the excuse for writing the
f
irst code.
1. FIRST TESTS
11
TDD TECHNIQUES — CRAFTSPEOPLE
test("create a game", () => {


const game = new Game()


})


class Game {}
@drpicox
@drpicox
Instead of manually things, make the test
f
irst
2. STEP TESTS
12
TDD TECHNIQUES — CRAFTSPEOPLE
@drpicox
@drpicox
13
TDD TECHNIQUES — CRAFTSPEOPLE
// 1: I want to check that I can add the search box


test("There is a search box", () => {


const searchBox = getByPlaceholderText(container, "search")


expect(searchBox).toBeInTheDocument()


})


// 2: I want to check that I can write in the text box


test("The search box accepts text", () => {


const searchBox = getByPlaceholderText(container, "search")


userEvent.type(searchBox, "apollo x")


expect(searchBox).toHaveAttribute("value", "apollo x")


})
// 3: I want to check that I have a search button


test('There is a search button', () => {


const searchButton = getByText(container, 'search')


expect(searchButton).toBeInTheDocument()


})
...
@drpicox
@drpicox
// 6: I want to check that results are in the response area


test("The search result is shown in the response area", async () => {


const searchBox = getByPlaceholderText(container, "search")


})
14
TDD TECHNIQUES — CRAFTSPEOPLE
@drpicox
@drpicox
// 6: I want to check that results are in the response area


test("The search result is shown in the response area", async () => {


const searchBox = getByPlaceholderText(container, "search")


userEvent.type(searchBox, "apollo x")


})
15
TDD TECHNIQUES — CRAFTSPEOPLE
@drpicox
@drpicox
// 6: I want to check that results are in the response area


test("The search result is shown in the response area", async () => {


const searchBox = getByPlaceholderText(container, "search")


userEvent.type(searchBox, "apollo x")


const searchButton = getByText(container, "search")


})
16
TDD TECHNIQUES — CRAFTSPEOPLE
@drpicox
@drpicox
// 6: I want to check that results are in the response area


test("The search result is shown in the response area", async () => {


const searchBox = getByPlaceholderText(container, "search")


userEvent.type(searchBox, "apollo x")


const searchButton = getByText(container, "search")


searchButton.click()


await fetchMock


.whenGET("/api/v1/search?q=apollo%20x")


.respond(["snoopy and charlie brown"])


const resultArea = await findByTestId(


container,


"search-response"


)


expect(resultArea).toHaveTextContent(


"snoopy and charlie brown"


)


})
17
TDD TECHNIQUES — CRAFTSPEOPLE
@drpicox
@drpicox
Make test express your intention, not how to use the UI or API


Protect your tests from the UI/API changes
3. REMOVE UI/API REFERENCES
18
TDD TECHNIQUES — CRAFTSPEOPLE
import { search, findSearchResult } from "./__helpers__/ui.js"


test("The search result is shown in the response area", async () => {


search(container, "apollo x")


await fetchMock


.whenGET("/api/v1/search?q=apollo%20x")


.respond(["snoopy and charlie brown"])


const resultArea = await findSearchResult(container)


expect(resultArea).toHaveTextContent("snoopy and charlie brown")


})
@drpicox
@drpicox
Make test (and code) easy to read and understand
4. REFACTOR
19
TDD TECHNIQUES — CRAFTSPEOPLE
import { search } from "./__helpers__/ui.js"


import { theSearchServiceFor } from "./__helpers__/searchService.js"


test("The search result is shown in the response area",


async () => {


theSearchServiceFor("apollo%20x").respond([


"snoopy and charlie brown",


])


const resultArea = search(container, "apollo x")


expect(resultArea).toHaveTextContent(


"snoopy and charlie brown"


)


})
@drpicox
@drpicox
All tests should directly express requirements
5. BUSINESS VALUE
20
TDD TECHNIQUES — CRAFTSPEOPLE
import { search } from "./__helpers__/ui.js"


import { theSearchServiceFor } from "./__helpers__/searchService.js"


// removed test('There is a search box', () => {


// removed test('The search box accepts text', () => {


// removed test('There is a search button', () => {


// removed test('The search button makes a fetch from the service',...


test("Search for the LEM and Module name", async () => {


theSearchServiceFor("apollo%20x").respond([


"snoopy and charlie brown",


])


const resultArea = search(container, "apollo x")


expect(resultArea).toHaveTextContent("snoopy and charlie brown")


})
@drpicox
@drpicox
Refactor your test to accommodate tables
BONUS: USE TABLES
21
TDD TECHNIQUES — CRAFTSPEOPLE
test.each`


text | query | response | result


${"unknown"} | ${"unknown"} | ${[]} | ${"no results"}


${"apollo"} | ${"apollo"} | ${["snoopy", "eagle"]} | ${"snoopyeagle"}


${"apollo x"} | ${"apollo%20x"} | ${["snoopy"]} | ${"snoopy"}


${"apollo x module:command"} | ${"apollo%20x&module=command"} | ${["charlie brown"]} | ${"charlie brown"}


${"module:command"} | ${"&module=command"} | ${["charlie", "columbia"]} | ${"charliecolumbia"}


`(


'Search for the LEM and module name of "$text"',


async ({ text, query, response, result }) => {


theSearchServiceFor(query).respond(response)


const resultArea = search(container, text)


expect(resultArea).toHaveTextContent(result)


}


)
@drpicox
REFACTOR
TDD TECHNIQUES 22
@drpicox
@drpicox
Find a path for small changes


Recipe for representation changes:


1. Add the structure representation → Test


2. Add a setter code → Test


3. Repeat 2. until no more setters


4. Modify a getter code → Test


5. Repeat 4. until no more getters


6. Clean a getter code → Test & Repeat


7. Clean a setter code → Test & Repeat


8. Remove old representation → Test
DO SMALL REFACTORS
23
TDD TECHNIQUES — REFACTOR
@drpicox
@drpicox
export default class Game {


_score = 0;


roll(pins) {


this._score += pins;


}


score() {


return this._score;


}


}
EXAMPLE (BGK)
24
TDD TECHNIQUES — REFACTOR
@drpicox
@drpicox
export default class Game {


_score = 0;


_rolls = [];


roll(pins) {


this._score += pins;


}


score() {


return this._score;


}


}
EXAMPLE (BGK)
25
TDD TECHNIQUES — REFACTOR
Step 1: new representation
@drpicox
@drpicox
export default class Game {


_score = 0;


_rolls = [];


roll(pins) {


this._score += pins;


this._rolls.push(pins);


}


score() {


return this._score;


}


}
EXAMPLE (BGK)
26
TDD TECHNIQUES — REFACTOR
Step 2: setters
@drpicox
@drpicox
export default class Game {


_score = 0;


_rolls = [];


roll(pins) {


this._score += pins;


this._rolls.push(pins);


}


score() {


let score = 0;


for (let i = 0; i < this._rolls.length; i++) {


score += this._rolls[i];


}


return score;


}


}
EXAMPLE (BGK)
27
TDD TECHNIQUES — REFACTOR
Step 4: getters
@drpicox
@drpicox
export default class Game {


_score = 0;


_rolls = [];


roll(pins) {


this._score += pins;


this._rolls.push(pins);


}


score() {


let score = 0;


for (let i = 0; i < this._rolls.length; i++) {


score += this._rolls[i];


}


return score;


}


}
EXAMPLE (BGK)
28
TDD TECHNIQUES — REFACTOR
Step 7: clean setters
@drpicox
@drpicox
export default class Game {


_rolls = [];


_score = 0;


roll(pins) {


this._rolls.push(pins);


}


score() {


let score = 0;


for (let i = 0; i < this._rolls.length; i++) {


score += this._rolls[i];


}


return score;


}


}
EXAMPLE (BGK)
29
TDD TECHNIQUES — REFACTOR
Step 8: clean old represent.
@drpicox
@drpicox
export default class Game {


_rolls = [];


roll(pins) {


this._rolls.push(pins);


}


score() {


let score = 0;


for (let i = 0; i < this._rolls.length; i++) {


score += this._rolls[i];


}


return score;


}


}
EXAMPLE (BGK)
30
TDD TECHNIQUES — REFACTOR
Done
@drpicox
FRAGILE TESTS
TDD TECHNIQUES 31
@drpicox
@drpicox
Programmers have to read the production code to
work out what the system does, rather than the tests.


When a test fails programmers usually have to
f
ix the
test, not production code.


When a test fails programmers have to step through
code in the debugger to work out what failed.


It takes a lot of effort to write a test, and after a few
tests, writing another test isn’t any easier.


Programmers have to carefully study the code of a
test to work out what it is actually testing.


Programmers have to carefully study the code of a
test to work out what it is not testing.


Tests are named after issue identi
f
iers in the
company's issue tracker. Bonus points if the issue
tracker no longer exists.


Test failures are ignored because the team expect
them to be transient or meaningless.


The test veri
f
ies that the library works, not the actual
code.


Tests do not express the intention of their feature.
SYMPTOMS
32
TDD TECHNIQUES — FRAGILE TESTS
@drpicox
E.O.TDD TECHNIQUES

Weitere ähnliche Inhalte

Was ist angesagt?

TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012Pietro Di Bello
 
Unit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and HowsUnit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and Howsatesgoral
 
Unit Test Your Database
Unit Test Your DatabaseUnit Test Your Database
Unit Test Your DatabaseDavid Wheeler
 
Stopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under TestStopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under TestSeb Rose
 
Navigating the xDD Alphabet Soup
Navigating the xDD Alphabet SoupNavigating the xDD Alphabet Soup
Navigating the xDD Alphabet SoupDror Helper
 
Working Effectively with Legacy Code
Working Effectively with Legacy CodeWorking Effectively with Legacy Code
Working Effectively with Legacy Codeslicklash
 
TDD and the Legacy Code Black Hole
TDD and the Legacy Code Black HoleTDD and the Legacy Code Black Hole
TDD and the Legacy Code Black HoleNoam Kfir
 
20111018 boost and gtest
20111018 boost and gtest20111018 boost and gtest
20111018 boost and gtestWill Shen
 
Tdd & clean code
Tdd & clean codeTdd & clean code
Tdd & clean codeEyal Vardi
 
Software Engineering - RS3
Software Engineering - RS3Software Engineering - RS3
Software Engineering - RS3AtakanAral
 
Applying TDD to Legacy Code
Applying TDD to Legacy CodeApplying TDD to Legacy Code
Applying TDD to Legacy CodeAlexander Goida
 
iOS Unit Testing
iOS Unit TestingiOS Unit Testing
iOS Unit Testingsgleadow
 
Google C++ Testing Framework in Visual Studio 2008
Google C++ Testing Framework in Visual Studio 2008Google C++ Testing Framework in Visual Studio 2008
Google C++ Testing Framework in Visual Studio 2008Andrea Francia
 
Testing Legacy Rails Apps
Testing Legacy Rails AppsTesting Legacy Rails Apps
Testing Legacy Rails AppsRabble .
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Developmentguy_davis
 
Google mock for dummies
Google mock for dummiesGoogle mock for dummies
Google mock for dummiesHarry Potter
 
Presentation_C++UnitTest
Presentation_C++UnitTestPresentation_C++UnitTest
Presentation_C++UnitTestRaihan Masud
 
Google test training
Google test trainingGoogle test training
Google test trainingThierry Gayet
 

Was ist angesagt? (20)

TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012
 
Unit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and HowsUnit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and Hows
 
Unit Test Your Database
Unit Test Your DatabaseUnit Test Your Database
Unit Test Your Database
 
Stopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under TestStopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under Test
 
Navigating the xDD Alphabet Soup
Navigating the xDD Alphabet SoupNavigating the xDD Alphabet Soup
Navigating the xDD Alphabet Soup
 
PHPUnit - Unit testing
PHPUnit - Unit testingPHPUnit - Unit testing
PHPUnit - Unit testing
 
Working Effectively with Legacy Code
Working Effectively with Legacy CodeWorking Effectively with Legacy Code
Working Effectively with Legacy Code
 
Cursus phpunit
Cursus phpunitCursus phpunit
Cursus phpunit
 
TDD and the Legacy Code Black Hole
TDD and the Legacy Code Black HoleTDD and the Legacy Code Black Hole
TDD and the Legacy Code Black Hole
 
20111018 boost and gtest
20111018 boost and gtest20111018 boost and gtest
20111018 boost and gtest
 
Tdd & clean code
Tdd & clean codeTdd & clean code
Tdd & clean code
 
Software Engineering - RS3
Software Engineering - RS3Software Engineering - RS3
Software Engineering - RS3
 
Applying TDD to Legacy Code
Applying TDD to Legacy CodeApplying TDD to Legacy Code
Applying TDD to Legacy Code
 
iOS Unit Testing
iOS Unit TestingiOS Unit Testing
iOS Unit Testing
 
Google C++ Testing Framework in Visual Studio 2008
Google C++ Testing Framework in Visual Studio 2008Google C++ Testing Framework in Visual Studio 2008
Google C++ Testing Framework in Visual Studio 2008
 
Testing Legacy Rails Apps
Testing Legacy Rails AppsTesting Legacy Rails Apps
Testing Legacy Rails Apps
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
Google mock for dummies
Google mock for dummiesGoogle mock for dummies
Google mock for dummies
 
Presentation_C++UnitTest
Presentation_C++UnitTestPresentation_C++UnitTest
Presentation_C++UnitTest
 
Google test training
Google test trainingGoogle test training
Google test training
 

Ähnlich wie TDD CrashCourse Part3: TDD Techniques

ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)David Rodenas
 
Static analysis: Around Java in 60 minutes
Static analysis: Around Java in 60 minutesStatic analysis: Around Java in 60 minutes
Static analysis: Around Java in 60 minutesAndrey Karpov
 
TDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving TestingTDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving TestingDavid Rodenas
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good TestsTomek Kaczanowski
 
React mit TypeScript – eine glückliche Ehe
React mit TypeScript – eine glückliche EheReact mit TypeScript – eine glückliche Ehe
React mit TypeScript – eine glückliche Eheinovex GmbH
 
EVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMER
EVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMEREVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMER
EVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMERAndrey Karpov
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good TestsTomek Kaczanowski
 
An Introduction to Property Based Testing
An Introduction to Property Based TestingAn Introduction to Property Based Testing
An Introduction to Property Based TestingC4Media
 
Mutation testing Bucharest Tech Week
Mutation testing Bucharest Tech WeekMutation testing Bucharest Tech Week
Mutation testing Bucharest Tech WeekPaco van Beckhoven
 
Refactoring
RefactoringRefactoring
Refactoringnkaluva
 
The real beginner's guide to android testing
The real beginner's guide to android testingThe real beginner's guide to android testing
The real beginner's guide to android testingEric (Trung Dung) Nguyen
 
Aaron Bedra - Effective Software Security Teams
Aaron Bedra - Effective Software Security TeamsAaron Bedra - Effective Software Security Teams
Aaron Bedra - Effective Software Security Teamscentralohioissa
 
The Ring programming language version 1.7 book - Part 92 of 196
The Ring programming language version 1.7 book - Part 92 of 196The Ring programming language version 1.7 book - Part 92 of 196
The Ring programming language version 1.7 book - Part 92 of 196Mahmoud Samir Fayed
 
Python Functions Tutorial | Working With Functions In Python | Python Trainin...
Python Functions Tutorial | Working With Functions In Python | Python Trainin...Python Functions Tutorial | Working With Functions In Python | Python Trainin...
Python Functions Tutorial | Working With Functions In Python | Python Trainin...Edureka!
 
The Ring programming language version 1.6 book - Part 184 of 189
The Ring programming language version 1.6 book - Part 184 of 189The Ring programming language version 1.6 book - Part 184 of 189
The Ring programming language version 1.6 book - Part 184 of 189Mahmoud Samir Fayed
 

Ähnlich wie TDD CrashCourse Part3: TDD Techniques (20)

ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)
 
Design for Testability
Design for TestabilityDesign for Testability
Design for Testability
 
Static analysis: Around Java in 60 minutes
Static analysis: Around Java in 60 minutesStatic analysis: Around Java in 60 minutes
Static analysis: Around Java in 60 minutes
 
TDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving TestingTDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving Testing
 
report
reportreport
report
 
Python testing
Python  testingPython  testing
Python testing
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
 
React mit TypeScript – eine glückliche Ehe
React mit TypeScript – eine glückliche EheReact mit TypeScript – eine glückliche Ehe
React mit TypeScript – eine glückliche Ehe
 
EVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMER
EVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMEREVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMER
EVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMER
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests
 
An Introduction to Property Based Testing
An Introduction to Property Based TestingAn Introduction to Property Based Testing
An Introduction to Property Based Testing
 
Mutation testing Bucharest Tech Week
Mutation testing Bucharest Tech WeekMutation testing Bucharest Tech Week
Mutation testing Bucharest Tech Week
 
DIWE - Advanced PHP Concepts
DIWE - Advanced PHP ConceptsDIWE - Advanced PHP Concepts
DIWE - Advanced PHP Concepts
 
Refactoring
RefactoringRefactoring
Refactoring
 
The real beginner's guide to android testing
The real beginner's guide to android testingThe real beginner's guide to android testing
The real beginner's guide to android testing
 
Aaron Bedra - Effective Software Security Teams
Aaron Bedra - Effective Software Security TeamsAaron Bedra - Effective Software Security Teams
Aaron Bedra - Effective Software Security Teams
 
The Ring programming language version 1.7 book - Part 92 of 196
The Ring programming language version 1.7 book - Part 92 of 196The Ring programming language version 1.7 book - Part 92 of 196
The Ring programming language version 1.7 book - Part 92 of 196
 
Python Functions Tutorial | Working With Functions In Python | Python Trainin...
Python Functions Tutorial | Working With Functions In Python | Python Trainin...Python Functions Tutorial | Working With Functions In Python | Python Trainin...
Python Functions Tutorial | Working With Functions In Python | Python Trainin...
 
Rhino Mocks
Rhino MocksRhino Mocks
Rhino Mocks
 
The Ring programming language version 1.6 book - Part 184 of 189
The Ring programming language version 1.6 book - Part 184 of 189The Ring programming language version 1.6 book - Part 184 of 189
The Ring programming language version 1.6 book - Part 184 of 189
 

Mehr von David Rodenas

TDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDDTDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDDDavid Rodenas
 
TDD CrashCourse Part1: Testing
TDD CrashCourse Part1: TestingTDD CrashCourse Part1: Testing
TDD CrashCourse Part1: TestingDavid Rodenas
 
Be professional: We Rule the World
Be professional: We Rule the WorldBe professional: We Rule the World
Be professional: We Rule the WorldDavid Rodenas
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorDavid Rodenas
 
ES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game KataES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game KataDavid Rodenas
 
ES3-2020-07 Testing techniques
ES3-2020-07 Testing techniquesES3-2020-07 Testing techniques
ES3-2020-07 Testing techniquesDavid Rodenas
 
ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for ProgrammersDavid Rodenas
 
Redux for ReactJS Programmers
Redux for ReactJS ProgrammersRedux for ReactJS Programmers
Redux for ReactJS ProgrammersDavid Rodenas
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersDavid Rodenas
 
From high school to university and work
From high school to university and workFrom high school to university and work
From high school to university and workDavid Rodenas
 
Modules in angular 2.0 beta.1
Modules in angular 2.0 beta.1Modules in angular 2.0 beta.1
Modules in angular 2.0 beta.1David Rodenas
 
Freelance i Enginyeria
Freelance i EnginyeriaFreelance i Enginyeria
Freelance i EnginyeriaDavid Rodenas
 
Angular 1.X Community and API Decissions
Angular 1.X Community and API DecissionsAngular 1.X Community and API Decissions
Angular 1.X Community and API DecissionsDavid Rodenas
 
Mvc - Model: the great forgotten
Mvc - Model: the great forgottenMvc - Model: the great forgotten
Mvc - Model: the great forgottenDavid Rodenas
 

Mehr von David Rodenas (19)

TDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDDTDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDD
 
TDD CrashCourse Part1: Testing
TDD CrashCourse Part1: TestingTDD CrashCourse Part1: Testing
TDD CrashCourse Part1: Testing
 
Be professional: We Rule the World
Be professional: We Rule the WorldBe professional: We Rule the World
Be professional: We Rule the World
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD Calculator
 
ES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game KataES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game Kata
 
ES3-2020-07 Testing techniques
ES3-2020-07 Testing techniquesES3-2020-07 Testing techniques
ES3-2020-07 Testing techniques
 
ES3-2020-05 Testing
ES3-2020-05 TestingES3-2020-05 Testing
ES3-2020-05 Testing
 
ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for Programmers
 
Vespres
VespresVespres
Vespres
 
Faster web pages
Faster web pagesFaster web pages
Faster web pages
 
Redux for ReactJS Programmers
Redux for ReactJS ProgrammersRedux for ReactJS Programmers
Redux for ReactJS Programmers
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for Programmers
 
From high school to university and work
From high school to university and workFrom high school to university and work
From high school to university and work
 
Modules in angular 2.0 beta.1
Modules in angular 2.0 beta.1Modules in angular 2.0 beta.1
Modules in angular 2.0 beta.1
 
Freelance i Enginyeria
Freelance i EnginyeriaFreelance i Enginyeria
Freelance i Enginyeria
 
Angular 1.X Community and API Decissions
Angular 1.X Community and API DecissionsAngular 1.X Community and API Decissions
Angular 1.X Community and API Decissions
 
JS and patterns
JS and patternsJS and patterns
JS and patterns
 
MVS: An angular MVC
MVS: An angular MVCMVS: An angular MVC
MVS: An angular MVC
 
Mvc - Model: the great forgotten
Mvc - Model: the great forgottenMvc - Model: the great forgotten
Mvc - Model: the great forgotten
 

Kürzlich hochgeladen

How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)jennyeacort
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfIdiosysTechnologies1
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfLivetecs LLC
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 

Kürzlich hochgeladen (20)

How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdf
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdf
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 

TDD CrashCourse Part3: TDD Techniques

  • 1. 03 BARCELONA David Ródenas, PhD TDD Course TDD TECHNIQUES
  • 2. @drpicox How to tdd? London vs. Chicago Step Tests Craftspeople Recipe Refactor Fragile Tests TDD TECHNIQUES
  • 4. @drpicox @drpicox London School of TDD: Mockists use spies to verify implementation higher coupling Chicago School of TDD: Statists depend on results, not on implementation details our objective LONDON VS CHICAGO TDD 4 TDD TECHNIQUES — LONDON VS CHICAGO
  • 8. @drpicox @drpicox Test that has no business value Test that helps us to construct the code Test that we f inally remove STEP TEST 8 TDD TECHNIQUES — STEP TEST import org.junit.jupiter.api.Test; public class BowlingGameTest { @Test public void create_game() { var g = new Game(); } @Test public void roll_a_ball() { var g = new Game(); g.roll(0); } }
  • 10. @drpicox @drpicox 1. First test 2. Step tests 3. Remove UI/API references 4. Refactor 5. Business value A. Bonus: Use tables CRAFTSPEOPLE RECIPE 10 TDD TECHNIQUES — CRAFTSPEOPLE
  • 11. @drpicox @drpicox Write f irst the test that gives you the excuse for writing the f irst code. 1. FIRST TESTS 11 TDD TECHNIQUES — CRAFTSPEOPLE test("create a game", () => { const game = new Game() }) class Game {}
  • 12. @drpicox @drpicox Instead of manually things, make the test f irst 2. STEP TESTS 12 TDD TECHNIQUES — CRAFTSPEOPLE
  • 13. @drpicox @drpicox 13 TDD TECHNIQUES — CRAFTSPEOPLE // 1: I want to check that I can add the search box test("There is a search box", () => { const searchBox = getByPlaceholderText(container, "search") expect(searchBox).toBeInTheDocument() }) // 2: I want to check that I can write in the text box test("The search box accepts text", () => { const searchBox = getByPlaceholderText(container, "search") userEvent.type(searchBox, "apollo x") expect(searchBox).toHaveAttribute("value", "apollo x") }) // 3: I want to check that I have a search button test('There is a search button', () => { const searchButton = getByText(container, 'search') expect(searchButton).toBeInTheDocument() }) ...
  • 14. @drpicox @drpicox // 6: I want to check that results are in the response area test("The search result is shown in the response area", async () => { const searchBox = getByPlaceholderText(container, "search") }) 14 TDD TECHNIQUES — CRAFTSPEOPLE
  • 15. @drpicox @drpicox // 6: I want to check that results are in the response area test("The search result is shown in the response area", async () => { const searchBox = getByPlaceholderText(container, "search") userEvent.type(searchBox, "apollo x") }) 15 TDD TECHNIQUES — CRAFTSPEOPLE
  • 16. @drpicox @drpicox // 6: I want to check that results are in the response area test("The search result is shown in the response area", async () => { const searchBox = getByPlaceholderText(container, "search") userEvent.type(searchBox, "apollo x") const searchButton = getByText(container, "search") }) 16 TDD TECHNIQUES — CRAFTSPEOPLE
  • 17. @drpicox @drpicox // 6: I want to check that results are in the response area test("The search result is shown in the response area", async () => { const searchBox = getByPlaceholderText(container, "search") userEvent.type(searchBox, "apollo x") const searchButton = getByText(container, "search") searchButton.click() await fetchMock .whenGET("/api/v1/search?q=apollo%20x") .respond(["snoopy and charlie brown"]) const resultArea = await findByTestId( container, "search-response" ) expect(resultArea).toHaveTextContent( "snoopy and charlie brown" ) }) 17 TDD TECHNIQUES — CRAFTSPEOPLE
  • 18. @drpicox @drpicox Make test express your intention, not how to use the UI or API Protect your tests from the UI/API changes 3. REMOVE UI/API REFERENCES 18 TDD TECHNIQUES — CRAFTSPEOPLE import { search, findSearchResult } from "./__helpers__/ui.js" test("The search result is shown in the response area", async () => { search(container, "apollo x") await fetchMock .whenGET("/api/v1/search?q=apollo%20x") .respond(["snoopy and charlie brown"]) const resultArea = await findSearchResult(container) expect(resultArea).toHaveTextContent("snoopy and charlie brown") })
  • 19. @drpicox @drpicox Make test (and code) easy to read and understand 4. REFACTOR 19 TDD TECHNIQUES — CRAFTSPEOPLE import { search } from "./__helpers__/ui.js" import { theSearchServiceFor } from "./__helpers__/searchService.js" test("The search result is shown in the response area", async () => { theSearchServiceFor("apollo%20x").respond([ "snoopy and charlie brown", ]) const resultArea = search(container, "apollo x") expect(resultArea).toHaveTextContent( "snoopy and charlie brown" ) })
  • 20. @drpicox @drpicox All tests should directly express requirements 5. BUSINESS VALUE 20 TDD TECHNIQUES — CRAFTSPEOPLE import { search } from "./__helpers__/ui.js" import { theSearchServiceFor } from "./__helpers__/searchService.js" // removed test('There is a search box', () => { // removed test('The search box accepts text', () => { // removed test('There is a search button', () => { // removed test('The search button makes a fetch from the service',... test("Search for the LEM and Module name", async () => { theSearchServiceFor("apollo%20x").respond([ "snoopy and charlie brown", ]) const resultArea = search(container, "apollo x") expect(resultArea).toHaveTextContent("snoopy and charlie brown") })
  • 21. @drpicox @drpicox Refactor your test to accommodate tables BONUS: USE TABLES 21 TDD TECHNIQUES — CRAFTSPEOPLE test.each` text | query | response | result ${"unknown"} | ${"unknown"} | ${[]} | ${"no results"} ${"apollo"} | ${"apollo"} | ${["snoopy", "eagle"]} | ${"snoopyeagle"} ${"apollo x"} | ${"apollo%20x"} | ${["snoopy"]} | ${"snoopy"} ${"apollo x module:command"} | ${"apollo%20x&module=command"} | ${["charlie brown"]} | ${"charlie brown"} ${"module:command"} | ${"&module=command"} | ${["charlie", "columbia"]} | ${"charliecolumbia"} `( 'Search for the LEM and module name of "$text"', async ({ text, query, response, result }) => { theSearchServiceFor(query).respond(response) const resultArea = search(container, text) expect(resultArea).toHaveTextContent(result) } )
  • 23. @drpicox @drpicox Find a path for small changes Recipe for representation changes: 1. Add the structure representation → Test 2. Add a setter code → Test 3. Repeat 2. until no more setters 4. Modify a getter code → Test 5. Repeat 4. until no more getters 6. Clean a getter code → Test & Repeat 7. Clean a setter code → Test & Repeat 8. Remove old representation → Test DO SMALL REFACTORS 23 TDD TECHNIQUES — REFACTOR
  • 24. @drpicox @drpicox export default class Game { _score = 0; roll(pins) { this._score += pins; } score() { return this._score; } } EXAMPLE (BGK) 24 TDD TECHNIQUES — REFACTOR
  • 25. @drpicox @drpicox export default class Game { _score = 0; _rolls = []; roll(pins) { this._score += pins; } score() { return this._score; } } EXAMPLE (BGK) 25 TDD TECHNIQUES — REFACTOR Step 1: new representation
  • 26. @drpicox @drpicox export default class Game { _score = 0; _rolls = []; roll(pins) { this._score += pins; this._rolls.push(pins); } score() { return this._score; } } EXAMPLE (BGK) 26 TDD TECHNIQUES — REFACTOR Step 2: setters
  • 27. @drpicox @drpicox export default class Game { _score = 0; _rolls = []; roll(pins) { this._score += pins; this._rolls.push(pins); } score() { let score = 0; for (let i = 0; i < this._rolls.length; i++) { score += this._rolls[i]; } return score; } } EXAMPLE (BGK) 27 TDD TECHNIQUES — REFACTOR Step 4: getters
  • 28. @drpicox @drpicox export default class Game { _score = 0; _rolls = []; roll(pins) { this._score += pins; this._rolls.push(pins); } score() { let score = 0; for (let i = 0; i < this._rolls.length; i++) { score += this._rolls[i]; } return score; } } EXAMPLE (BGK) 28 TDD TECHNIQUES — REFACTOR Step 7: clean setters
  • 29. @drpicox @drpicox export default class Game { _rolls = []; _score = 0; roll(pins) { this._rolls.push(pins); } score() { let score = 0; for (let i = 0; i < this._rolls.length; i++) { score += this._rolls[i]; } return score; } } EXAMPLE (BGK) 29 TDD TECHNIQUES — REFACTOR Step 8: clean old represent.
  • 30. @drpicox @drpicox export default class Game { _rolls = []; roll(pins) { this._rolls.push(pins); } score() { let score = 0; for (let i = 0; i < this._rolls.length; i++) { score += this._rolls[i]; } return score; } } EXAMPLE (BGK) 30 TDD TECHNIQUES — REFACTOR Done
  • 32. @drpicox @drpicox Programmers have to read the production code to work out what the system does, rather than the tests. When a test fails programmers usually have to f ix the test, not production code. When a test fails programmers have to step through code in the debugger to work out what failed. It takes a lot of effort to write a test, and after a few tests, writing another test isn’t any easier. Programmers have to carefully study the code of a test to work out what it is actually testing. Programmers have to carefully study the code of a test to work out what it is not testing. Tests are named after issue identi f iers in the company's issue tracker. Bonus points if the issue tracker no longer exists. Test failures are ignored because the team expect them to be transient or meaningless. The test veri f ies that the library works, not the actual code. Tests do not express the intention of their feature. SYMPTOMS 32 TDD TECHNIQUES — FRAGILE TESTS