Slide 1

Slide 1 text

Effective testing Mohamed3on How to write tests that let you confidently deploy on a Friday By Mohamed Oun Software Engineer at HelloFresh mohamed3on.online

Slide 2

Slide 2 text

Tests when you make a one-line change

Slide 3

Slide 3 text

Why do we even write tests?

Slide 4

Slide 4 text

We write tests to give us more confidence The point of tests is NOT to tell you that you made changes, it’s to tell you whether your changes broke something

Slide 5

Slide 5 text

If we want developers to embrace a culture of testing, we have to show the benefits to it

Slide 6

Slide 6 text

Tests should serve as a documentation for how the code works • Think about clear names for your test cases • Be explicit about what you’re testing • Avoid DRY test code, It’s ok to duplicate test objects and code to make clearer, easier to read test cases

Slide 7

Slide 7 text

Each test should bring unique value and should not be coupled to any other test

Slide 8

Slide 8 text

Tests should be as flexible and accommodating as possible Think hard of the core functionalities you don’t want to break, and focus on testing those

Slide 9

Slide 9 text

Thinking flexibly, how do we test this?

Slide 10

Slide 10 text

Two ways to test for this • Ensure that all recipe cards are 170px height (current default size) • Ensure that all recipe cards have the same height (more flexibility)

Slide 11

Slide 11 text

Fix your bugs by writing tests for them 1. Find out the buggy function that’s returning a wrong value for some inputs (easier said than done). 2. call the function with those inputs in a test. 3. Use that test to reproduce the bug and fix it. Why? 1. Rerunning that test is much faster that reproducing manually over and over. • Faster feedback loop leads to faster bug fixes 2. Having that test in the test suite ensures this bug never happens again

Slide 12

Slide 12 text

How do I know if my test is bad? • If your test broke when your source code didn’t, it’s a bad test • If your source code broke when your test didn’t, it’s a bad test

Slide 13

Slide 13 text

Tests should be behaviour-sensitive, but structure-insensitive

Slide 14

Slide 14 text

What shouldn’t break your tests • Adding a data-test-id • Refactoring without changing functionality • Changing styles* (fonts, colours, paddings) * unless it’s a reusable UI component (example: Design System)

Slide 15

Slide 15 text

A tale of two tests

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

Avoid snapshots as much as you can • They’re implicit, so it’s hard to know exactly what the test is for • They’re usually brittle, breaking when the component’s functionality doesn’t • They almost always fail the (bad test) test • Can be helpful in the case of reusable UI components (ex. design system components)

Slide 19

Slide 19 text

Many of your unit tests can be replaced by a type system* *Not sponsored by Microsoft

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

VS

Slide 22

Slide 22 text

100% test coverage is a trap “When a measure becomes a target, it ceases to be a good measure.”

Slide 23

Slide 23 text

High test coverage is NOT an indicator that your tests are sufficient • Focusing on high test coverage leads to low-quality, easy-gain tests (hint: snapshots) • you get diminishing returns on your tests as the coverage increases much beyond 70-80% • Very high coverage means that you are likely testing implementation details, which means your tests will probably break while refactoring, ironically making it harder, not easier, to refactor your code.

Slide 24

Slide 24 text

OK, so how do I know if my test suite is good enough? • You rarely get bugs that escape into production. • You are rarely hesitant to change some code for fear it will cause production bugs.

Slide 25

Slide 25 text

When you have bugs in production but tests are green

Slide 26

Slide 26 text

Black-box testing Testing the public API, from the point of view of your users

Slide 27

Slide 27 text

React components have 2 main users The developer using the component in another component, and the user seeing the rendered output

Slide 28

Slide 28 text

• Clicking on an interactive element (end user) • Changing props for a component (developer user) • Instead of testing component state/methods, testing the rendered output Black box testing in UI

Slide 29

Slide 29 text

How to test this counter?

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

Better yet, use data- test-id

Slide 32

Slide 32 text

How do I know if I’m testing implementation details? • Imagine you didn’t have access to the source code of what you are testing, would you still be able to write that test?

Slide 33

Slide 33 text

Unit? Integration? End to end?

Slide 34

Slide 34 text

How to know if my test is unit, integration or E2E? • If you mock everything, it’s a unit test • If you mock nothing, it’s an end to end test • Everything in between is an integration test

Slide 35

Slide 35 text

Unit → integration → E2E Trade-offs 1. Points of potential failure 2. Engineering time

Slide 36

Slide 36 text

Unit → integration → E2E 1. Amount of code tested 2. Confidence 3. Testing implementation details Trade-offs

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

Testing tools • Cypress/Selenium: • Integration ↔ E2E • Run in a real browser • Can still mock API responses • Jest: Enzyme/React-testing-library: Unit ↔ Integration • Run in an emulated browser • Can mock almost everything (functions, components, API responses)

Slide 39

Slide 39 text

Tired: Testing pyramid

Slide 40

Slide 40 text

Credits: @mrjedmao Wired: Testing trophy

Slide 41

Slide 41 text

Summary • Prefer explicit over implicit tests (avoid snapshots in most cases). • Use tests to fix the bugs you find • Use test coverage as a guide, not as a goal. • Prefer integration tests to get the most confidence and value out of your tests (mock as few things as possible). • Write tests that mimic real world usage of your application, and avoid testing implementation details (black-box testing). • Use a type system if you can.

Slide 42

Slide 42 text

Thank you!