Qwik Creator (Previously Angular)
Course Description
Dive into testing with Miško Hevery, covering unit and end-to-end testing, refactoring for testability, and using tools like Vitest and Playwright. You'll learn to mock dependencies, test UI with Storybook, and learn strategies for testing tricky-to-test asynchronous code. With this testing knowledge, you and your teams will build more reliable and maintainable web apps!
This course and others like it are available as part of our Frontend Masters video subscription.
Preview
CloseCourse Details
Published: April 2, 2024
Learning Paths
Topics
Learn Straight from the Experts Who Shape the Modern Web
Your Path to Senior Developer and Beyond
- 200+ In-depth courses
- 18 Learning Paths
- Industry Leading Experts
- Live Interactive Workshops
Table of Contents
Introduction
Section Duration: 43 minutes
- Miško Hevery, the creator of the Angular and Qwik frameworks, begins the workshop by sharing some general benefits of including testing as a part of the application development process. Including tests will improve code quality, increase productivity, strengthen team collaboration, and build confidence in the product.
- Miško discredits the common excuses for not including tests in a codebase. Often, omitting tests is not because of time or scope of work but a lack of knowledge for writing effective tests and having the tools in place to execute them.
- Miško answers audience questions related to the role Quality Assurance has in the testing lifecycle and how AI can facilitate testing. Traditional QA roles were responsible for application testing, whereas modern QA engineers helped define the domain-specific language for testing and the infrastructure for executing the tests.
- Miško discusses different types of tests and compares the scope, speed, and isolation attributes of each. The tests discussed are unit, integration, system tests, and end-to-end tests.
Unit Testing & Mocking
Section Duration: 1 hour, 22 minutes
- Miško explains asynchronous calls can be difficult to unit test when they are part of a more complex function. Refactoring the code and putting the asynchronous call into a separate component makes it easy for a unit test to call the code independently and ensure it's functioning properly.
- Miško introduces Vitest and begins writing a unit test for the GitHub API to verify repository information is returned. The tests are executed in the command line. Vitest also has a user interface that provides a list of tests and reports. Snapshots are also demonstrated in this lesson. The final code is on the lesson-1 branch
- Miško demonstrates how to mock external dependencies with Vitest. Creating a mock allows developers to test APIs without wasting resources or waiting for server responses. For a mock to work, components should be written in a way that allows them to be tested more easily. The final code is located on the lesson-2 branch
- Miško breaks down the anatomy of a test. Tests should contain a setup that initializes anything needed for the test, a stimulus that is the target of the test, and the expectations containing what is tested. A few questions about the differences between unit and end-to-end tests are also answered in this lesson.
- Miško adds a test to verify the asynchronous call times out after a set delay. Testing delays can slow down the test runner, so the test is then refactored so the delay can be resolved immediately. The final code is located on the lesson-3 branch
- Miško simplifies the tests by moving repeated code to the parent describe block. This allows multiple tests to use the same setup logic.
- Miško creates a test that requires two asynchronous calls to be sent. Mocks are used for each request and a test is written to ensure the result has the expected shape. The final code can be found on the lesson-4 branch.
- Miško introduces the concept of a "friendly" while sharing some advice for unit testing a class. A friendly is similar to a mock because it's a set of code that lives inside the test that can be passed objects from the test drive to help control the scope or create edge cases needed to be tested.
- Miško spends a few minutes walking through the clustering application included in the course repository. The user interface allows users to change the dataset's size, distance, and minimum cluster amount.
- Miško creates a unit test for a data set and for the clustering algorithms output. Creating a sample data set in the test makes the test faster and easier to reason about. Once the data set is run through the clustering algorithm, an expectation is written for the result. The final code can be found on the lesson-5 branch.
UI & End-to-End Testing
Section Duration: 47 minutes
- Miško introduces Storybook, which enables UI testing by allowing developers to isolate individual components. The visual representation can be compared to previous tests, and controls can be exposed to manipulate the component in isolation to test how it responds to different inputs. The final code can be found on the lesson-6 branch.
- Miško explains the value of end-to-end testing and introduces Playwright, which is similar to other testing tools like Cypress. Playwright is installed and an initial test is written for verifying the title of the clustering web page.
- Miško tests the behavior of the clustering form. Since elements on the page need to be selected and given specific values, a page object is created so the test API is more readable. This allows for some self-documentation to happen inside the test and alleviates confusion.
- Miško uses Playwright to test the form validation. The additional selectors are added to the page object. When the submit button is clicked, the tests verify the error has the correct text. The final code can be found on the lesson-7 branch
- Miško spends a few minutes answering questions about testing. Questions include the difference between Playwright and Storybook and writing tests that are too complex.
Writing Testable Code
Section Duration: 54 minutes
- Miško compares the different test strategies based on the number of tests they require and the execution time. This comparison is represented in a testing pyramid and illustrates unit tests represent a majority of the tests while end-to-end tests take the longest time to execute
- Miško emphasizes testing is all about correctly structuring your code. Leveraging patterns similar to dependency injection or a more functional style will simplify the inputs and outputs of a function and make it easy to test.
- Miško walks through several coding issues that create untestable code. Some of these techniques include mixing instantiation and logic, global state usage, and using too many conditionals.
- Miško shares some advice for tracking down issues in legacy applications. The progression includes scenario tests, which test the application as a whole. From there, functional tests can be written to test subsystems and, eventually, test individual classes in isolation with unit tests.
- Miško walks through the Guide for Testable Code to share additional pitfalls in code that lead to untestable code.
Wrapping Up
Section Duration: 6 minutes
- Miško wraps up the course with a few final thoughts about creating a testing mindset within a team and answers some additional questions on testing strategies.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops