SlideShare a Scribd company logo
06 Testing - TDD
Enginyeria del Software 3
1
@drpicox — 2020
Accounting
• Accounting is a discipline that is in charge of studying,
measuring and analyzing the assets and financial and
economic situation of a company or organization, in order
to facilitate decision-making within it and external control,
presenting the information , previously registered, in a
systematic and useful way for the different interested
parties.



—Wikipedia
2
Double-entry bookkeping
• At least two accounting entries are required to record
each financial transaction: debit and credit.
3
–Merriam-Webster dictionary
“Discipline: training that corrects, molds, or
perfects the mental faculties or moral character”
4
Test Development Driven
• The Three rules of TDD:

1. You are not allowed to write any production code unless it is
to make a failing unit test pass.

2. You are not allowed to write any more of a unit test than is
sufficient to fail; and compilation failures are failures.

3. You are not allowed to write any more production code than
is sufficient to pass the one failing unit test.
5
http://www.butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
Stages of TDD
6
RED
GREEN
REFACTOR
TEST CODE
CLEAN
Write production code
until tests pass.
Write tests
until a test fails.
Clean code while tests passes.
Clean tests while tests passes.
Clean ...
...
YOU
START
HERE
30s
loop
Common Pitfalls (1/2)
• Typical individual mistakes include:

• forgetting to run tests frequently,

• writing too many tests at once,

• writing tests that are too large or coarse-grained,

• writing overly trivial tests, for instance omitting assertions,

• writing tests for trivial code, for instance accessors.
7
Common Pitfalls (2/2)
• Typical team mistakes include:

• partial adoption: only a few developers on the team use TDD,

• poor maintenance of the test suite: most commonly leading to a
test suite with a prohibitively long running time,

• abandoned test suite (i.e. seldom or never run): sometimes as a
result of poor maintenance, sometimes as a result of team
turnover.
8
London vs Chicago TDD
• London School of TDD: Mockists

• use spies to verify implementation

• higher coupling

• Chicago School of TDD: Statists

• depend on results, not on imlpementation details

• our objective
9
London Example
import { add } from "math"
import multiply from "./multiply"
let log
function addMock(a, b) {
log.push(`${a}+${b}`)
return add(a, b)
}
test("multiplies two numbers", () => {
log = []
const result = multiply(3, 4, { add: addMock })
expect(log).toEqual("0+3", "3+3", "6+3", "9+3")
expect(result).toEqual(12)
})
10
Chicago Example
import multiply from "./multiply"
test("multiplies two numbers", () => {
const result = multiply(3, 4)
expect(result).toEqual(12)
})
11
Craftsman Recipe
• You already know how to create tests and do TDD

• Probably you already do some kind of TDD manually

• You just need to write it first

• There are 5 steps to help you
12
Step 1: First tests
• Write first the test that gives you the excuse for writing
the first code.
13
test("create a game", () => {
const game = new Game()
})
class Game {}
Step 2: Progressing
• You already test manually things before and after code

• Write the test code that test that for you
14
Step 2: Progressing
// 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()
})
15
Step 2: Progressing
// 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")
})
16
Step 2: Progressing
// 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()
})
17
Step 2: Progressing
// 4: I want to know that clicking in search triggers fetch
test("The search button makes a fetch from the service",
async () => {
const searchBox = getByPlaceholderText(
container,
"search"
)
userEvent.type(searchBox, "apollo x")
const searchButton = getByText(container, "search")
searchButton.click()
await fetchMock.expectGET("/api/v1/search?q=apollo%20x")
})
18
Step 2: Progressing
// 5: I want to know if there is the response area
test("There is a response area after doing a search", 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).toBeInTheDocument()
})
19
Step 2: Progressing
// 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"
)
})
20
Step 3: Remove UI use
• Make test express your intention, not how to use the UI

• Protect your tests from the UI changes
21
Step 3: Remove UI use
• Make test express your intention, not how to use the UI

• Protect your tests from the UI changes
22
Step 3: Remove UI use
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"
)
})
23
Step 3: Remove UI use
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"
)
})
24
Step 3: Remove UI use
// __helpers__/ui.js
export function search(container, text) {
const searchBox = getByPlaceholderText(
container,
"search"
)
userEvent.type(searchBox, text)
const searchButton = getByText(container, "search")
searchButton.click()
}
export async function findSearchResult(container) {
const results = await findByTestId(
container,
"search-result"
)
return results
}
25
Step 4: Refactor
• Make test and code easy to read and understand
26
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"
)
})
Step 5: Business value
• All tests should directly express requirements
27
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"
)
})
Bonus Step: Use tables
• Refactor your test to accommodate tables
28
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)
}
)
Refactors
• Big Refactors

• Small Refactors
29
Big Refactors
• Programmers always want to throw
away the code and start over

• They think the old code is a mess

• They are probably wrong.
30
https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/
by Joel Spolsky
It’s harder to read code than to write it.
Small Refactors
• Leverage on Tests: small change, test, small change, test, ...

