Mastering React Test-Driven Development. - Daniel Irvine - E-Book

Mastering React Test-Driven Development. E-Book

Daniel Irvine

0,0
29,99 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.
Mehr erfahren.
Beschreibung

Test-driven development (TDD) is a programming workflow that helps you build your apps by specifying behavior as automated tests. The TDD workflow future-proofs apps so that they can be modified without fear of breaking existing functionality. Another benefit of TDD is that it helps software development teams communicate their intentions more clearly, by way of test specifications.
This book teaches you how to apply TDD when building React apps. You’ll create a sample app using the same React libraries and tools that professional React developers use, such as Jest, React Router, Redux, Relay (GraphQL), Cucumber, and Puppeteer. The TDD workflow is supported by various testing techniques and patterns, which are useful even if you’re not following the TDD process. This book covers these techniques by walking you through the creation of a component test framework. You’ll learn automated testing theory which will help you work with any of the test libraries that are in standard usage today, such as React Testing Library. This second edition has been revised with a stronger focus on concise code examples and has been fully updated for React 18.
By the end of this TDD book, you’ll be able to use React, Redux, and GraphQL to develop robust web apps.

Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:

EPUB
MOBI

Seitenzahl: 561

Veröffentlichungsjahr: 2022

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Mastering React Test-Driven Development

Second Edition

Build simple and maintainable web apps with React, Redux, and GraphQL

Daniel Irvine

BIRMINGHAM—MUMBAI

Mastering React Test-Driven Development

Second Edition

Copyright © 2022 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.

Group Product Manager: Pavan Ramchandani

Publishing Product Manager: Bhavya Rao

Senior Editor: Aamir Ahmed

Senior Content Development Editor: Feza Shaikh

Technical Editor: Saurabh Kadave

Copy Editor: Safis Editing

Project Coordinator: Manthan Patel

Proofreader: Safis Editing

Indexer: Manju Arasan

Production Designer: Aparna Bhagat

Marketing Coordinator: Anamika Singh and Marylou De Mello

First published: May 2019

Second edition: September 2022

Production reference: 2130922

Published by Packt Publishing Ltd.

Livery Place

35 Livery Street

Birmingham

B3 2PB, UK.

ISBN 978-1-80324-712-0

www.packt.com

To Nige, my first mentor, who taught me the importance of slowing down.

– Daniel Irvine

Foreword

For as long as test-driven development(TDD) has existed, there has been debate over whether TDD is feasible for user interface work—even among its staunchest proponents. When people built tools to prove that it’s possible, the debate shifted to whether TDD is as valuable for UIs, considering that programmers can get rapid feedback by seeing and interacting with an interface. Even when TDD’s value is evidenced by smaller, more consistent, single-responsibility units of UI code, some would question whether the same could have been accomplished with less effort by simply following established design patterns.

Is TDD worth your time? Will it result in fewer bugs in your code? Will it improve the design of your system? Will it make future maintenance easier? Maybe.

In the fifteen-or-so years that I’ve been learning, practicing, and teaching test-driven development I have oscillated back-and-forth. Sometimes I relentlessly pursue 100% code coverage, and other times I’ll build worrisomely large applications with no automated tests at all. What I’ve found—and what might surprise some readers—is that my code basically turns out the same whether I practice TDD or not: a similar frequency of bugs, the same idiosyncratic design, and no more or less a burden to maintain.

(At this point, you’d be right to start wondering what this ambivalent foreword is doing in a book designed to teach you TDD.)

The reason that TDD itself doesn’t impact my code very much is because my years of practice have utterly and irrevocably changed me.

I write small single-purpose units, because I’ve felt the sheer exhaustion of writing tests of sprawling unfocused objects.

I avoid mixing levels of abstraction, because I’ve been hopelessly lost in mazes of mock objects that combine testing logic with specifying interactions.

I segregate code coupled to frameworks from feature logic, because I’ve contorted too many tests to fit dependencies that weren’t meant to be tested.

Rigorously practicing TDD transformed my career. Not because it’s the One True Way to program, but because it forces you to ceaselessly ask “how would we test that?” TDD is incredibly challenging at first, but patterns gradually emerge that result in easy-to-test code. And code that’s easy to test, is easy to write. And use. And maintain.

Wherever you are in your journey, I hope this book brings you closer to a similar destination.

Justin Searls VP of Engineering at Test Double

testdouble.com

Contributors

About the author

Daniel Irvine is a software consultant based in London. He works with a variety of languages including C#, Clojure, JavaScript, and Ruby. He’s a mentor and coach for junior developers and runs TDD and XP workshops and courses. When he’s not working, he spends time cooking and practicing yoga. He co-founded the Queer Code London meetup and is an active member of the European software craft community.

I would like to thank the technical reviewer of this edition of the book, Emmanuel Demey, for spotting the weakest points of the text and helping me improve them. I continue to be grateful for my friend and technical reviewer from the first edition, Raimo Radczewski, who is also the author of the expect-redux package that is used in this book.

The team at Packt has been supportive and professional throughout, giving me exactly what I needed to finish the book. For this second edition, I am thankful for the detailed and thoughtful editing that Feza Shaikh has undertaken, helping to deliver the book ahead of schedule. My technical editor, Saurabh Kadave, spotted plenty of mistakes that would have otherwise gone unnoticed. Aamir Ahmed, Bhavya Rao, and Manthan Patel were also instrumental in the production of the second edition.

From the first edition, I am thankful for the hard work of Keagan Carneiro, Sachin Sunilkumar from Packt, and also my friends and colleagues Charlotte Payne, Dan Pelensky, Isidro López, Makis Otman, Sam Szreter, Zach Shaw, Brendan Murphy, and Lucy Monie Hall.

Finally, thank you to all the readers of the first edition who took the time to send me comments and feedback, all of which were invaluable. This second edition is better because of your help.

About the reviewer

Emmanuel Demey works with the JavaScript ecosystem every day, and he spends his time sharing his knowledge with anybody. His first goal at work is to help the people that he works with. He speaks at French conferences (Devfest Nantes, Devfest Toulouse, Sunny Tech, Devoxx France, and others) about anything related to the web platform: JavaScript frameworks (Angular, React.js, Vue.js), accessibility, Nest.js, and so on. He has been a trainer for 10 years at Worldline and Zenika (two French consulting companies). He is also a co-leader of the Google Developer of Lille group and a co-organizer of the Devfest Lille conference.

Table of Contents

Preface

Part 1 – Exploring the TDD Workflow

1

First Steps with Test-Driven Development

Technical requirements

Creating a new React project from scratch

Installing npm

Creating a new Jest project

Bringing in React and Babel

Displaying data with your first test

Writing a failing test

Make it pass

Making use of the act test helper

Triangulating to remove hardcoding

Backtracking on ourselves

Refactoring your work

Sharing setup code between tests

Extracting methods

Writing great tests

Red, green, refactor

Streamlining your testing process

Summary

Further reading

2

Rendering Lists and Detail Views

Technical requirements

Sketching a mock-up

Creating the new component

Specifying list item content

Selecting data to view

Initial selection of data

Adding events to a functional component

Manually testing our changes

Adding an entry point

Putting it all together with webpack

Summary

Exercises

Further reading

3

Refactoring the Test Suite

Technical requirements

Pulling out reusable rendering logic

Creating a Jest matcher using TDD

Extracting DOM helpers

Summary

Exercises

Further reading

4

Test-Driving Data Input

Technical requirements

Adding a form element

Accepting text input

Submitting a form

Submitting without any changes

Preventing the default submit action

Submitting changed values

Duplicating tests for multiple form fields

Nesting describe blocks

Generating parameterized tests

Solving a batch of tests

Modifying handleChange so that it works with multiple fields

Testing it out

Summary

Exercises

5

Adding Complex Form Interactions

Technical requirements

Choosing a value from a select box

Providing select box options

Preselecting a value

Constructing a calendar view

Adding the table

Adding a header column

Adding a header row

Test-driving radio button groups

Hiding input controls

Selecting a radio button in a group

Handling field changes through a component hierarchy

Reducing effort when constructing components

Extracting test data builders for time and date functions

Extracting a test props object

Summary

Exercises

Further reading

6

Exploring Test Doubles

Technical requirements

What is a test double?

Learning to avoid fakes

Submitting forms using spies

Untangling AAA

Making a reusable spy function

Using a matcher to simplify spy expectations

Spying on the fetch API

Replacing global functions with spies

Test-driving fetch argument values

Reworking existing tests with the side-by-side implementation

Improving spy expectations with helper functions

Stubbing fetch responses

Upgrading spies to stubs

Acting on the fetch response

Displaying errors to the user

Grouping stub scenarios in nested describe contexts

Migrating to Jest’s built-in test double support

Using Jest to spy and stub

Migrating the test suite to use Jest’s test double support

Extracting fetch test functionality

Summary

Exercises

Further reading

7

Testing useEffect and Mocking Components

Technical requirements

Mocking child components

How to mock components, and why?

Testing the initial component props

Fetching data on mount with useEffect

Understanding the useEffect hook

Adding the renderAndWait helper

Adding the useEffect hook

Testing the useEffect dependency list

Building matchers for component mocks

Variants of the jest.mock call

Removing the spy function

Rendering the children of mocked components

Checking multiple instances of the rendered component

