Writing Good Tests for Vue Applications (e2e vs. Component Tests, Features of a *Good* Test)

Rate this content
Bookmark

The emergence of SPAs, and therefore logic-heavy client-side code, drastically changed the game for front-end developers. As a result, for the last couple of years, we have had to catch up with sophisticated techniques to build high-quality applications—one of the essential being testing.

More and more people started to add tests to their Vue.js-powered applications. With varying degrees of success. The field is still relatively new, and we all need more experience in how to test client-side applications most effectively.

With my talk, I want to walk through 1) how to come up with a solid testing strategy (tools and practices) and 2) work on a real-world example of how we combine E2E testing with component testing.

I want to highlight some general principles from testing theory and then go into the practical application—live coding in a TDD manner.

This talk has been presented at Vue.js London 2023, check out the latest edition of this JavaScript Conference.

FAQ

Good tests enable developers to refactor code with confidence, write better code faster, and allow for deployments at any time, including on Fridays, without fear of breaking existing functionalities.

Decoupling tests from the test framework means designing tests so that they are independent of any specific testing tools or libraries. This allows for easier switching between testing frameworks if a current framework becomes outdated or if a better tool is available.

Decoupling tests from implementation details, such as specific CSS selectors, ensures that tests focus on functionality rather than on how the code is implemented. This approach improves test resilience against changes in the codebase and aids in maintaining high accessibility standards.

Tests can be decoupled from the user interface by using a domain-specific language that abstracts UI details. This allows the same tests to be applicable across different platforms, such as web, mobile, or voice-controlled interfaces, and facilitates UI changes without breaking tests.

The two critical tips for writing good tests are writing tests first before the code implementation and decoupling everything, which includes decoupling tests from the framework, user interface, and implementation details.

Tightly coupling tests to a specific framework can lead to significant challenges when the framework is no longer supported, or better alternatives arise. This situation may require rewriting a large number of tests, which is time-consuming and costly.

Semantic selector methods, such as 'find by label text' or 'find by role', help decouple tests from specific implementation details like CSS selectors and ensure a base level of accessibility, making the tests more robust and the application more user-friendly.

Markus Oberlehner
Markus Oberlehner
33 min
12 May, 2023

Comments

Sign in or register to post your comment.
Video Summary and Transcription
This Talk discusses the importance of testing and the need to decouple tests from test frameworks, CSS selectors, and user interfaces. It emphasizes the benefits of writing tests first and provides examples of simulating shopping lists and working in a test-driven way. The Q&A section covers topics such as changing testing frameworks, bug coverage, and using data attributes for decoupling.

1. Introduction to Testing

Short description:

Hello, London. Today I talk about testing. A couple of years ago, my team and I were tasked to work on a completely new project. We were very motivated and wrote a lot of tests. However, I was new to testing and made some mistakes. Good tests enable us to refactor code with confidence, write better code faster, and deploy on Friday if we want to. To write good tests, we need to write test first and decouple all the things. Decoupling tests from the test framework is important to avoid rewriting tests when the framework is no longer maintained.

Hello, London. How are you doing? Awesome. So yeah, today I talk about testing. I will start with a little story.

A couple of years ago, my team and I were tasked to work on a completely new project so we could start a new project from scratch. And this is good news for us developers because most of us like to start from scratch with new projects. And we were a bunch of very motivated people and we wanted to do everything the right way. And the right way for us also included writing tests. So we wrote a lot of them. We wrote a lot of end-to-end tests. We wrote a lot of component tests and the years passed by and everything turned out great. And of course that's not how it went unfortunately. So what was the problem? The problem was that although we wrote a lot of tests, I, at that point, didn't know a lot about how to write good tests. So I was new to this testing topic and I made some mistakes. Let's put it that way. So a lot of those promises that come with advocates for testing always tell us didn't come. We still had a big mess of a code base in the end. But what are those promises that good tests should enable us to do? And the first one is good tests enable us to refactor our code with confidence. And also, good tests allow us to write better code faster. And good tests allow us to deploy on Friday if we want to. We still don't have to. So, I said the phrase good tests a couple of times. And what do I mean by good tests? How do we write good tests? And the good news is there are only two things, two very important things you have to consider. The first one is write test first. And the second one is decouple all the things.