• Clean the code and adjust the architecture, slowly and firmly
31
REFACTOR
CLEAN
Small Refactors
• 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. Moddify 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
32
Example (BGK)
export default class Game {
_score = 0;
roll(pins) {
this._score += pins;
}
score() {
return this._score;
}
}
33
Example (BGK)
export default class Game {
_score = 0;
_rolls = [];
roll(pins) {
this._score += pins;
}
score() {
return this._score;
}
}
34
Step 1: new representation
Example (BGK)
export default class Game {
_score = 0;
_rolls = [];
roll(pins) {
this._score += pins;
this._rolls.push(pins);
}
score() {
return this._score;
}
}
35
Step 2: setters
Example (BGK)
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;
}
}
36
Step 4: getters
Example (BGK)
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;
}
}
37
Step 7: clean setters
Example (BGK)
export default class Game {
_score = 0;
_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;
}
}
38
Step 8: clean old represent.
Example (BGK)
export default class Game {
_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;
}
}
39
Done
Example (Pattern)
// Painter should draw a square
class Painter {
draw() {
drawSquare()
}
}
40
Example (Pattern)
// The square size may change
class Painter {
draw(size: number) {
drawSquare(size)
}
}
41
Example (Pattern)
// The painter can draw also circles with size
class Painter {
draw(shape: String, size: number) {
if (shape === "Circle") drawCircle(size)
else drawSquare(size)
}
}
42
Example (Pattern)
// The painter can draw also stars
class Painter {
draw(shape: String, size: number) {
if (shape === "Star") drawStar(size)
else if (shape === "Circle") drawCircle(size)
else drawSquare(size)
}
}
43
This is not right, too complex if/switch
Example (Pattern)
// The painter can draw also circles with size
class Painter {
draw(shape: String, size: number) {
if (shape === "circle") drawCircle(size)
else drawSquare(size)
}
}
44
Example (Pattern)
interface Shape {
draw(size: number);
}
class Painter {
draw(shape: String, size: number) {
if (shape === "circle") drawCircle(size)
else drawSquare(size)
}
}
45
Example (Pattern)
interface Shape { ... }
class Circle implements Shape {
draw(size: number) {
drawCircle(size)
}
}
class Painter {
draw(shape: String, size: number) {
if (shape === "circle") drawCircle(size)
else drawSquare(size)
}
}
46
Example (Pattern)
interface Shape { ... }
class Circle implements Shape {
draw(size: number) {
drawCircle(size)
}
}
class Painter {
draw(shape: String, size: number) {
if (shape === "circle") new Circle.draw(size)
else drawSquare(size)
}
}
47
Example (Pattern)
interface Shape { ... }
class Circle implements Shape { ... }
class Square implements Shape {
draw(size: number) {
drawSquare(size)
}
}
class Painter {
draw(shape: String, size: number) {
if (shape === "circle") new Circle.draw(size)
else drawSquare(size)
}
}
48
Example (Pattern)
interface Shape { ... }
class Circle implements Shape { ... }
class Square implements Shape {
draw(size: number) {
drawSquare(size)
}
}
class Painter {
draw(shape: String, size: number) {
if (shape === "circle") new Circle.draw(size)
else new Square.draw(size)
}
}
49
Example (Pattern)
interface Shape { ... }
class Circle implements Shape { ... }
class Square implements Shape { ... }
const shapes = {
circle: new Circle(),
square: new Square(),
};
class Painter {
draw(shape: String, size: number) {
if (shape === "circle") new Circle.draw(size)
else new Circle.draw(size)
}
}
50
Example (Pattern)
interface Shape { ... }
class Circle implements Shape { ... }
class Square implements Shape { ... }
const shapes = { ... };
class Painter {
draw(shape: String, size: number) {
shapes[shape].draw(size)
}
}
51
Example (Pattern)
interface Shape { ... }
class Circle implements Shape { ... }
class Square implements Shape { ... }
const shapes = { ... };
class Painter {
draw(shape: String = "square", size: number) {
shapes[shape].draw(size)
}
}
52
Example (Pattern)
interface Shape { ... }
class Circle implements Shape { ... }
class Square implements Shape { ... }
class Star implements Shape {
draw(size) {}
}
const shapes = { ... };
class Painter {
draw(shape: String = "square", size: number) {
shapes[shape].draw(size);
}
}
53
Example (Pattern)
interface Shape { ... }
class Circle implements Shape { ... }
class Square implements Shape { ... }
class Star implements Shape {
draw(size) {}
}
const shapes = {
circle: new Circle(),
square: new Square(),
star: new Star(),
};
class Painter {
draw(shape: String = "square", size: number) {
shapes[shape].draw(size);
}
}
54
Example (Pattern)
interface Shape { ... }
class Circle implements Shape { ... }
class Square implements Shape { ... }
class Star implements Shape {
draw(size) {
drawStar(size)
}
}
const shapes = { ... };
class Painter {
draw(shape: String = "square", size: number) {
shapes[shape].draw(size);
}
}
55
Small Refactors
• Step by Step

• Always Green
56
Homework
• https://www.agilealliance.org/glossary/acceptance 

• https://www.agilealliance.org/glossary/unit-test 

• https://wiki.c2.com/?ArrangeActAssert 

• http://agileinaflash.blogspot.com/2009/02/first.html
57
The Two Disks Parable
58
TESTS CODE
Ad

More Related Content

What's hot (20)

JS and patterns
JS and patternsJS and patterns
JS and patterns
David Rodenas
 
Redux for ReactJS Programmers
Redux for ReactJS ProgrammersRedux for ReactJS Programmers
Redux for ReactJS Programmers
David Rodenas
 
Testing, Learning and Professionalism — 20171214
Testing, Learning and Professionalism — 20171214Testing, Learning and Professionalism — 20171214
Testing, Learning and Professionalism — 20171214
David Rodenas
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests
Tomek Kaczanowski
 
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
Tomek Kaczanowski
 
The secret unit testing tools no one ever told you about
The secret unit testing tools no one ever told you aboutThe secret unit testing tools no one ever told you about
The secret unit testing tools no one ever told you about
Dror Helper
 
GMock framework
GMock frameworkGMock framework
GMock framework
corehard_by
 
My java file
My java fileMy java file
My java file
Anamika Chauhan
 
Agile Android
Agile AndroidAgile Android
Agile Android
Godfrey Nolan
 
