Testing... Testing...
1, 2, NaN
A voyage into testing that fickle devil known as JavaScript... and beyond!
Hi!
Β‘HOLA!

I am Gant

[ graphic ]
maybe something about preparedness here
readability etc.

Caveats:
-
Infomercials
-
Imperfect Coverage
Warning!!!

Imperfect Coverage
My perspective.
Sooo... lots of React Native
How to use this talk?

Why Tests?
?


Why Tests?
but seriously...

Tests Pass
Test...
How do they work?

Smart People


Teams
who want to ship durable code
But I'm not a testing expert!
The Tester's Crisis
π±
Testing Myths
aka Excuses

π¦ Tests make projects harder


π¦ Backfilling tests is a good or bad thing.


RED - GREEN - REFACTOR

π¦ Thinking tests before code is too hard.


Think Functional
- One input β one output
- Declarative code
- Parallel friendly
- Lazy evaluation
If you're doing the same thing in two places, DRY your code."
- Everyone
If you're doing two things in one place, split your code."
- Gant (and probably everyone, too)
π¦ Testing is algorithmic and not heuristic.


π¦ Testing is pass/fail with no between.


Does that mean in the end I need to roll my own tests suite?

... yes, but...
YES

The Testing Domain
The Testing Triangle
"-ish"

The Testing Triangle
"-ish"

The Testing Triangle
"-ish"

Venture with me!

Unit Tests
simple, cheap, tests
Code
Do some thing!
Test
Did it do the thing?
Unit Tests
But be functional!!!!
JEST
Fan of AVA? Try this article

Unit Tests
import React from "react"
import { MagicButton } from "../src/components/magicButton"
import renderer from "react-test-renderer"
test("MagicButton has onPress fn", () => {
let x = 0
const buttonInstance = renderer
.create(<MagicButton onPress={() => x++} />)
.getInstance()
expect(buttonInstance.handleCrazyPress).toBeDefined()
expect(x).toBe(0)
buttonInstance.props.handleCrazyPress()
expect(x).toBe(1)
})
Simple! π
GOTCHAS!

Mock it All
Mock API
// setupJest.js or similar file
global.fetch = require('jest-fetch-mock')
jest-fetch-mock
custom mock
const API = require('mockAPI')
JEST automatically uses the mock folder
MockDate
describe("My Date() Tests", () => {
beforeEach(() => {
MockDate.set("2012-12-12T00:00:00.000Z")
})
afterEach(() => {
MockDate.reset()
})
...
})
DOUBLE GOTCHA


Make sure mocking is deterministic
import React from 'react'
import Mole from '../../src/views/Mole/mole'
import renderer from 'react-test-renderer'
test('Inactive Mole Press', () => {
const moleInstance = renderer.create(<Mole />).getInstance()
moleInstance.handlePressIn()
expect(moleInstance.state.currentImage.testUri).toContain('hole')
})
Passes on Mac - Fails on Windows

Unit Testing
Ideally: Where we keep declarative code accountable.
Integration

Integration

Integration
Not so much in React

Integration
Forcing integration can be false security.
UNLESS
- You violated or blurred encapsulation
- You are checking performance
- You are checking visuals
Integration

Snapshot Unit Tests
β© πΈ π
FAST!!!!
Snapshot Unit Tests
This replaces:
- console.log the object
- copy and paste it into the test
- then check for equality
Snapshot Unit Tests
const temp = createAmazingObject('test', 'Ο', 1.61803)
expect(temp).toMatchSnapshot()
feel free to use snapshots on anything that's not data.
Snapshot Unit Tests
React components are PERFECT for snapshot tests!
Snapshot Storybook
Because Storybook Rocks!

Snapshot Storybook
import initStoryshots from "@storybook/addon-storyshots"
initStoryshots({
configPath: "./storybook",
framework: "react-native",
})
Now all storybook stories are snapshot tests
Snapshot State
XState and React-Automata
Automatic Tests!?
import { testStateMachine } from 'react-automata'
import { App } from '../App'
test('all state snapshots', () => {
testStateMachine(App, { fixtures })
})
Assure your app code handles all combinations of state you've identified!
Other automatic examples?

Dependency injected middleware combinations
E2E Tests
Gray vs Black

Blackbox Sounds Great
sleep(4)
sleep(9)
sleep(12)
sleep(17)
Cypress
React.js Testing Awesome

Cypress
Example App:
Try it yourself! Especially the time travel.
Recordings

Cypress for Web π
Mobile? π€·ββοΈ
Appium
http://appium.io/


