SlideShare une entreprise Scribd logo
1  sur  96
Télécharger pour lire hors ligne
Old Solutions
to
New Testing Problems
Josh Justice
1 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
2 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
JavaScript test tooling
has improved a lot.
3 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
The problem now:
Test Maintainability
4 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
How can we learn how
to write more
maintainable tests?
5 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
6 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
"Well actually,
in Ruby we write
tests like this—"
7 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
8 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
PATTERNS
9 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
10 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Five Patterns
11 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Takeaways
1. New testing approaches
2. Clearer explanation of the benefits
3. Shared language and support
12 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
!
"Code Smells"
13 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
"Code Smells"
⚠
Warning Signs
14 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
115 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
import formatAddress from '../formatAddress';
import addresses from '../__sampleData__/addresses';
describe('formatAddress', () => {
it('formats addresses correctly', () => {
let expectedResult;
for (const address of addresses) {
if (address.street2) {
expectedResult = `${address.street1}
${address.street2}
${address.city}, ${address.province} ${address.postalCode}`;
} else {
expectedResult = `${address.street1}
${address.city}, ${address.province} ${address.postalCode}`;
}
expect(formatAddress(address)).toEqual(expectedResult);
}
});
});
16 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Problems
• Tests can be hard to understand
• Tests might have a bug, and you don't test your tests
• If test data changes, not all cases might be executed
17 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Flexible Test
18 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Flexible Test
"Using conditional logic to reuse a single test to verify several different
cases."
19 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Solution: Simple Tests
Split the tests into simpler cases, controlling for specific situations.
20 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('formats an address with two lines correctly', () => {
const address = addresses[0];
const expectedResult = `${address.street1}
${address.street2}
${address.city}, ${address.province} ${address.postalCode}`;
expect(formatAddress(address)).toEqual(expectedResult);
});
21 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('formats an address with one line correctly', () => {
const address = addresses[1];
const expectedResult = `${address.street1}
${address.city}, ${address.province} ${address.postalCode}`;
expect(formatAddress(address)).toEqual(expectedResult);
});
22 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Warning Sign:
⚠
Flexible Test
Solution:
Simple Tests
23 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
224 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
import formatAddress from '../formatAddress';
import addresses from '../__sampleData__/addresses';
describe('formatAddress', () => {
it('formats an address with one line correctly', () => {
const address = addresses[1];
const expectedResult = `${address.street1}
${address.city}, ${address.province} ${address.postalCode}`;
expect(formatAddress(address)).toEqual(expectedResult);
});
});
25 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
import formatAddress from '../formatAddress';
import addresses from '../__sampleData__/addresses';
describe('formatAddress', () => {
it('formats an address with one line correctly', () => {
const address = addresses[1];
const expectedResult = `${address.street1}
${address.city}, ${address.province} ${address.postalCode}`;
expect(formatAddress(address)).toEqual(expectedResult);
});
});
26 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Problems
• Can't see the data relevant to what's being tested, have to look in
another file
• Test harder to understand, easier for bugs to sneak through
• Coupled to shared test data; if it changes, test could break or give a
false positive
27 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Mystery Guest
28 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Mystery Guest
“The test reader is not able to see the cause and effect between
fixture and verification logic because part of it is done outside the
Test Method.”
29 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Mystery Guest
“The test reader is not able to see the cause and effect between
FIXTURE and verification logic because part of it is done outside the
Test Method.”
30 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Fixture
“everything we need in place to exercise the [production code]”...“the
pre-conditions of the test”
31 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Shared Fixture
“…reusing the same fixture for several or many tests.”
32 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Fresh Fixture
“Each test constructs its own brand-new test fixture for its own
private use.”
33 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Mystery Guest
“The test reader is not able to see the cause and effect between fixture
and verification logic because part of it is done outside the Test
Method.”
34 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Solution: set up the data
closer to the test
Several possible approaches using Fresh Fixtures
35 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Approach 1: In-Line Setup
“Each Test Method creates its own Fresh Fixture by [building] exactly
the test fixture it requires.”
36 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('formats an address with one line correctly', () => {
const address = {
street1: '101 College Street',
city: 'Toronto',
province: 'ON',
postalCode: 'M5G 1L7'
};
const expectedResult = `${address.street1}
${address.city}, ${address.province} ${address.postalCode}`;
expect(formatAddress(address)).toEqual(expectedResult);
});
37 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Approach 2: Delegated Setup
38 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Approach 2: Delegated Setup
39 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Approach 2: Delegated Setup
“Each Test Method creates its own Fresh Fixture by calling Creation
Methods from within the Test Methods.”
40 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
function createAddress({ hasStreet2 = false }) {
const address = {
street1: '101 College Street',
city: 'Toronto',
province: 'ON',
postalCode: 'M5G 1L7'
};
if (hasStreet2) {
address.street2 = 'Suite 123';
}
return address;
};
41 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('formats an address with one line correctly', () => {
const address = createAddress({ hasStreet2: false });
const expectedResult = `${address.street1}
${address.city}, ${address.province} ${address.postalCode}`;
expect(formatAddress(address)).toEqual(expectedResult);
});
42 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('formats an address with two lines correctly', () => {
const address = createAddress({ hasStreet2: true });
const expectedResult = `${address.street1}
${address.street2}
${address.city}, ${address.province} ${address.postalCode}`;
expect(formatAddress(address)).toEqual(expectedResult);
});
43 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Approach 3: Implicit Setup
“We build the test fixture common to several tests in the setUp
method."
44 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
let address;
beforeEach(() => {
address = {
street1: '101 College Street',
city: 'Toronto',
province: 'ON',
postalCode: 'M5G 1L7'
};
});
45 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('formats an address with one line correctly', () => {
const expectedResult = `${address.street1}
${address.city}, ${address.province} ${address.postalCode}`;
expect(formatAddress(address)).toEqual(expectedResult);
});
46 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('formats an address with two lines correctly', () => {
address.street2 = 'Apt. 317';
const expectedResult = `${address.street1}
${address.street2}
${address.city}, ${address.province} ${address.postalCode}`;
expect(formatAddress(address)).toEqual(expectedResult);
});
47 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Mystery Guest
Solutions:
1. In-Line Setup
2. Delegated Setup
3. Implicit Setup
48 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
349 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('formats an address correctly', () => {
const address = {
firstName: 'Sally',
lastName: 'Smith',
street1: '80 Spanida Avenue',
street2: '4th Floor',
city: 'Toronto',
province: 'ON',
postalCode: 'M5V 2J4',
country: 'CA'
};
const expectedResult = `${address.street1}
${address.street2}
${address.city}, ${address.province} ${address.postalCode}`;
expect(formatAddress(address)).toEqual(expectedResult);
});
50 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Problems
• Hard to see which fields matter and which don't
• Tests get long
51 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Irrelevant Information
52 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Irrelevant Information
“The test exposes a lot of irrelevant details about the fixture that
distract the test reader from what really affects the behavior of the
[system under test].”
53 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
General Fixture
“The test builds or references a larger fixture than is needed to verify
the functionality in question.”
54 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Solution 1: Minimal Fixture
“We use the smallest and simplest fixture possible for each test.”
55 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('formats an address correctly', () => {
const address = {
- firstName: 'Sally',
- lastName: 'Smith',
street1: '80 Spanida Avenue',
street2: '4th Floor',
city: 'Toronto',
province: 'ON',
postalCode: 'M5V 2J4',
- country: 'CA'
};
56 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('formats an address correctly', () => {
const address = {
street1: '80 Spanida Avenue',
street2: '4th Floor',
city: 'Toronto',
province: 'ON',
postalCode: 'M5V 2J4'
};
57 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
What if that data is still
needed for the code to run?
• Type verification
• Class instance requiring constructor args
• Fields validated by code unrelated to the test
58 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Solution 2: Parameterized
Creation Method
“We set up the test fixture by calling methods that hide the mechanics
of building ready-to-use objects behind Intent-Revealing Names.”
“A Parameterized Creation Method allows the test to pass in some
attributes to be used in the creation of the object. In such a case, we
should pass only those attributes that are expected to affect…the
test's outcome”
59 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
const defaultAddress = {
firstName: 'Sally',
lastName: 'Smith',
street1: '80 Spanida Avenue',
street2: '4th Floor',
city: 'Toronto',
province: 'ON',
postalCode: 'M5V 2J4',
country: 'CA'
};
function createAddress(overrides = {}) {
return {
...defaultAddress,
...overrides
};
};
60 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('formats an address correctly', () => {
const address = createAddress({
street1: '80 Spanida Avenue',
street2: '4th Floor',
city: 'Toronto',
province: 'ON',
postalCode: 'M5V 2J4'
});
const expectedResult = `${address.street1}
${address.street2}
${address.city}, ${address.province} ${address.postalCode}`;
expect(formatAddress(address)).toEqual(expectedResult);
});
61 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Solution 3: Test Data
Creation Libraries
62 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Test Data Bot
!
const { build, sequence } = require('test-data-bot')
const addressBuilder = build('address').fields({
street1: '80 Spanida Avenue',
street2: sequence(x => `Suite ${x}`),
city: 'Toronto',
province: 'ON',
postalCode: 'M5V 2J4',
})
63 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Test Data Bot
!
const user = addressBuilder({ street2: null })
64 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Irrelevant Information
Solutions:
1. Minimal Fixture
2. Parameterized Creation Method
3. Test Data Creation Library
65 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
466 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
import totalOrder from '../totalOrder';
import orders from '../__sampleData__/orders';
describe('totalOrder', () => {
it('calculates the correct total values when there are no line items', () => {
const order = orders[0];
order.lines = [];
const totalValues = totalOrder(order);
expect(totalValues.subtotal).toEqual(0);
expect(totalValues.tax).toEqual(0);
expect(totalValues.total).toEqual(0);
});
67 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('calculates the correct total values', () => {
const order = orders[0];
const totalValues = totalOrder(order);
expect(totalValues.subtotal).toEqual(7);
expect(totalValues.tax).toBeCloseTo(1.05);
expect(totalValues.total).toBeCloseTo(8.05);
});
});
68 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Interacting Tests
69 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Interacting Tests
"Tests depend on other tests in some way…[for example,] a test can be
run as part of a suite but cannot be run by itself"
In our case, a test can be run by itself but cannot be run as part of a
suite.
70 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Shared Fixture
71 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Solution: Fresh Fixture
72 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Solution: Fresh Fixture
“Each test constructs its own brand-new test fixture for its own
private use.”
73 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('calculates the correct total values when there are no line items', () => {
const order = _.cloneDeep(orders[0]);
order.lines = [];
const totalValues = totalOrder(order);
expect(totalValues.subtotal).toEqual(0);
expect(totalValues.tax).toEqual(0);
expect(totalValues.total).toEqual(0);
});
74 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('calculates the correct total values', () => {
const order = _.cloneDeep(orders[0]);
const totalValues = totalOrder(order);
expect(totalValues.subtotal).toEqual(7);
expect(totalValues.tax).toBeCloseTo(1.05);
expect(totalValues.total).toBeCloseTo(8.05);
});
});
75 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Warning Sign:
⚠
Interacting Tests
Solution:
Fresh Fixture
76 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
577 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
const TAX_PERCENT = 0.15;
function totalOrder(order) {
const lineTotals = order.lines.map(line => (
line.pricePerItem * line.quantity
));
const subtotal = lineTotals.reduce((acc, val) => acc + val, 0);
const tax = subtotal * TAX_PERCENT;
const total = subtotal + tax;
return { subtotal, tax, total };
}
78 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
describe('totalOrder', () => {
it('calculates the correct total values', () => {
const order = {
lines: [
{
pricePerItem: 5.99,
quantity: 3
},
{
pricePerItem: 7.99,
quantity: 4
}
]
};
79 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
const lineTotals = order.lines.map(
line => line.pricePerItem * line.quantity
);
const subtotal = lineTotals.reduce((acc, val) => acc + val);
const tax = subtotal * 0.15;
const total = subtotal + tax;
const totalValues = totalOrder(order);
expect(totalValues.subtotal).toEqual(subtotal);
expect(totalValues.tax).toBeCloseTo(tax);
expect(totalValues.total).toBeCloseTo(total);
});
});
80 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Problems
• If the logic is wrong in one place, it's wrong in both. Is it really
testing?
• Doesn't let you see the intended result at a glance
81 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Production Logic in Test
82 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
⚠
Production Logic in Test
“[If we] use a Calculated Value based on the inputs…we find ourselves
replicating the expected [production] logic inside our test to calculate
the expected values for assertions.”
83 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Solution: Hard-Coded
Test Data
84 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
it('calculates the correct total values', () => {
const order = {
lines: [
{
pricePerItem: 2,
quantity: 2
},
{
pricePerItem: 3,
quantity: 1
}
]
};
const totalValues = totalOrder(order);
expect(totalValues.subtotal).toEqual(7);
expect(totalValues.tax).toBeCloseTo(1.05);
expect(totalValues.total).toBeCloseTo(8.05);
});
85 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Solution: Hard-Coded
Test Data
86 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Solution: Hard-Coded
Test Data
!
87 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Warning Sign
⚠
Production Logic in Test
Solution
Hard-Coded Test Data
88 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Review: Test Patterns
1. Flexible Test → Simple Tests
2. Mystery Guest → In-Line Setup
3. Irrelevant Information → Minimal Fixture
4. Interacting Tests → Fresh Fixture
5. Production Logic in Test → Hard-Coded Test Data
89 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Takeaways
90 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
91 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Let's talk about test
patterns!
92 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Let's talk about test
patterns!
And let's use shared
language!
93 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
The deeper takeaway…
94 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
Let's connect people
with our rich testing
history.
95 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
@CodingItWrong
jjustice@bignerdranch.com
Photos: https://unsplash.com/collections/
8294370/old-solutions-talk
96 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong

Contenu connexe

Similaire à Old Solutions to New Testing Problems

Salesforce interview preparation toolkit formula and validation rules in sale...
Salesforce interview preparation toolkit formula and validation rules in sale...Salesforce interview preparation toolkit formula and validation rules in sale...
Salesforce interview preparation toolkit formula and validation rules in sale...Amit Sharma
 
ES3-2020-07 Testing techniques
ES3-2020-07 Testing techniquesES3-2020-07 Testing techniques
ES3-2020-07 Testing techniquesDavid Rodenas
 
An introduction to Competitive Programming
An introduction to Competitive ProgrammingAn introduction to Competitive Programming
An introduction to Competitive ProgrammingGaurav Agarwal
 
Name _______________________________ Class time __________.docx
Name _______________________________    Class time __________.docxName _______________________________    Class time __________.docx
Name _______________________________ Class time __________.docxrosemarybdodson23141
 
Excuse me, sir, do you have a moment to talk about tests in Kotlin
Excuse me, sir, do you have a moment to talk about tests in KotlinExcuse me, sir, do you have a moment to talk about tests in Kotlin
Excuse me, sir, do you have a moment to talk about tests in Kotlinleonsabr
 
Investigating the Quality Aspects of Crowd-Sourced Developer Forum: A Case St...
Investigating the Quality Aspects of Crowd-Sourced Developer Forum: A Case St...Investigating the Quality Aspects of Crowd-Sourced Developer Forum: A Case St...
Investigating the Quality Aspects of Crowd-Sourced Developer Forum: A Case St...University of Saskatchewan
 
White-box Unit Test Generation with Microsoft IntelliTest
White-box Unit Test Generation with Microsoft IntelliTestWhite-box Unit Test Generation with Microsoft IntelliTest
White-box Unit Test Generation with Microsoft IntelliTestDávid Honfi
 
Test-Driven Development in React with Cypress
Test-Driven Development in React with CypressTest-Driven Development in React with Cypress
Test-Driven Development in React with CypressJosh Justice
 

Similaire à Old Solutions to New Testing Problems (11)

Salesforce interview preparation toolkit formula and validation rules in sale...
Salesforce interview preparation toolkit formula and validation rules in sale...Salesforce interview preparation toolkit formula and validation rules in sale...
Salesforce interview preparation toolkit formula and validation rules in sale...
 
ES3-2020-07 Testing techniques
ES3-2020-07 Testing techniquesES3-2020-07 Testing techniques
ES3-2020-07 Testing techniques
 
An introduction to Competitive Programming
An introduction to Competitive ProgrammingAn introduction to Competitive Programming
An introduction to Competitive Programming
 
Gate-Cs 1993
Gate-Cs 1993Gate-Cs 1993
Gate-Cs 1993
 
Name _______________________________ Class time __________.docx
Name _______________________________    Class time __________.docxName _______________________________    Class time __________.docx
Name _______________________________ Class time __________.docx
 
Rspec
RspecRspec
Rspec
 
Excuse me, sir, do you have a moment to talk about tests in Kotlin
Excuse me, sir, do you have a moment to talk about tests in KotlinExcuse me, sir, do you have a moment to talk about tests in Kotlin
Excuse me, sir, do you have a moment to talk about tests in Kotlin
 
Investigating the Quality Aspects of Crowd-Sourced Developer Forum: A Case St...
Investigating the Quality Aspects of Crowd-Sourced Developer Forum: A Case St...Investigating the Quality Aspects of Crowd-Sourced Developer Forum: A Case St...
Investigating the Quality Aspects of Crowd-Sourced Developer Forum: A Case St...
 
White-box Unit Test Generation with Microsoft IntelliTest
White-box Unit Test Generation with Microsoft IntelliTestWhite-box Unit Test Generation with Microsoft IntelliTest
White-box Unit Test Generation with Microsoft IntelliTest
 
16May_ICSE_MIP_APR_2023.pptx
16May_ICSE_MIP_APR_2023.pptx16May_ICSE_MIP_APR_2023.pptx
16May_ICSE_MIP_APR_2023.pptx
 
Test-Driven Development in React with Cypress
Test-Driven Development in React with CypressTest-Driven Development in React with Cypress
Test-Driven Development in React with Cypress
 

Plus de Josh Justice

Effective Detox Testing - React Advanced 2023
Effective Detox Testing - React Advanced 2023Effective Detox Testing - React Advanced 2023
Effective Detox Testing - React Advanced 2023Josh Justice
 
Designing Effective Tests with React Testing Library - React Summit 2023
Designing Effective Tests with React Testing Library - React Summit 2023Designing Effective Tests with React Testing Library - React Summit 2023
Designing Effective Tests with React Testing Library - React Summit 2023Josh Justice
 
Testing React Native Apps - Chain React 2023
Testing React Native Apps - Chain React 2023Testing React Native Apps - Chain React 2023
Testing React Native Apps - Chain React 2023Josh Justice
 
Designing Effective Tests with React Testing Library - React Day Berlin 2022
Designing Effective Tests with React Testing Library - React Day Berlin 2022Designing Effective Tests with React Testing Library - React Day Berlin 2022
Designing Effective Tests with React Testing Library - React Day Berlin 2022Josh Justice
 
Building for Mobile and Web with Expo - React Day Berlin 2022
Building for Mobile and Web with Expo - React Day Berlin 2022Building for Mobile and Web with Expo - React Day Berlin 2022
Building for Mobile and Web with Expo - React Day Berlin 2022Josh Justice
 
Intro to React Native Testing Library
Intro to React Native Testing LibraryIntro to React Native Testing Library
Intro to React Native Testing LibraryJosh Justice
 
Building for Mobile and Web with Expo - React Advanced London 2022
Building for Mobile and Web with Expo - React Advanced London 2022Building for Mobile and Web with Expo - React Advanced London 2022
Building for Mobile and Web with Expo - React Advanced London 2022Josh Justice
 
Getting Better All the Time: How to Escape Bad Code
Getting Better All the Time: How to Escape Bad CodeGetting Better All the Time: How to Escape Bad Code
Getting Better All the Time: How to Escape Bad CodeJosh Justice
 
Sustainable Learning - ReactATL Jan 2022
Sustainable Learning - ReactATL Jan 2022Sustainable Learning - ReactATL Jan 2022
Sustainable Learning - ReactATL Jan 2022Josh Justice
 
Building an App for Mobile and Web with Expo
Building an App for Mobile and Web with ExpoBuilding an App for Mobile and Web with Expo
Building an App for Mobile and Web with ExpoJosh Justice
 
User-Modifiable Software: Smalltalk and HyperCard
User-Modifiable Software: Smalltalk and HyperCardUser-Modifiable Software: Smalltalk and HyperCard
User-Modifiable Software: Smalltalk and HyperCardJosh Justice
 
Practical Accessibility (A11y)
Practical Accessibility (A11y)Practical Accessibility (A11y)
Practical Accessibility (A11y)Josh Justice
 
Test-Driven Development in Vue with Cypress
Test-Driven Development in Vue with CypressTest-Driven Development in Vue with Cypress
Test-Driven Development in Vue with CypressJosh Justice
 
Newbie's Guide to Contributing to Babel
Newbie's Guide to Contributing to BabelNewbie's Guide to Contributing to Babel
Newbie's Guide to Contributing to BabelJosh Justice
 
Outside-in Testing in Vue with Cypress
Outside-in Testing in Vue with CypressOutside-in Testing in Vue with Cypress
Outside-in Testing in Vue with CypressJosh Justice
 

Plus de Josh Justice (15)

Effective Detox Testing - React Advanced 2023
Effective Detox Testing - React Advanced 2023Effective Detox Testing - React Advanced 2023
Effective Detox Testing - React Advanced 2023
 
Designing Effective Tests with React Testing Library - React Summit 2023
Designing Effective Tests with React Testing Library - React Summit 2023Designing Effective Tests with React Testing Library - React Summit 2023
Designing Effective Tests with React Testing Library - React Summit 2023
 
Testing React Native Apps - Chain React 2023
Testing React Native Apps - Chain React 2023Testing React Native Apps - Chain React 2023
Testing React Native Apps - Chain React 2023
 
Designing Effective Tests with React Testing Library - React Day Berlin 2022
Designing Effective Tests with React Testing Library - React Day Berlin 2022Designing Effective Tests with React Testing Library - React Day Berlin 2022
Designing Effective Tests with React Testing Library - React Day Berlin 2022
 
Building for Mobile and Web with Expo - React Day Berlin 2022
Building for Mobile and Web with Expo - React Day Berlin 2022Building for Mobile and Web with Expo - React Day Berlin 2022
Building for Mobile and Web with Expo - React Day Berlin 2022
 
Intro to React Native Testing Library
Intro to React Native Testing LibraryIntro to React Native Testing Library
Intro to React Native Testing Library
 
Building for Mobile and Web with Expo - React Advanced London 2022
Building for Mobile and Web with Expo - React Advanced London 2022Building for Mobile and Web with Expo - React Advanced London 2022
Building for Mobile and Web with Expo - React Advanced London 2022
 
Getting Better All the Time: How to Escape Bad Code
Getting Better All the Time: How to Escape Bad CodeGetting Better All the Time: How to Escape Bad Code
Getting Better All the Time: How to Escape Bad Code
 
Sustainable Learning - ReactATL Jan 2022
Sustainable Learning - ReactATL Jan 2022Sustainable Learning - ReactATL Jan 2022
Sustainable Learning - ReactATL Jan 2022
 
Building an App for Mobile and Web with Expo
Building an App for Mobile and Web with ExpoBuilding an App for Mobile and Web with Expo
Building an App for Mobile and Web with Expo
 
User-Modifiable Software: Smalltalk and HyperCard
User-Modifiable Software: Smalltalk and HyperCardUser-Modifiable Software: Smalltalk and HyperCard
User-Modifiable Software: Smalltalk and HyperCard
 
Practical Accessibility (A11y)
Practical Accessibility (A11y)Practical Accessibility (A11y)
Practical Accessibility (A11y)
 
Test-Driven Development in Vue with Cypress
Test-Driven Development in Vue with CypressTest-Driven Development in Vue with Cypress
Test-Driven Development in Vue with Cypress
 
Newbie's Guide to Contributing to Babel
Newbie's Guide to Contributing to BabelNewbie's Guide to Contributing to Babel
Newbie's Guide to Contributing to Babel
 
Outside-in Testing in Vue with Cypress
Outside-in Testing in Vue with CypressOutside-in Testing in Vue with Cypress
Outside-in Testing in Vue with Cypress
 

Dernier

WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...masabamasaba
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburgmasabamasaba
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Bert Jan Schrijver
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyviewmasabamasaba
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...masabamasaba
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationJuha-Pekka Tolvanen
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfonteinmasabamasaba
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...Jittipong Loespradit
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...chiefasafspells
 

Dernier (20)

WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security Program
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 

Old Solutions to New Testing Problems

  • 1. Old Solutions to New Testing Problems Josh Justice 1 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 2. 2 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 3. JavaScript test tooling has improved a lot. 3 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 4. The problem now: Test Maintainability 4 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 5. How can we learn how to write more maintainable tests? 5 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 6. 6 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 7. "Well actually, in Ruby we write tests like this—" 7 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 8. 8 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 9. PATTERNS 9 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 10. 10 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 11. Five Patterns 11 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 12. Takeaways 1. New testing approaches 2. Clearer explanation of the benefits 3. Shared language and support 12 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 13. ! "Code Smells" 13 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 14. "Code Smells" ⚠ Warning Signs 14 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 15. 115 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 16. import formatAddress from '../formatAddress'; import addresses from '../__sampleData__/addresses'; describe('formatAddress', () => { it('formats addresses correctly', () => { let expectedResult; for (const address of addresses) { if (address.street2) { expectedResult = `${address.street1} ${address.street2} ${address.city}, ${address.province} ${address.postalCode}`; } else { expectedResult = `${address.street1} ${address.city}, ${address.province} ${address.postalCode}`; } expect(formatAddress(address)).toEqual(expectedResult); } }); }); 16 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 17. Problems • Tests can be hard to understand • Tests might have a bug, and you don't test your tests • If test data changes, not all cases might be executed 17 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 18. ⚠ Flexible Test 18 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 19. ⚠ Flexible Test "Using conditional logic to reuse a single test to verify several different cases." 19 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 20. Solution: Simple Tests Split the tests into simpler cases, controlling for specific situations. 20 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 21. it('formats an address with two lines correctly', () => { const address = addresses[0]; const expectedResult = `${address.street1} ${address.street2} ${address.city}, ${address.province} ${address.postalCode}`; expect(formatAddress(address)).toEqual(expectedResult); }); 21 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 22. it('formats an address with one line correctly', () => { const address = addresses[1]; const expectedResult = `${address.street1} ${address.city}, ${address.province} ${address.postalCode}`; expect(formatAddress(address)).toEqual(expectedResult); }); 22 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 23. Warning Sign: ⚠ Flexible Test Solution: Simple Tests 23 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 24. 224 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 25. import formatAddress from '../formatAddress'; import addresses from '../__sampleData__/addresses'; describe('formatAddress', () => { it('formats an address with one line correctly', () => { const address = addresses[1]; const expectedResult = `${address.street1} ${address.city}, ${address.province} ${address.postalCode}`; expect(formatAddress(address)).toEqual(expectedResult); }); }); 25 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 26. import formatAddress from '../formatAddress'; import addresses from '../__sampleData__/addresses'; describe('formatAddress', () => { it('formats an address with one line correctly', () => { const address = addresses[1]; const expectedResult = `${address.street1} ${address.city}, ${address.province} ${address.postalCode}`; expect(formatAddress(address)).toEqual(expectedResult); }); }); 26 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 27. Problems • Can't see the data relevant to what's being tested, have to look in another file • Test harder to understand, easier for bugs to sneak through • Coupled to shared test data; if it changes, test could break or give a false positive 27 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 28. ⚠ Mystery Guest 28 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 29. ⚠ Mystery Guest “The test reader is not able to see the cause and effect between fixture and verification logic because part of it is done outside the Test Method.” 29 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 30. ⚠ Mystery Guest “The test reader is not able to see the cause and effect between FIXTURE and verification logic because part of it is done outside the Test Method.” 30 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 31. Fixture “everything we need in place to exercise the [production code]”...“the pre-conditions of the test” 31 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 32. Shared Fixture “…reusing the same fixture for several or many tests.” 32 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 33. Fresh Fixture “Each test constructs its own brand-new test fixture for its own private use.” 33 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 34. ⚠ Mystery Guest “The test reader is not able to see the cause and effect between fixture and verification logic because part of it is done outside the Test Method.” 34 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 35. Solution: set up the data closer to the test Several possible approaches using Fresh Fixtures 35 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 36. Approach 1: In-Line Setup “Each Test Method creates its own Fresh Fixture by [building] exactly the test fixture it requires.” 36 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 37. it('formats an address with one line correctly', () => { const address = { street1: '101 College Street', city: 'Toronto', province: 'ON', postalCode: 'M5G 1L7' }; const expectedResult = `${address.street1} ${address.city}, ${address.province} ${address.postalCode}`; expect(formatAddress(address)).toEqual(expectedResult); }); 37 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 38. Approach 2: Delegated Setup 38 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 39. Approach 2: Delegated Setup 39 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 40. Approach 2: Delegated Setup “Each Test Method creates its own Fresh Fixture by calling Creation Methods from within the Test Methods.” 40 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 41. function createAddress({ hasStreet2 = false }) { const address = { street1: '101 College Street', city: 'Toronto', province: 'ON', postalCode: 'M5G 1L7' }; if (hasStreet2) { address.street2 = 'Suite 123'; } return address; }; 41 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 42. it('formats an address with one line correctly', () => { const address = createAddress({ hasStreet2: false }); const expectedResult = `${address.street1} ${address.city}, ${address.province} ${address.postalCode}`; expect(formatAddress(address)).toEqual(expectedResult); }); 42 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 43. it('formats an address with two lines correctly', () => { const address = createAddress({ hasStreet2: true }); const expectedResult = `${address.street1} ${address.street2} ${address.city}, ${address.province} ${address.postalCode}`; expect(formatAddress(address)).toEqual(expectedResult); }); 43 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 44. Approach 3: Implicit Setup “We build the test fixture common to several tests in the setUp method." 44 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 45. let address; beforeEach(() => { address = { street1: '101 College Street', city: 'Toronto', province: 'ON', postalCode: 'M5G 1L7' }; }); 45 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 46. it('formats an address with one line correctly', () => { const expectedResult = `${address.street1} ${address.city}, ${address.province} ${address.postalCode}`; expect(formatAddress(address)).toEqual(expectedResult); }); 46 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 47. it('formats an address with two lines correctly', () => { address.street2 = 'Apt. 317'; const expectedResult = `${address.street1} ${address.street2} ${address.city}, ${address.province} ${address.postalCode}`; expect(formatAddress(address)).toEqual(expectedResult); }); 47 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 48. ⚠ Mystery Guest Solutions: 1. In-Line Setup 2. Delegated Setup 3. Implicit Setup 48 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 49. 349 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 50. it('formats an address correctly', () => { const address = { firstName: 'Sally', lastName: 'Smith', street1: '80 Spanida Avenue', street2: '4th Floor', city: 'Toronto', province: 'ON', postalCode: 'M5V 2J4', country: 'CA' }; const expectedResult = `${address.street1} ${address.street2} ${address.city}, ${address.province} ${address.postalCode}`; expect(formatAddress(address)).toEqual(expectedResult); }); 50 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 51. Problems • Hard to see which fields matter and which don't • Tests get long 51 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 52. ⚠ Irrelevant Information 52 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 53. ⚠ Irrelevant Information “The test exposes a lot of irrelevant details about the fixture that distract the test reader from what really affects the behavior of the [system under test].” 53 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 54. General Fixture “The test builds or references a larger fixture than is needed to verify the functionality in question.” 54 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 55. Solution 1: Minimal Fixture “We use the smallest and simplest fixture possible for each test.” 55 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 56. it('formats an address correctly', () => { const address = { - firstName: 'Sally', - lastName: 'Smith', street1: '80 Spanida Avenue', street2: '4th Floor', city: 'Toronto', province: 'ON', postalCode: 'M5V 2J4', - country: 'CA' }; 56 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 57. it('formats an address correctly', () => { const address = { street1: '80 Spanida Avenue', street2: '4th Floor', city: 'Toronto', province: 'ON', postalCode: 'M5V 2J4' }; 57 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 58. What if that data is still needed for the code to run? • Type verification • Class instance requiring constructor args • Fields validated by code unrelated to the test 58 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 59. Solution 2: Parameterized Creation Method “We set up the test fixture by calling methods that hide the mechanics of building ready-to-use objects behind Intent-Revealing Names.” “A Parameterized Creation Method allows the test to pass in some attributes to be used in the creation of the object. In such a case, we should pass only those attributes that are expected to affect…the test's outcome” 59 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 60. const defaultAddress = { firstName: 'Sally', lastName: 'Smith', street1: '80 Spanida Avenue', street2: '4th Floor', city: 'Toronto', province: 'ON', postalCode: 'M5V 2J4', country: 'CA' }; function createAddress(overrides = {}) { return { ...defaultAddress, ...overrides }; }; 60 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 61. it('formats an address correctly', () => { const address = createAddress({ street1: '80 Spanida Avenue', street2: '4th Floor', city: 'Toronto', province: 'ON', postalCode: 'M5V 2J4' }); const expectedResult = `${address.street1} ${address.street2} ${address.city}, ${address.province} ${address.postalCode}`; expect(formatAddress(address)).toEqual(expectedResult); }); 61 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 62. Solution 3: Test Data Creation Libraries 62 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 63. Test Data Bot ! const { build, sequence } = require('test-data-bot') const addressBuilder = build('address').fields({ street1: '80 Spanida Avenue', street2: sequence(x => `Suite ${x}`), city: 'Toronto', province: 'ON', postalCode: 'M5V 2J4', }) 63 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 64. Test Data Bot ! const user = addressBuilder({ street2: null }) 64 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 65. ⚠ Irrelevant Information Solutions: 1. Minimal Fixture 2. Parameterized Creation Method 3. Test Data Creation Library 65 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 66. 466 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 67. import totalOrder from '../totalOrder'; import orders from '../__sampleData__/orders'; describe('totalOrder', () => { it('calculates the correct total values when there are no line items', () => { const order = orders[0]; order.lines = []; const totalValues = totalOrder(order); expect(totalValues.subtotal).toEqual(0); expect(totalValues.tax).toEqual(0); expect(totalValues.total).toEqual(0); }); 67 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 68. it('calculates the correct total values', () => { const order = orders[0]; const totalValues = totalOrder(order); expect(totalValues.subtotal).toEqual(7); expect(totalValues.tax).toBeCloseTo(1.05); expect(totalValues.total).toBeCloseTo(8.05); }); }); 68 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 69. ⚠ Interacting Tests 69 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 70. ⚠ Interacting Tests "Tests depend on other tests in some way…[for example,] a test can be run as part of a suite but cannot be run by itself" In our case, a test can be run by itself but cannot be run as part of a suite. 70 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 71. ⚠ Shared Fixture 71 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 72. Solution: Fresh Fixture 72 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 73. Solution: Fresh Fixture “Each test constructs its own brand-new test fixture for its own private use.” 73 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 74. it('calculates the correct total values when there are no line items', () => { const order = _.cloneDeep(orders[0]); order.lines = []; const totalValues = totalOrder(order); expect(totalValues.subtotal).toEqual(0); expect(totalValues.tax).toEqual(0); expect(totalValues.total).toEqual(0); }); 74 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 75. it('calculates the correct total values', () => { const order = _.cloneDeep(orders[0]); const totalValues = totalOrder(order); expect(totalValues.subtotal).toEqual(7); expect(totalValues.tax).toBeCloseTo(1.05); expect(totalValues.total).toBeCloseTo(8.05); }); }); 75 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 76. Warning Sign: ⚠ Interacting Tests Solution: Fresh Fixture 76 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 77. 577 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 78. const TAX_PERCENT = 0.15; function totalOrder(order) { const lineTotals = order.lines.map(line => ( line.pricePerItem * line.quantity )); const subtotal = lineTotals.reduce((acc, val) => acc + val, 0); const tax = subtotal * TAX_PERCENT; const total = subtotal + tax; return { subtotal, tax, total }; } 78 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 79. describe('totalOrder', () => { it('calculates the correct total values', () => { const order = { lines: [ { pricePerItem: 5.99, quantity: 3 }, { pricePerItem: 7.99, quantity: 4 } ] }; 79 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 80. const lineTotals = order.lines.map( line => line.pricePerItem * line.quantity ); const subtotal = lineTotals.reduce((acc, val) => acc + val); const tax = subtotal * 0.15; const total = subtotal + tax; const totalValues = totalOrder(order); expect(totalValues.subtotal).toEqual(subtotal); expect(totalValues.tax).toBeCloseTo(tax); expect(totalValues.total).toBeCloseTo(total); }); }); 80 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 81. Problems • If the logic is wrong in one place, it's wrong in both. Is it really testing? • Doesn't let you see the intended result at a glance 81 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 82. ⚠ Production Logic in Test 82 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 83. ⚠ Production Logic in Test “[If we] use a Calculated Value based on the inputs…we find ourselves replicating the expected [production] logic inside our test to calculate the expected values for assertions.” 83 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 84. Solution: Hard-Coded Test Data 84 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 85. it('calculates the correct total values', () => { const order = { lines: [ { pricePerItem: 2, quantity: 2 }, { pricePerItem: 3, quantity: 1 } ] }; const totalValues = totalOrder(order); expect(totalValues.subtotal).toEqual(7); expect(totalValues.tax).toBeCloseTo(1.05); expect(totalValues.total).toBeCloseTo(8.05); }); 85 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 86. Solution: Hard-Coded Test Data 86 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 87. Solution: Hard-Coded Test Data ! 87 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 88. Warning Sign ⚠ Production Logic in Test Solution Hard-Coded Test Data 88 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 89. Review: Test Patterns 1. Flexible Test → Simple Tests 2. Mystery Guest → In-Line Setup 3. Irrelevant Information → Minimal Fixture 4. Interacting Tests → Fresh Fixture 5. Production Logic in Test → Hard-Coded Test Data 89 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 90. Takeaways 90 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 91. 91 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 92. Let's talk about test patterns! 92 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 93. Let's talk about test patterns! And let's use shared language! 93 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 94. The deeper takeaway… 94 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong
  • 95. Let's connect people with our rich testing history. 95 Old Solutions to New Testing Problems - Assert(js) 2019 - @CodingItWrong