UA testing with Selenium and PHPUnit - PFCongres 2013
UA testing with Selenium and PHPUnit - PFCongres 2013UA testing with Selenium and PHPUnit - PFCongres 2013
UA testing with Selenium and PHPUnit - PFCongres 2013
Michelangelo van Dam
 
Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013
Michelangelo van Dam
 
Ensure code quality with vs2012
Ensure code quality with vs2012Ensure code quality with vs2012
Ensure code quality with vs2012
Sandeep Joshi
 
Developer Test - Things to Know
Developer Test - Things to KnowDeveloper Test - Things to Know
Developer Test - Things to Know
vilniusjug
 
201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing
wahyuseptiansyah
 
7
77
7
Vipul Khandelwal
 
We Make Debugging Sucks Less
We Make Debugging Sucks LessWe Make Debugging Sucks Less
We Make Debugging Sucks Less
Alon Fliess
 
Introduction to Software Testing
Introduction to Software TestingIntroduction to Software Testing
Introduction to Software Testing
Sergio Arroyo
 
Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016
Danny Preussler
 
Clojure in the Wild
Clojure in the WildClojure in the Wild
Clojure in the Wild
suitzero
 
Rechecking SharpDevelop: Any New Bugs?
Rechecking SharpDevelop: Any New Bugs?Rechecking SharpDevelop: Any New Bugs?
Rechecking SharpDevelop: Any New Bugs?
PVS-Studio
 
Redux for ReactJS Programmers
Redux for ReactJS ProgrammersRedux for ReactJS Programmers
Redux for ReactJS Programmers
David Rodenas
 
Testing, Learning and Professionalism — 20171214
Testing, Learning and Professionalism — 20171214Testing, Learning and Professionalism — 20171214
Testing, Learning and Professionalism — 20171214
David Rodenas
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests
Tomek Kaczanowski
 
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
Tomek Kaczanowski
 
The secret unit testing tools no one ever told you about
The secret unit testing tools no one ever told you aboutThe secret unit testing tools no one ever told you about
The secret unit testing tools no one ever told you about
Dror Helper
 
UA testing with Selenium and PHPUnit - PFCongres 2013
UA testing with Selenium and PHPUnit - PFCongres 2013UA testing with Selenium and PHPUnit - PFCongres 2013
UA testing with Selenium and PHPUnit - PFCongres 2013
Michelangelo van Dam
 
Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013
Michelangelo van Dam
 
Ensure code quality with vs2012
Ensure code quality with vs2012Ensure code quality with vs2012
Ensure code quality with vs2012
Sandeep Joshi
 
Developer Test - Things to Know
Developer Test - Things to KnowDeveloper Test - Things to Know
Developer Test - Things to Know
vilniusjug
 
201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing
wahyuseptiansyah
 
We Make Debugging Sucks Less
We Make Debugging Sucks LessWe Make Debugging Sucks Less
We Make Debugging Sucks Less
Alon Fliess
 
Introduction to Software Testing
Introduction to Software TestingIntroduction to Software Testing
Introduction to Software Testing
Sergio Arroyo
 
Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016
Danny Preussler
 
Clojure in the Wild
Clojure in the WildClojure in the Wild
Clojure in the Wild
suitzero
 
Rechecking SharpDevelop: Any New Bugs?
Rechecking SharpDevelop: Any New Bugs?Rechecking SharpDevelop: Any New Bugs?
Rechecking SharpDevelop: Any New Bugs?
PVS-Studio
 

Similar to ES3-2020-06 Test Driven Development (TDD) (20)

TDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD TechniquesTDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD Techniques
David Rodenas
 
A test framework out of the box - Geb for Web and mobile
A test framework out of the box - Geb for Web and mobileA test framework out of the box - Geb for Web and mobile
A test framework out of the box - Geb for Web and mobile
GlobalLogic Ukraine
 
The Ring programming language version 1.5.2 book - Part 7 of 181
The Ring programming language version 1.5.2 book - Part 7 of 181The Ring programming language version 1.5.2 book - Part 7 of 181
The Ring programming language version 1.5.2 book - Part 7 of 181
Mahmoud Samir Fayed
 
Django quickstart
Django quickstartDjango quickstart
Django quickstart
Marconi Moreto
 
An Introduction to Property Based Testing
An Introduction to Property Based TestingAn Introduction to Property Based Testing
An Introduction to Property Based Testing
C4Media
 
JavaScript Lessons 2023
JavaScript Lessons 2023JavaScript Lessons 2023
JavaScript Lessons 2023
Laurence Svekis ✔
 
Building l10n Payroll Structures from the Ground up
Building l10n Payroll Structures from the Ground upBuilding l10n Payroll Structures from the Ground up
Building l10n Payroll Structures from the Ground up
Odoo
 
Python Code Camp for Professionals 4/4
Python Code Camp for Professionals 4/4Python Code Camp for Professionals 4/4
Python Code Camp for Professionals 4/4
DEVCON
 
Groovy kind of test
Groovy kind of testGroovy kind of test
Groovy kind of test
OPITZ CONSULTING Deutschland
 
Groovy kind of test
Groovy kind of testGroovy kind of test
Groovy kind of test
Torsten Mandry
 
2013 DevFest Vienna - Bad Tests, Good Tests
2013 DevFest Vienna - Bad Tests, Good Tests2013 DevFest Vienna - Bad Tests, Good Tests
2013 DevFest Vienna - Bad Tests, Good Tests
Tomek Kaczanowski
 
The Ring programming language version 1.7 book - Part 47 of 196
The Ring programming language version 1.7 book - Part 47 of 196The Ring programming language version 1.7 book - Part 47 of 196
The Ring programming language version 1.7 book - Part 47 of 196
Mahmoud Samir Fayed
 