Detox

"rehab": "detox build && detox test"
GOTCHAS!

Setup
-
package.json Edits
-
config.json Edits
Set time for setup!

Detox
describe("Example", () => {
beforeEach(async () => {
// await device.reloadReactNative()
await device.launchApp({ newInstance: true })
})
it("should have packing list screen", async () => {
await expect(element(by.id("packingListScreen"))).toBeVisible()
})
it("should have an input screen", async () => {
await element(by.text("Input")).tap()
await expect(element(by.id("listInputScreen"))).toBeVisible()
})
})
Detox
Given that accessibilityLabel is an outwardly-facing string that is actually used by accessibility screen readers (and should be localized to the device user's language), Apple now provides an alternate property (iOS 5+) that is specifically intended for UI Automation purposes"
Detox

Detox
describe("List Input Test", () => {
beforeEach(async () => {
// await device.reloadReactNative()
await device.launchApp({ newInstance: true })
await element(by.text("Input")).tap()
})
it("should have list input screen", async () => {
await expect(element(by.id("listInputScreen"))).toBeVisible()
})
it("should have a list input component", async () => {
await expect(element(by.id("inputField"))).toBeVisible()
await element(by.id("inputField")).replaceText("Socks")
await element(by.text("Add item to List")).tap()
await element(by.text("List")).tap()
await expect(element(by.text("Socks"))).toBeVisible()
})
})
Detox

Detox Instruments?

Soft-Tests
linters++
Style Linting
Prettier Rocks

Complexity Audits
http://jshint.com
Company Audits

Accessibility?

Linting and A11y
React
https://github.com/evcohen/eslint-plugin-jsx-a11y
by Evan Cohen @beefancohen
React Native
https://github.com/FormidableLabs/eslint-plugin-react-native-a11y
by Jen Luker @knitcodemonkey
GOTCHAS!

Common Testing Stack
When
to test?
- On Commit?
- On Push?
- On PR?
Rely on CI!
Soft CI?
Danger CI π«
"Stop saying 'You forgot to ...' in code review"
Write JavaScript!
Beyond!

Environment Tests?
wat?

API Snapshots?
protecting REST API Calls Backwards

API Snapshots?
Enforce API structure with Schemas
API Snapshots

Perf Testing
Not "How" but "How Well"

Perf Testing
Copy-Paste Testing?
DRY code is maintainable code
Size - Audit
-
Images
-
App Data
-
Dependencies
Test Tests?

use https://codecov.io/ or others
Coverage Reporting
Test Dependencies?
Non-trivial Updating
Test Dependencies?
greenkeeper.io

Test Dependencies?
updtr



Madge Graphs
Madge Circular Checks
$ yarn madge --circular path/src/
$ yarn madge --extensions ts --circular src/


Anomaly Detection?

Static Type Checking
PLEASE!



Chaos Testing

Chaos Testing

Localization
Generalized Chaos
By breaking systems on purpose with chaos engineering, engineers can find vulnerabilities and address them before they result in downtime and lost revenue.
Generalized Chaos
Naughty Code

Parameterized Chaos
TestCheck.js
works with most common testing libs
check(
property(
gen.int, gen.int,
(a, b) => a + b >= a && a + b >= b
)
)
TestCheck.js
Simplest failcase
{ result: false,
failingSize: 2,
numTests: 3,
fail: [ 2, -1 ],
shrunk:
{ totalNodesVisited: 2,
depth: 1,
result: false,
smallest: [ 0, -1 ]
}
}
Parameterized Chaos
Parameterized Chaos
Typescript version?

Manual Testing
QA and UATs
Manual Testing

With React Consider
All States
- Failure State
- Invalid State
- Offline State
- No Permission State
- Localizations
- Return App State
With React Consider
- Devices/Platforms
- Orientation
- 3rd Party Failure
- Low light environment
- Simple gestures
- Button mashing
- Screen Readers
And all combinations!!!
Production Testing
Crowd-sourced Errors
Production Testing

Production Testing
React
React Native
Production Testing
A/B Testing?
Not JS
beyond the beyond

Non-JS Testing
README Testing
Just trying to be ridiculous now...
Find the ones that fit your project, and use them!
Accessibility - Audit
JSX - Audit

Deep Interconnected
Feedback Loops

The question is:
"What needs to be durable and effective for your software?"
It can feel messy

It can feel crazy

But who do we blame?

Good Tools and Great Wisdom

Thanks React Alicante!

GantLaborde.com
@GantLaborde