The Benefits of
Testing and Automation
Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
Hi, I’m Andrew
Developer Programs Engineer at Pantheon.
ataylorme on GitHub and Twitter.
Some things I enjoy away from the computer are
@ataylorme • Slides: goo.gl/s1eMNn
Adding Tests To "Catch of The Day"
@ataylorme • Slides: goo.gl/s1eMNn
The Price Input Experience
@ataylorme • Slides: goo.gl/s1eMNn
Order.js
const total = orderIds.reduce((prevTotal, key) => {
const fish = this.props.fishes[key];
const count = this.props.order[key];
const isAvailable = fish && fish.status === "available";
if (isAvailable) {
return prevTotal + count * fish.price;
}
return prevTotal;
}, 0);
@ataylorme • Slides: goo.gl/s1eMNn
helpers.js
export function formatPrice(cents) {
return (cents / 100).toLocaleString("en-US", {
style: "currency",
currency: "USD"
});
}
@ataylorme • Slides: goo.gl/s1eMNn
Read The Docs
@ataylorme • Slides: goo.gl/s1eMNn
Add formatPrice.test.js
import { formatPrice } from "../helpers";
test('formatPrice returns a properly formatted price', () => {
const priceList = [
[123456,'$1,234.56',],
[1234567890,'$12,345,678.90',],
['12345.67889.986545','$12,345,678,899,865.45',],
[-12345678.91,'-$12,345,678.91',],
['1234@$975645643asfasdf.w3rw.sdfdzc4','$1,234,975,645,643.34',],
];
priceList.forEach(function (prices) {
expect(formatPrice(prices[0])).toBe(prices[1]);
});
});
@ataylorme • Slides: goo.gl/s1eMNn
Run The Test
@ataylorme • Slides: goo.gl/s1eMNn
Add toCents function helpers.js
export function toCents(input) {
let cents = input
// convert to a string
.toString()
// remove everything except numbers and dashes
.replace(/[^\d-]/g, "");
// convert back to a number
cents = parseInt(cents, 10);
return cents;
}
@ataylorme • Slides: goo.gl/s1eMNn
helpers.js
export function formatPrice(input) {
if( null === input ){
return '';
}
const cents = toCents(input);
// format for US dollars
return (cents / 100).toLocaleString("en-US", {
style: "currency",
currency: "USD"
});
}
@ataylorme • Slides: goo.gl/s1eMNn
Order.js
const total = orderIds.reduce((prevTotal, key) => {
const fish = this.props.fishes[key];
const count = this.props.order[key];
const isAvailable = fish && fish.status === "available";
if (isAvailable) {
return prevTotal + (count * toCents(fish.price));
}
return prevTotal;
}, 0);
@ataylorme • Slides: goo.gl/s1eMNn
Test Again
@ataylorme • Slides: goo.gl/s1eMNn
Refactored Price Input Experience
@ataylorme • Slides: goo.gl/s1eMNn
Add toCents Test
import { toCents } from "../helpers";�test('toCents returns the cents value of different inputs', () => {
const priceList = [
[123456,123456,],
['12345.67889.986545',1234567889986545,],
[-12345678.91,-1234567891,],
['1234@$975645643asfasdf.w3rw.sdfdzc4',123497564564334,],
];
priceList.forEach(function (prices) {
expect(toCents(prices[0])).toBe(prices[1]);
});
});
@ataylorme • Slides: goo.gl/s1eMNn
Run The Tests Automatically With CI
@ataylorme • Slides: goo.gl/s1eMNn
What is Continuous Integration?
LoopConf 3.0 • Slides: goo.gl/YB3v43
It is a State of Mind
LoopConf 3.0 • Slides: goo.gl/YB3v43
What Happens After �a Code Change?
LoopConf 3.0 • Slides: goo.gl/YB3v43
Let the robots do all the things
Devs do custom work, �robots do redundant tasks
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
Consistency
@ataylorme • Slides: goo.gl/s1eMNn
Ever Forgotten To Check That One Thing After a Deploy?
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
Reduced Overhead
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
Risk Mitigation
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
Confidence
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
Communication
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
@ataylorme • Slides: goo.gl/s1eMNn
Automation is a journey
@ataylorme • Slides: goo.gl/s1eMNn
Resources
@ataylorme • Slides: goo.gl/s1eMNn
Thanks!
Slides: goo.gl/s1eMNn
@ataylorme
@ataylorme • Slides: goo.gl/s1eMNn