The Ring programming language version 1.3 book - Part 83 of 88
The Ring programming language version 1.3 book - Part 83 of 88The Ring programming language version 1.3 book - Part 83 of 88
The Ring programming language version 1.3 book - Part 83 of 88
Mahmoud Samir Fayed
 
Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing Strategies
CiaranMcNulty
 
The Ring programming language version 1.3 book - Part 30 of 88
The Ring programming language version 1.3 book - Part 30 of 88The Ring programming language version 1.3 book - Part 30 of 88
The Ring programming language version 1.3 book - Part 30 of 88
Mahmoud Samir Fayed
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test community
Kerry Buckley
 
Spicy javascript: Create your first Chrome extension for web analytics QA
Spicy javascript: Create your first Chrome extension for web analytics QASpicy javascript: Create your first Chrome extension for web analytics QA
Spicy javascript: Create your first Chrome extension for web analytics QA
Alban Gérôme
 
Acceptance Testing with Webrat
Acceptance Testing with WebratAcceptance Testing with Webrat
Acceptance Testing with Webrat
Luismi Cavallé
 
The Ring programming language version 1.8 book - Part 49 of 202
The Ring programming language version 1.8 book - Part 49 of 202The Ring programming language version 1.8 book - Part 49 of 202
The Ring programming language version 1.8 book - Part 49 of 202
Mahmoud Samir Fayed
 
MongoDB - Aggregation Pipeline
MongoDB - Aggregation PipelineMongoDB - Aggregation Pipeline
MongoDB - Aggregation Pipeline
Jason Terpko
 
TDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD TechniquesTDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD Techniques
David Rodenas
 
A test framework out of the box - Geb for Web and mobile
A test framework out of the box - Geb for Web and mobileA test framework out of the box - Geb for Web and mobile
A test framework out of the box - Geb for Web and mobile
GlobalLogic Ukraine
 
The Ring programming language version 1.5.2 book - Part 7 of 181
The Ring programming language version 1.5.2 book - Part 7 of 181The Ring programming language version 1.5.2 book - Part 7 of 181
The Ring programming language version 1.5.2 book - Part 7 of 181
Mahmoud Samir Fayed
 
An Introduction to Property Based Testing
An Introduction to Property Based TestingAn Introduction to Property Based Testing
An Introduction to Property Based Testing
C4Media
 
Building l10n Payroll Structures from the Ground up
Building l10n Payroll Structures from the Ground upBuilding l10n Payroll Structures from the Ground up
Building l10n Payroll Structures from the Ground up
Odoo
 
Python Code Camp for Professionals 4/4
Python Code Camp for Professionals 4/4Python Code Camp for Professionals 4/4
Python Code Camp for Professionals 4/4
DEVCON
 
2013 DevFest Vienna - Bad Tests, Good Tests
2013 DevFest Vienna - Bad Tests, Good Tests2013 DevFest Vienna - Bad Tests, Good Tests
2013 DevFest Vienna - Bad Tests, Good Tests
Tomek Kaczanowski
 
The Ring programming language version 1.7 book - Part 47 of 196
The Ring programming language version 1.7 book - Part 47 of 196The Ring programming language version 1.7 book - Part 47 of 196
The Ring programming language version 1.7 book - Part 47 of 196
Mahmoud Samir Fayed
 
The Ring programming language version 1.3 book - Part 83 of 88
The Ring programming language version 1.3 book - Part 83 of 88The Ring programming language version 1.3 book - Part 83 of 88
The Ring programming language version 1.3 book - Part 83 of 88
Mahmoud Samir Fayed
 
Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing Strategies
CiaranMcNulty
 
The Ring programming language version 1.3 book - Part 30 of 88
The Ring programming language version 1.3 book - Part 30 of 88The Ring programming language version 1.3 book - Part 30 of 88
The Ring programming language version 1.3 book - Part 30 of 88
Mahmoud Samir Fayed
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test community
Kerry Buckley
 
Spicy javascript: Create your first Chrome extension for web analytics QA
Spicy javascript: Create your first Chrome extension for web analytics QASpicy javascript: Create your first Chrome extension for web analytics QA
Spicy javascript: Create your first Chrome extension for web analytics QA
Alban Gérôme
 
Acceptance Testing with Webrat
Acceptance Testing with WebratAcceptance Testing with Webrat
Acceptance Testing with Webrat
Luismi Cavallé
 
The Ring programming language version 1.8 book - Part 49 of 202
The Ring programming language version 1.8 book - Part 49 of 202The Ring programming language version 1.8 book - Part 49 of 202
The Ring programming language version 1.8 book - Part 49 of 202
Mahmoud Samir Fayed
 
MongoDB - Aggregation Pipeline
MongoDB - Aggregation PipelineMongoDB - Aggregation Pipeline
MongoDB - Aggregation Pipeline
Jason Terpko
 
Ad

More from David Rodenas (16)

TDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDDTDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDD
David Rodenas
 
TDD CrashCourse Part1: Testing
TDD CrashCourse Part1: TestingTDD CrashCourse Part1: Testing
TDD CrashCourse Part1: Testing
David Rodenas
 
Be professional: We Rule the World
Be professional: We Rule the WorldBe professional: We Rule the World
Be professional: We Rule the World
David Rodenas
 
ES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game KataES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game Kata
David Rodenas
 
ES3-2020-05 Testing
ES3-2020-05 TestingES3-2020-05 Testing
ES3-2020-05 Testing
David Rodenas
 
Vespres
VespresVespres
Vespres
David Rodenas
 
Faster web pages
Faster web pagesFaster web pages
Faster web pages
David Rodenas
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for Programmers
David 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 work
David 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.1
David Rodenas
 