Let's start with the second one, decouple all the things. What do I mean by all the things? And there are three aspects in which we can decouple our tests from our code base. The first one being we can decouple our tests from the test framework we are using. And now you might wonder why should we do this? Why should we go the route of decoupling our tests from the test framework? What's the point of it? And the thing is, imagine you are using, you have hundreds of tests and you're using a kind of old test framework and the maintainers of the test framework decide they don't want to maintain this framework anymore. And now you suddenly have to rewrite hundreds of tests and this can be a lot of work.

2. Decoupling Tests from Test Frameworks

Short description:

There's a new and better test framework called V-Test in the Vue ecosystem that can replace Jest. Decoupling tests from the test framework allows for easy switching of frameworks. We can improve test decoupling by using a generic driver and injecting it into the test callback. This allows us to switch between different test frameworks by changing only one file. For component tests, moving test methods into separate utils files enables easy swapping of test frameworks and customization of test functions.

Or there's a new and better test framework out there like just now in the Vue ecosystem or generally in the ecosystem we have V-Test which is very popular in the Vue ecosystem but tends to replace Jest maybe. And if you decouple your test from the test framework, you can switch frameworks just by rewriting of lines of code instead of all of your tests.

So what's the problem and how can we fix this? Here we can see a test for a simple application and because we are using this test for all the other, this application for all the other examples as well I want to show you this simple application. It's a very straightforward shopping list application and we can add something like bread for example and then we have bread on our shopping list and we can add something like milk and then we have milk on our shopping list and in the end we want to also be able to remove those items by clicking on those items. For now this doesn't work. We will add this feature later.

So this is the simple application, we test and in this test, this test is coupled to the test framework. In this instance Cypress for example. So you see this by this Cypress, Cy prefix and we are using methods from Cypress and we are using a get method to get some selector and typing something in it and we use again we use the get method of Cypress to click some buttons and so on. So how can we improve this? How can we decouple this test from Cypress? From the test framework? So we can switch to playwright for example just by changing 1 file instead of hundreds of tests. And the fix can look something like this. So here you see now we inject a generic driver so in the test callback we inject a generic driver, implementation on a generic driver object and for the test itself it doesn't matter if this driver is a playwright driver, a Cypress driver or maybe even a V test driver, it just doesn't matter. And then instead of the Cypress object we use the driver object which has a particular interface but it doesn't matter which implementation is behind it. Again, we have this get method to get some selectors and do some stuff like clicking or typing text. So this is for end-to-end tests. That way we can decouple end-to-end tests. Now you might wonder what about component tests. And for component tests I think this aspect isn't that important because for component tests we are closer to the code and we have to use specific methods and we have to work with return variables and stuff like that. And implementing a truly generic driver for component tests is harder to do, and I think it's also not that important. But what we still can do is to move all the test methods we use in our tests, like expect it and mount for example into our own utils files. And this enables us to swap test frameworks very easily. Imagine you were using Chess, for example, and now you want to switch to VTEST. If you have all your files or all your methods in this utils file, you can simply change this utils file and all your tests will still work. And the second thing this enables us to do is that, for example, we can wrap the mount function. And imagine you're having a UX Store or something like that or a router, and you can create your own custom implementation of the mount function which always loads your router or your OpinIO Store and so on. So much for decoupling for end-to-end tests and component tests. The next way in which we can decouple our tests from the code in this case is by decoupling our tests from implementation details. And you maybe heard of that already because it's probably one of the most important aspects when it comes to decoupling our tests. And let's take a look at the problem first again. So we see the test from before.

QnA

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