Alternatives to module mocks

Summary

Exercises

Further reading

8

Building an Application Component

Technical requirements

Formulating a plan

Using state to control the active view

Test-driving callback props

Making use of callback values

Summary

Exercises

Part 2 – Building Application Features

9

Form Validation

Technical requirements

Performing client-side validation

Validating a required field

Generalizing validation for multiple fields

Submitting the form

Extracting non-React functionality into a new module

Handling server errors

Indicating form submission status

Testing state before promise completion

Refactoring long methods

Summary

Exercises

Further reading

10

Filtering and Searching Data

Technical requirements

Displaying tabular data fetched from an endpoint

Paging through a large dataset

Adding a button to move to the next page

Adjusting the design

Adding a button to move to the previous page

Forcing design changes using tests

Filtering data

Refactoring to simplify the component design

Performing actions with render props

Testing render props in additional render contexts

Summary

Exercises

11

Test-Driving React Router

Technical requirements

Designing React Router applications from a test-first perspective

A list of all the React Router pieces

Splitting tests when the window location changes

Up-front design for our new routes

Testing components within a router

The Router component and its test equivalent

Using the Routes component to replace a switch statement

Using intermediate components to translate URL state

Testing router links

Checking the page for hyperlinks

Mocking the Link component

Testing programmatic navigation

Summary

Exercise

Further reading

12

Test-Driving Redux

Technical requirements

Up-front design for a reducer and a saga

Why Redux?

Designing the store state and actions

Test-driving a reducer

Pulling out generator functions for reducer actions

Setting up a store and an entry point

Test-driving a saga

Using expect-redux to write expectations

Making asynchronous requests with sagas

Switching component state for Redux state

Submitting a React form by dispatching a Redux action

Making use of store state within a component

Navigating router history in a Redux saga

Summary

Exercise

Further reading

13

Test-Driving GraphQL

Technical requirements

Compiling the schema before you begin

Testing the Relay environment

Building a performFetch function

Test-driving the Environment object construction

Test-driving a singleton instance of Environment

Fetching GraphQL data from within a component

Summary

Exercises

Further reading

Part 3 – Interactivity

14

Building a Logo Interpreter

Technical requirements

Studying the Spec Logo user interface

Undoing and redoing user actions in Redux

Building the reducer

Building buttons

Saving to local storage via Redux middleware

Building middleware

Changing keyboard focus

Writing the reducer

Focusing the prompt

Requesting focus in other components

Summary

Further reading

15

Adding Animation

Technical requirements

Designing animation

Building an animated line component

Animating with requestAnimationFrame

Canceling animations with cancelAnimationFrame

Varying animation behavior

Summary

Exercises

16

Working with WebSockets

Technical requirements

Designing a WebSocket interaction

The sharing workflow

The new UI elements

Splitting apart the saga

Test-driving a WebSocket connection

Streaming events with redux-saga

Updating the app

Summary

Exercises

Further reading

Part 4 – Behavior-Driven Development with Cucumber

17

Writing Your First Cucumber Test

Technical requirements

Integrating Cucumber and Puppeteer into your code base

Writing your first Cucumber test

Using data tables to perform setup

Summary

18

Adding Features Guided by Cucumber Tests

Technical requirements

Adding Cucumber tests for a dialog box

Fixing Cucumber tests by test-driving production code

Adding a dialog box

Updating sagas to a reset or replay state

Avoiding timeouts in test code

Adding HTML classes to mark animation status

Updating step definitions to use waitForSelector

Summary

Exercise

19

Understanding TDD in the Wider Testing Landscape

Test-driven development as a testing technique

Best practices for your unit tests

Improving your technique

Manual testing

Demonstrating software

Testing the whole product

Exploratory testing

Debugging in the browser

Automated testing

Integration tests

System tests and end-to-end tests

Acceptance tests

Property-based and generative testing

Snapshot testing

Canary testing

Not testing at all

When quality doesn’t matter

Spiking and deleting code

Summary

Further reading

Index

Other Books You May Enjoy

Part 1 – Exploring the TDD Workflow

Part 1 introduces all of the basic techniques you’ll need to test-drive React applications. As you build more of the application, you will create a set of library functions that help to simplify and accelerate your testing. The goal is to give you both theoretical and practical advice that will help you apply the test-driven development workflow to your daily work.

This part includes the following chapters:

Chapter 1, First Steps with Test-Driven DevelopmentChapter 2, Rendering Lists and Detail ViewsChapter 3, Refactoring the Test SuiteChapter 4, Test-Driving Data InputChapter 5, Adding Complex Form InteractionsChapter 6, Exploring Test DoublesChapter 7, Testing useEffect and Mocking ComponentsChapter 8, Building an Application Component