Freelance i Enginyeria
Freelance i EnginyeriaFreelance i Enginyeria
Freelance i Enginyeria
David 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 Decissions
David Rodenas
 
MVS: An angular MVC
MVS: An angular MVCMVS: An angular MVC
MVS: An angular MVC
David Rodenas
 
Mvc - Model: the great forgotten
Mvc - Model: the great forgottenMvc - Model: the great forgotten
Mvc - Model: the great forgotten
David Rodenas
 
(automatic) Testing: from business to university and back
(automatic) Testing: from business to university and back(automatic) Testing: from business to university and back
(automatic) Testing: from business to university and back
David Rodenas
 
Testing: ¿what, how, why?
Testing: ¿what, how, why?Testing: ¿what, how, why?
Testing: ¿what, how, why?
David Rodenas
 
TDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDDTDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDD
David Rodenas
 
TDD CrashCourse Part1: Testing
TDD CrashCourse Part1: TestingTDD CrashCourse Part1: Testing
TDD CrashCourse Part1: Testing
David Rodenas
 
Be professional: We Rule the World
Be professional: We Rule the WorldBe professional: We Rule the World
Be professional: We Rule the World
David Rodenas
 
ES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game KataES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game Kata
David Rodenas
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for Programmers
David 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 work
David 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.1
David Rodenas
 
Freelance i Enginyeria
Freelance i EnginyeriaFreelance i Enginyeria
Freelance i Enginyeria
David 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 Decissions
David Rodenas
 
Mvc - Model: the great forgotten
Mvc - Model: the great forgottenMvc - Model: the great forgotten
Mvc - Model: the great forgotten
David Rodenas
 
(automatic) Testing: from business to university and back
(automatic) Testing: from business to university and back(automatic) Testing: from business to university and back
(automatic) Testing: from business to university and back
David Rodenas
 
Testing: ¿what, how, why?
Testing: ¿what, how, why?Testing: ¿what, how, why?
Testing: ¿what, how, why?
David Rodenas
 
Ad

Recently uploaded (20)

Data Structures_Introduction to algorithms.pptx
Data Structures_Introduction to algorithms.pptxData Structures_Introduction to algorithms.pptx
Data Structures_Introduction to algorithms.pptx
RushaliDeshmukh2
 
Compiler Design Unit1 PPT Phases of Compiler.pptx
Compiler Design Unit1 PPT Phases of Compiler.pptxCompiler Design Unit1 PPT Phases of Compiler.pptx
Compiler Design Unit1 PPT Phases of Compiler.pptx
RushaliDeshmukh2
 
Reagent dosing (Bredel) presentation.pptx
Reagent dosing (Bredel) presentation.pptxReagent dosing (Bredel) presentation.pptx
Reagent dosing (Bredel) presentation.pptx
AlejandroOdio
 
ELectronics Boards & Product Testing_Shiju.pdf
ELectronics Boards & Product Testing_Shiju.pdfELectronics Boards & Product Testing_Shiju.pdf
ELectronics Boards & Product Testing_Shiju.pdf
Shiju Jacob
 
theory-slides-for react for beginners.pptx
theory-slides-for react for beginners.pptxtheory-slides-for react for beginners.pptx
theory-slides-for react for beginners.pptx
sanchezvanessa7896
 
Raish Khanji GTU 8th sem Internship Report.pdf
Raish Khanji GTU 8th sem Internship Report.pdfRaish Khanji GTU 8th sem Internship Report.pdf
Raish Khanji GTU 8th sem Internship Report.pdf
RaishKhanji
 
Introduction to FLUID MECHANICS & KINEMATICS
Introduction to FLUID MECHANICS &  KINEMATICSIntroduction to FLUID MECHANICS &  KINEMATICS
Introduction to FLUID MECHANICS & KINEMATICS
narayanaswamygdas
 
211421893-M-Tech-CIVIL-Structural-Engineering-pdf.pdf
211421893-M-Tech-CIVIL-Structural-Engineering-pdf.pdf211421893-M-Tech-CIVIL-Structural-Engineering-pdf.pdf
211421893-M-Tech-CIVIL-Structural-Engineering-pdf.pdf
inmishra17121973
 
Structural Response of Reinforced Self-Compacting Concrete Deep Beam Using Fi...
Structural Response of Reinforced Self-Compacting Concrete Deep Beam Using Fi...Structural Response of Reinforced Self-Compacting Concrete Deep Beam Using Fi...
Structural Response of Reinforced Self-Compacting Concrete Deep Beam Using Fi...
Journal of Soft Computing in Civil Engineering
 
π0.5: a Vision-Language-Action Model with Open-World Generalization
π0.5: a Vision-Language-Action Model with Open-World Generalizationπ0.5: a Vision-Language-Action Model with Open-World Generalization
π0.5: a Vision-Language-Action Model with Open-World Generalization
NABLAS株式会社
 
Development of MLR, ANN and ANFIS Models for Estimation of PCUs at Different ...
Development of MLR, ANN and ANFIS Models for Estimation of PCUs at Different ...Development of MLR, ANN and ANFIS Models for Estimation of PCUs at Different ...
Development of MLR, ANN and ANFIS Models for Estimation of PCUs at Different ...
Journal of Soft Computing in Civil Engineering
 
Smart_Storage_Systems_Production_Engineering.pptx
Smart_Storage_Systems_Production_Engineering.pptxSmart_Storage_Systems_Production_Engineering.pptx
Smart_Storage_Systems_Production_Engineering.pptx
rushikeshnavghare94
 
Introduction to Zoomlion Earthmoving.pptx
Introduction to Zoomlion Earthmoving.pptxIntroduction to Zoomlion Earthmoving.pptx
Introduction to Zoomlion Earthmoving.pptx
AS1920
 
DT REPORT by Tech titan GROUP to introduce the subject design Thinking
DT REPORT by Tech titan GROUP to introduce the subject design ThinkingDT REPORT by Tech titan GROUP to introduce the subject design Thinking
DT REPORT by Tech titan GROUP to introduce the subject design Thinking
DhruvChotaliya2
 
Oil-gas_Unconventional oil and gass_reseviours.pdf
Oil-gas_Unconventional oil and gass_reseviours.pdfOil-gas_Unconventional oil and gass_reseviours.pdf
Oil-gas_Unconventional oil and gass_reseviours.pdf
M7md3li2
 
Metal alkyne complexes.pptx in chemistry
Metal alkyne complexes.pptx in chemistryMetal alkyne complexes.pptx in chemistry
Metal alkyne complexes.pptx in chemistry
mee23nu
 
Compiler Design_Lexical Analysis phase.pptx
Compiler Design_Lexical Analysis phase.pptxCompiler Design_Lexical Analysis phase.pptx
Compiler Design_Lexical Analysis phase.pptx
RushaliDeshmukh2
 
AI-assisted Software Testing (3-hours tutorial)
AI-assisted Software Testing (3-hours tutorial)AI-assisted Software Testing (3-hours tutorial)
AI-assisted Software Testing (3-hours tutorial)
Vəhid Gəruslu
 
railway wheels, descaling after reheating and before forging
railway wheels, descaling after reheating and before forgingrailway wheels, descaling after reheating and before forging
railway wheels, descaling after reheating and before forging
Javad Kadkhodapour
 
"Boiler Feed Pump (BFP): Working, Applications, Advantages, and Limitations E...
"Boiler Feed Pump (BFP): Working, Applications, Advantages, and Limitations E..."Boiler Feed Pump (BFP): Working, Applications, Advantages, and Limitations E...
"Boiler Feed Pump (BFP): Working, Applications, Advantages, and Limitations E...
Infopitaara
 
Data Structures_Introduction to algorithms.pptx
Data Structures_Introduction to algorithms.pptxData Structures_Introduction to algorithms.pptx
Data Structures_Introduction to algorithms.pptx
RushaliDeshmukh2
 
Compiler Design Unit1 PPT Phases of Compiler.pptx
Compiler Design Unit1 PPT Phases of Compiler.pptxCompiler Design Unit1 PPT Phases of Compiler.pptx
Compiler Design Unit1 PPT Phases of Compiler.pptx
RushaliDeshmukh2
 
Reagent dosing (Bredel) presentation.pptx
Reagent dosing (Bredel) presentation.pptxReagent dosing (Bredel) presentation.pptx
Reagent dosing (Bredel) presentation.pptx
AlejandroOdio
 
ELectronics Boards & Product Testing_Shiju.pdf
ELectronics Boards & Product Testing_Shiju.pdfELectronics Boards & Product Testing_Shiju.pdf
ELectronics Boards & Product Testing_Shiju.pdf
Shiju Jacob
 
theory-slides-for react for beginners.pptx
theory-slides-for react for beginners.pptxtheory-slides-for react for beginners.pptx
theory-slides-for react for beginners.pptx
sanchezvanessa7896
 
Raish Khanji GTU 8th sem Internship Report.pdf
Raish Khanji GTU 8th sem Internship Report.pdfRaish Khanji GTU 8th sem Internship Report.pdf
Raish Khanji GTU 8th sem Internship Report.pdf
RaishKhanji
 
Introduction to FLUID MECHANICS & KINEMATICS
Introduction to FLUID MECHANICS &  KINEMATICSIntroduction to FLUID MECHANICS &  KINEMATICS
Introduction to FLUID MECHANICS & KINEMATICS
narayanaswamygdas
 
211421893-M-Tech-CIVIL-Structural-Engineering-pdf.pdf
211421893-M-Tech-CIVIL-Structural-Engineering-pdf.pdf211421893-M-Tech-CIVIL-Structural-Engineering-pdf.pdf
211421893-M-Tech-CIVIL-Structural-Engineering-pdf.pdf
inmishra17121973
 
π0.5: a Vision-Language-Action Model with Open-World Generalization
π0.5: a Vision-Language-Action Model with Open-World Generalizationπ0.5: a Vision-Language-Action Model with Open-World Generalization
π0.5: a Vision-Language-Action Model with Open-World Generalization
NABLAS株式会社
 
Smart_Storage_Systems_Production_Engineering.pptx
Smart_Storage_Systems_Production_Engineering.pptxSmart_Storage_Systems_Production_Engineering.pptx
Smart_Storage_Systems_Production_Engineering.pptx
rushikeshnavghare94
 
Introduction to Zoomlion Earthmoving.pptx
Introduction to Zoomlion Earthmoving.pptxIntroduction to Zoomlion Earthmoving.pptx
Introduction to Zoomlion Earthmoving.pptx
AS1920
 
DT REPORT by Tech titan GROUP to introduce the subject design Thinking
DT REPORT by Tech titan GROUP to introduce the subject design ThinkingDT REPORT by Tech titan GROUP to introduce the subject design Thinking
DT REPORT by Tech titan GROUP to introduce the subject design Thinking
DhruvChotaliya2
 
Oil-gas_Unconventional oil and gass_reseviours.pdf
Oil-gas_Unconventional oil and gass_reseviours.pdfOil-gas_Unconventional oil and gass_reseviours.pdf
Oil-gas_Unconventional oil and gass_reseviours.pdf
M7md3li2
 