One Year Into Vue 3
Vue.js London Live 2021Vue.js London Live 2021
20 min
One Year Into Vue 3
Top Content
Vue 3 has seen significant adoption and improvements in performance, bundle size, architecture, and TypeScript integration. The ecosystem around Vue 3 is catching up, with new tools and frameworks being developed. The Vue.js.org documentation is undergoing a complete overhaul. PNIA is emerging as the go-to state management solution for Vue 3. The options API and composition API are both viable options in Vue 3, with the choice depending on factors such as complexity and familiarity with TypeScript. Vue 3 continues to support CDN installation and is recommended for new projects.
Network Requests with Cypress
TestJS Summit 2021TestJS Summit 2021
33 min
Network Requests with Cypress
Top Content
Cecilia Martinez, a technical account manager at Cypress, discusses network requests in Cypress and demonstrates commands like cydot request and SCI.INTERCEPT. She also explains dynamic matching and aliasing, network stubbing, and the pros and cons of using real server responses versus stubbing. The talk covers logging request responses, testing front-end and backend API, handling list length and DOM traversal, lazy loading, and provides resources for beginners to learn Cypress.
Vue: Feature Updates
Vue.js London 2023Vue.js London 2023
44 min
Vue: Feature Updates
Top Content
Watch video: Vue: Feature Updates
The Talk discusses the recent feature updates in Vue 3.3, focusing on script setup and TypeScript support. It covers improvements in defining props using imported types and complex types support. The introduction of generic components and reworked signatures for defined components provides more flexibility and better type support. Other features include automatic inference of runtime props, improved define emits and defined slots, and experimental features like reactive props destructure and define model. The Talk also mentions future plans for Vue, including stabilizing suspense and enhancing computer invalidations.
Testing Pyramid Makes Little Sense, What We Can Use Instead
TestJS Summit 2021TestJS Summit 2021
38 min
Testing Pyramid Makes Little Sense, What We Can Use Instead
Top Content
Featured Video
Gleb Bahmutov
Roman Sandler
2 authors
The testing pyramid - the canonical shape of tests that defined what types of tests we need to write to make sure the app works - is ... obsolete. In this presentation, Roman Sandler and Gleb Bahmutov argue what the testing shape works better for today's web applications.
Full-Circle Testing With Cypress
TestJS Summit 2022TestJS Summit 2022
27 min
Full-Circle Testing With Cypress
Top Content
Cypress is a powerful tool for end-to-end testing and API testing. It provides instant feedback on test errors and allows tests to be run inside the browser. Cypress enables testing at both the application and network layers, making it easier to reach different edge cases. With features like AppActions and component testing, Cypress allows for comprehensive testing of individual components and the entire application. Join the workshops to learn more about full circle testing with Cypress.
Test Effective Development
TestJS Summit 2021TestJS Summit 2021
31 min
Test Effective Development
Top Content
This Talk introduces Test Effective Development, a new approach to testing that aims to make companies more cost-effective. The speaker shares their personal journey of improving code quality and reducing bugs through smarter testing strategies. They discuss the importance of finding a balance between testing confidence and efficiency and introduce the concepts of isolated and integrated testing. The speaker also suggests different testing strategies based on the size of the application and emphasizes the need to choose cost-effective testing approaches based on the specific project requirements.

Workshops on related topic

Designing Effective Tests With React Testing Library
React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Top Content
Featured Workshop
Josh Justice
Josh Justice
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents- The different kinds of React application tests, and where component tests fit in- A mental model for thinking about the inputs and outputs of the components you test- Options for selecting DOM elements to verify and interact with them- The value of mocks and why they shouldn’t be avoided- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites- Familiarity with building applications with React- Basic experience writing automated tests with Jest or another unit testing framework- You do not need any experience with React Testing Library- Machine setup: Node LTS, Yarn
Vue3: Modern Frontend App Development
Vue.js London Live 2021Vue.js London Live 2021
169 min
Vue3: Modern Frontend App Development
Top Content
Featured WorkshopFree
Mikhail Kuznetsov
Mikhail Kuznetsov
The Vue3 has been released in mid-2020. Besides many improvements and optimizations, the main feature of Vue3 brings is the Composition API – a new way to write and reuse reactive code. Let's learn more about how to use Composition API efficiently.

Besides core Vue3 features we'll explain examples of how to use popular libraries with Vue3.

Table of contents:
- Introduction to Vue3
- Composition API
- Core libraries
- Vue3 ecosystem