Metal alkyne complexes.pptx in chemistry
Metal alkyne complexes.pptx in chemistryMetal alkyne complexes.pptx in chemistry
Metal alkyne complexes.pptx in chemistry
mee23nu
 
Compiler Design_Lexical Analysis phase.pptx
Compiler Design_Lexical Analysis phase.pptxCompiler Design_Lexical Analysis phase.pptx
Compiler Design_Lexical Analysis phase.pptx
RushaliDeshmukh2
 
AI-assisted Software Testing (3-hours tutorial)
AI-assisted Software Testing (3-hours tutorial)AI-assisted Software Testing (3-hours tutorial)
AI-assisted Software Testing (3-hours tutorial)
Vəhid Gəruslu
 
railway wheels, descaling after reheating and before forging
railway wheels, descaling after reheating and before forgingrailway wheels, descaling after reheating and before forging
railway wheels, descaling after reheating and before forging
Javad Kadkhodapour
 
"Boiler Feed Pump (BFP): Working, Applications, Advantages, and Limitations E...
"Boiler Feed Pump (BFP): Working, Applications, Advantages, and Limitations E..."Boiler Feed Pump (BFP): Working, Applications, Advantages, and Limitations E...
"Boiler Feed Pump (BFP): Working, Applications, Advantages, and Limitations E...
Infopitaara
 