Prerequisites:
IDE of choice (Inellij or VSC) installed
Nodejs + NPM
How to Start With Cypress
TestJS Summit 2022TestJS Summit 2022
146 min
How to Start With Cypress
Featured WorkshopFree
Filip Hric
Filip Hric
The web has evolved. Finally, testing has also. Cypress is a modern testing tool that answers the testing needs of modern web applications. It has been gaining a lot of traction in the last couple of years, gaining worldwide popularity. If you have been waiting to learn Cypress, wait no more! Filip Hric will guide you through the first steps on how to start using Cypress and set up a project on your own. The good news is, learning Cypress is incredibly easy. You'll write your first test in no time, and then you'll discover how to write a full end-to-end test for a modern web application. You'll learn the core concepts like retry-ability. Discover how to work and interact with your application and learn how to combine API and UI tests. Throughout this whole workshop, we will write code and do practical exercises. You will leave with a hands-on experience that you can translate to your own project.
Detox 101: How to write stable end-to-end tests for your React Native application
React Summit 2022React Summit 2022
117 min
Detox 101: How to write stable end-to-end tests for your React Native application
Top Content
WorkshopFree
Yevheniia Hlovatska
Yevheniia Hlovatska
Compared to unit testing, end-to-end testing aims to interact with your application just like a real user. And as we all know it can be pretty challenging. Especially when we talk about Mobile applications.
Tests rely on many conditions and are considered to be slow and flaky. On the other hand - end-to-end tests can give the greatest confidence that your app is working. And if done right - can become an amazing tool for boosting developer velocity.
Detox is a gray-box end-to-end testing framework for mobile apps. Developed by Wix to solve the problem of slowness and flakiness and used by React Native itself as its E2E testing tool.
Join me on this workshop to learn how to make your mobile end-to-end tests with Detox rock.
Prerequisites- iOS/Android: MacOS Catalina or newer- Android only: Linux- Install before the workshop
API Testing with Postman Workshop
TestJS Summit 2023TestJS Summit 2023
48 min
API Testing with Postman Workshop
Top Content
WorkshopFree
Pooja Mistry
Pooja Mistry
In the ever-evolving landscape of software development, ensuring the reliability and functionality of APIs has become paramount. "API Testing with Postman" is a comprehensive workshop designed to equip participants with the knowledge and skills needed to excel in API testing using Postman, a powerful tool widely adopted by professionals in the field. This workshop delves into the fundamentals of API testing, progresses to advanced testing techniques, and explores automation, performance testing, and multi-protocol support, providing attendees with a holistic understanding of API testing with Postman.
1. Welcome to Postman- Explaining the Postman User Interface (UI)2. Workspace and Collections Collaboration- Understanding Workspaces and their role in collaboration- Exploring the concept of Collections for organizing and executing API requests3. Introduction to API Testing- Covering the basics of API testing and its significance4. Variable Management- Managing environment, global, and collection variables- Utilizing scripting snippets for dynamic data5. Building Testing Workflows- Creating effective testing workflows for comprehensive testing- Utilizing the Collection Runner for test execution- Introduction to Postbot for automated testing6. Advanced Testing- Contract Testing for ensuring API contracts- Using Mock Servers for effective testing- Maximizing productivity with Collection/Workspace templates- Integration Testing and Regression Testing strategies7. Automation with Postman- Leveraging the Postman CLI for automation- Scheduled Runs for regular testing- Integrating Postman into CI/CD pipelines8. Performance Testing- Demonstrating performance testing capabilities (showing the desktop client)- Synchronizing tests with VS Code for streamlined development9. Exploring Advanced Features - Working with Multiple Protocols: GraphQL, gRPC, and more
Join us for this workshop to unlock the full potential of Postman for API testing, streamline your testing processes, and enhance the quality and reliability of your software. Whether you're a beginner or an experienced tester, this workshop will equip you with the skills needed to excel in API testing with Postman.
Monitoring 101 for React Developers
React Summit US 2023React Summit US 2023
107 min
Monitoring 101 for React Developers
Top Content
WorkshopFree
Lazar Nikolov
Sarah Guthals
2 authors
If finding errors in your frontend project is like searching for a needle in a code haystack, then Sentry error monitoring can be your metal detector. Learn the basics of error monitoring with Sentry. Whether you are running a React, Angular, Vue, or just “vanilla” JavaScript, see how Sentry can help you find the who, what, when and where behind errors in your frontend project. 
Workshop level: Intermediate