ES3-2020-06 Test Driven Development (TDD)

  • 1. 06 Testing - TDD Enginyeria del Software 3 1 @drpicox — 2020
  • 2. Accounting • Accounting is a discipline that is in charge of studying, measuring and analyzing the assets and financial and economic situation of a company or organization, in order to facilitate decision-making within it and external control, presenting the information , previously registered, in a systematic and useful way for the different interested parties.
 
 —Wikipedia 2
  • 3. Double-entry bookkeping • At least two accounting entries are required to record each financial transaction: debit and credit. 3
  • 4. –Merriam-Webster dictionary “Discipline: training that corrects, molds, or perfects the mental faculties or moral character” 4
  • 5. Test Development Driven • The Three rules of TDD:
 1. You are not allowed to write any production code unless it is to make a failing unit test pass.
 2. You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
 3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test. 5 http://www.butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
  • 6. Stages of TDD 6 RED GREEN REFACTOR TEST CODE CLEAN Write production code until tests pass. Write tests until a test fails. Clean code while tests passes. Clean tests while tests passes. Clean ... ... YOU START HERE 30s loop
  • 7. Common Pitfalls (1/2) • Typical individual mistakes include: • forgetting to run tests frequently, • writing too many tests at once, • writing tests that are too large or coarse-grained, • writing overly trivial tests, for instance omitting assertions, • writing tests for trivial code, for instance accessors. 7
  • 8. Common Pitfalls (2/2) • Typical team mistakes include: • partial adoption: only a few developers on the team use TDD, • poor maintenance of the test suite: most commonly leading to a test suite with a prohibitively long running time, • abandoned test suite (i.e. seldom or never run): sometimes as a result of poor maintenance, sometimes as a result of team turnover. 8
  • 9. London vs Chicago TDD • London School of TDD: Mockists • use spies to verify implementation • higher coupling • Chicago School of TDD: Statists • depend on results, not on imlpementation details • our objective 9
  • 10. London Example import { add } from "math" import multiply from "./multiply" let log function addMock(a, b) { log.push(`${a}+${b}`) return add(a, b) } test("multiplies two numbers", () => { log = [] const result = multiply(3, 4, { add: addMock }) expect(log).toEqual("0+3", "3+3", "6+3", "9+3") expect(result).toEqual(12) }) 10
  • 11. Chicago Example import multiply from "./multiply" test("multiplies two numbers", () => { const result = multiply(3, 4) expect(result).toEqual(12) }) 11
  • 12. Craftsman Recipe • You already know how to create tests and do TDD • Probably you already do some kind of TDD manually • You just need to write it first • There are 5 steps to help you 12
  • 13. Step 1: First tests • Write first the test that gives you the excuse for writing the first code. 13 test("create a game", () => { const game = new Game() }) class Game {}
  • 14. Step 2: Progressing • You already test manually things before and after code • Write the test code that test that for you 14
  • 15. Step 2: Progressing // 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() }) 15
  • 16. Step 2: Progressing // 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") }) 16
  • 17. Step 2: Progressing // 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() }) 17
  • 18. Step 2: Progressing // 4: I want to know that clicking in search triggers fetch test("The search button makes a fetch from the service", async () => { const searchBox = getByPlaceholderText( container, "search" ) userEvent.type(searchBox, "apollo x") const searchButton = getByText(container, "search") searchButton.click() await fetchMock.expectGET("/api/v1/search?q=apollo%20x") }) 18
  • 19. Step 2: Progressing // 5: I want to know if there is the response area test("There is a response area after doing a search", 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).toBeInTheDocument() }) 19
  • 20. Step 2: Progressing // 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" ) }) 20
  • 21. Step 3: Remove UI use • Make test express your intention, not how to use the UI • Protect your tests from the UI changes 21
  • 22. Step 3: Remove UI use • Make test express your intention, not how to use the UI • Protect your tests from the UI changes 22
  • 23. Step 3: Remove UI use 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" ) }) 23
  • 24. Step 3: Remove UI use 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" ) }) 24
  • 25. Step 3: Remove UI use // __helpers__/ui.js export function search(container, text) { const searchBox = getByPlaceholderText( container, "search" ) userEvent.type(searchBox, text) const searchButton = getByText(container, "search") searchButton.click() } export async function findSearchResult(container) { const results = await findByTestId( container, "search-result" ) return results } 25
  • 26. Step 4: Refactor • Make test and code easy to read and understand 26 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" ) })
  • 27. Step 5: Business value • All tests should directly express requirements 27 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" ) })
  • 28. Bonus Step: Use tables • Refactor your test to accommodate tables 28 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) } )
  • 29. Refactors • Big Refactors • Small Refactors 29
  • 30. Big Refactors • Programmers always want to throw away the code and start over • They think the old code is a mess • They are probably wrong. 30 https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/ by Joel Spolsky It’s harder to read code than to write it.
  • 31. Small Refactors • Leverage on Tests: small change, test, small change, test, ... • Clean the code and adjust the architecture, slowly and firmly 31 REFACTOR CLEAN
  • 32. Small Refactors • 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. Moddify 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 32
  • 33. Example (BGK) export default class Game { _score = 0; roll(pins) { this._score += pins; } score() { return this._score; } } 33
  • 34. Example (BGK) export default class Game { _score = 0; _rolls = []; roll(pins) { this._score += pins; } score() { return this._score; } } 34 Step 1: new representation
  • 35. Example (BGK) export default class Game { _score = 0; _rolls = []; roll(pins) { this._score += pins; this._rolls.push(pins); } score() { return this._score; } } 35 Step 2: setters
  • 36. Example (BGK) 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; } } 36 Step 4: getters
  • 37. Example (BGK) 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; } } 37 Step 7: clean setters
  • 38. Example (BGK) export default class Game { _score = 0; _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; } } 38 Step 8: clean old represent.
  • 39. Example (BGK) export default class Game { _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; } } 39 Done
  • 40. Example (Pattern) // Painter should draw a square class Painter { draw() { drawSquare() } } 40
  • 41. Example (Pattern) // The square size may change class Painter { draw(size: number) { drawSquare(size) } } 41
  • 42. Example (Pattern) // The painter can draw also circles with size class Painter { draw(shape: String, size: number) { if (shape === "Circle") drawCircle(size) else drawSquare(size) } } 42
  • 43. Example (Pattern) // The painter can draw also stars class Painter { draw(shape: String, size: number) { if (shape === "Star") drawStar(size) else if (shape === "Circle") drawCircle(size) else drawSquare(size) } } 43 This is not right, too complex if/switch
  • 44. Example (Pattern) // The painter can draw also circles with size class Painter { draw(shape: String, size: number) { if (shape === "circle") drawCircle(size) else drawSquare(size) } } 44
  • 45. Example (Pattern) interface Shape { draw(size: number); } class Painter { draw(shape: String, size: number) { if (shape === "circle") drawCircle(size) else drawSquare(size) } } 45
  • 46. Example (Pattern) interface Shape { ... } class Circle implements Shape { draw(size: number) { drawCircle(size) } } class Painter { draw(shape: String, size: number) { if (shape === "circle") drawCircle(size) else drawSquare(size) } } 46
  • 47. Example (Pattern) interface Shape { ... } class Circle implements Shape { draw(size: number) { drawCircle(size) } } class Painter { draw(shape: String, size: number) { if (shape === "circle") new Circle.draw(size) else drawSquare(size) } } 47
  • 48. Example (Pattern) interface Shape { ... } class Circle implements Shape { ... } class Square implements Shape { draw(size: number) { drawSquare(size) } } class Painter { draw(shape: String, size: number) { if (shape === "circle") new Circle.draw(size) else drawSquare(size) } } 48
  • 49. Example (Pattern) interface Shape { ... } class Circle implements Shape { ... } class Square implements Shape { draw(size: number) { drawSquare(size) } } class Painter { draw(shape: String, size: number) { if (shape === "circle") new Circle.draw(size) else new Square.draw(size) } } 49
  • 50. Example (Pattern) interface Shape { ... } class Circle implements Shape { ... } class Square implements Shape { ... } const shapes = { circle: new Circle(), square: new Square(), }; class Painter { draw(shape: String, size: number) { if (shape === "circle") new Circle.draw(size) else new Circle.draw(size) } } 50
  • 51. Example (Pattern) interface Shape { ... } class Circle implements Shape { ... } class Square implements Shape { ... } const shapes = { ... }; class Painter { draw(shape: String, size: number) { shapes[shape].draw(size) } } 51
  • 52. Example (Pattern) interface Shape { ... } class Circle implements Shape { ... } class Square implements Shape { ... } const shapes = { ... }; class Painter { draw(shape: String = "square", size: number) { shapes[shape].draw(size) } } 52
  • 53. Example (Pattern) interface Shape { ... } class Circle implements Shape { ... } class Square implements Shape { ... } class Star implements Shape { draw(size) {} } const shapes = { ... }; class Painter { draw(shape: String = "square", size: number) { shapes[shape].draw(size); } } 53
  • 54. Example (Pattern) interface Shape { ... } class Circle implements Shape { ... } class Square implements Shape { ... } class Star implements Shape { draw(size) {} } const shapes = { circle: new Circle(), square: new Square(), star: new Star(), }; class Painter { draw(shape: String = "square", size: number) { shapes[shape].draw(size); } } 54
  • 55. Example (Pattern) interface Shape { ... } class Circle implements Shape { ... } class Square implements Shape { ... } class Star implements Shape { draw(size) { drawStar(size) } } const shapes = { ... }; class Painter { draw(shape: String = "square", size: number) { shapes[shape].draw(size); } } 55
  • 56. Small Refactors • Step by Step • Always Green 56
  • 57. Homework • https://www.agilealliance.org/glossary/acceptance • https://www.agilealliance.org/glossary/unit-test • https://wiki.c2.com/?ArrangeActAssert • http://agileinaflash.blogspot.com/2009/02/first.html 57
  • 58. The Two Disks Parable 58 TESTS CODE