In the field of React, we have seen a significant shift in the way we test our components over the past years. While previously it was mainly focused on unit tests, the current standard is more orientated towards making sure your tests are as representative as possible of the experience of your users — behaviour testing.
In all React engineering teams that I’ve worked with so far, behaviour testing has always been a topic of active discussion. Either we were considering adopting it, decided to transition a project’s testing stack towards a more behaviour focused setup, or were already applying them. This is very much in line with how the field has been moving: away from snapshot testing and more towards tests that verify behaviour.
But while this is a trend in the field, it doesn’t mean that every React developer or team can follow those trends whenever they appear. For some projects and teams, it’s not a realistic situation to throw away the entire existing setup to adopt a new concept like behaviour testing. This isn’t a problem in itself, but it does mean that not every React developer will be as familiar with the behaviour testing
For those developers, who are more inexperienced and new to behaviour testing, it’s not crazy to have questions and uncertainties about how to approach implementing these kinds of tests. To help them, this article will serve as an introductory guide to behaviour testing in React. It will answer a set of fundamental questions that I’ve experienced during the time that I’ve worked with behaviour testing. This information will provide you with a solid foundation to understand behaviour testing in React, what the focus is, why to do it, whether it makes sense for your use cases, and to get started yourself.
What is behaviour testing?
First of all, let’s start with the most basic thing: what is behaviour testing? Well, it’s a form of frontend testing where the goal is to verify the behaviour of React components. But in particular, the focus is on doing this in a way that’s most representative of how the end-users also experience these behaviours.
Behaviour testing is based on the principles that the end-user experience of our web application is most important. And part of this is making sure that our web application works as expected when the end-user interacts with it. So it does what it should do, show what it should show, update the UI appropriately: behave as expected.
Where does behaviour testing stand in the testing spectrum?
In my current team, we try to do behaviour testing as much as possible, but there’s still some legacy testing code laying around here and there. While this is normally not a big problem, it is for newcomers who use existing code as points of reference. Coincidentally, we had two new developers join our team in recent months.
Encountering ‘normal’ unit tests, snapshot tests, E2E tests, and then behaviour tests altogether can be overwhelming. It makes you lose overview and start questioning a lot of things about the setup, like why there are so many forms of tests, which form should use in what scenarios, and who is responsible for what. Unfortunately, this is exactly what happened.
Most likely, this isn’t an uncommon setup and situation to have in the field of React teams. Therefore, it’s important to be clear about the role of behaviour testing and where it stands. In the end, behaviour tests are a form of unit tests. Testing wise, they’re not very different from ‘normal’ unit tests and snapshot tests. But they mostly differ in the way they’re implemented and how verifications are performed.
What’s the difference between behaviour tests and E2E tests?
For someone relatively new to the concept of behaviour testing, the difference between behaviour and E2E tests can be very difficult to identify. Although we say that behaviour tests are unit tests, they still run the actual React components and interact with them like end-users. From an inexperienced one’s perspective, this can be extremely similar to an E2E test.
However, there are some subtle but crucial differences.
- Rendering environment. Although we run and render the React code in both types of tests, behaviour tests aren’t run in an actual browser. This makes them more lightweight to run compared to E2E tests, which means they’re more scalable.
- Connections. The main idea behind E2E testing is simulating the real user experience in the entire application. In our case, the React applications are only a small part of the entire product. So E2E tests are meant to verify the connections between the React code and the application around it, which behaviour tests can’t.
- Responsibility. Based on the previous point, E2E tests and behaviour tests have different scopes and goals. This means that in certain engineering teams different people are responsible for different types of tests. We have a similar situation, although not as clear-cut.
Do behaviour tests replace “normal” unit tests and snapshot tests?
Yes and no, the real answer is that it depends. All of the different forms of tests have their purposes and use cases, even snapshot tests. Different scenarios will call for different forms of unit tests.
Does this mean that you should throw away all your existing unit tests and replace them with behaviour tests?
No, because there are still use cases for the others forms. Some existing tests might not even be convertible to a behaviour test. Doing so for the sake of migrating isn’t only a waste of time and effort, but the resulting tests might not even make sense. This can ultimately even lower the quality and value of the test.
But does this mean that behaviour testing is most often the most appropriate form of unit testing?
Yes, behaviour testing should be able to cover most of your use cases. The number of scenarios in which other forms of unit tests are more appropriate and can provide more value is very low. Either they’re very specific or the focus of those scenarios is more targeted towards verifying code flows.
Do you need to use React Testing Library for behaviour testing in React?
No, that’s not necessary. In general, behaviour testing as a concept is framework and library agnostic. This means that you can create behaviour tests no matter the stack you’re using. However, React Testing Library is tailored towards behaviour testing in React. The tools and utilities it provides make the job a whole lot easier compared to other testing libraries.
This makes it the preferred choice when working with behaviour testing in React. But it’s still definitely possible to perform behaviour testing using other testing libraries like Enzyme. The only thing is that it will take more effort to do it properly and it’s easier to mess up. This means you’ll have to be more thorough with your tests and pay attention to a lot more things.
Are behaviour tests more complex to implement?
In general, behaviour tests are more complex and require more effort to implement compared to your typical unit or snapshot tests. This is because the goal and scope of behaviour tests are different from the other forms of tests. Behaviour testing is more focused on end-user interactions, while other types of unit tests are oftentimes focused on verifying code flows.
For this reason, there are a lot more aspects to focus on in your tests. While implementing typical unit tests only require focusing on the flow of the code, behaviour tests have to focus on making sure they’re representative of how end-users experience it. This covers all the aspects related to tests, like identifying UI elements, trigger interactions, and verifying the results. All of this makes behaviour tests more complex to implement properly.
But while behaviour tests require more time and effort to implement, they can hold way more value compared to your usual unit tests. If implemented properly, behaviour tests will provide you with a way higher degree of guarantee and safety that your application is working as expected from the perspective of your user.
Can I do behaviour testing in a project that doesn’t have them?
Yes. As mentioned a few times in this article already, behaviour testing is not tied towards any library, framework, or technology. This means that there aren’t any technical requirements, so you can add behaviour tests to any existing project with ease.
In a project without React Testing Library, there are two options. The first is to implement behaviour tests in the testing library that’s already present. Although this will be more difficult to do, it means that you don’t have to introduce another dependency to the project which you have to maintain.
The other option is to add React Testing Library and introduce the new tests gradually to the project. While this introduces another dependency to the project, it allows you to make use of a library that’s optimized for the task at hand. This will give you a head start in doing it properly.
Regardless of which option you choose, it’s important to keep in mind that you’re adding an additional concept to the project that needs to be adopted, learned, and maintained by the developers. Behaviour testing and all of its code are no exception to this. If you also decide to maintain multiple testing strategies in a project, this effect is amplified even more.
Introducing behaviour testing to a project has a lot of benefits, but it’s also important to consider the increased burden in development, maintenance, and testing.
Behaviour testing has become more and more relevant in the field of React development over the past years. Nowadays, it’s an important tool to have in your skillset as a React developer. Understanding and knowledge of the topic will be relevant in a lot of scenarios. However, not every developer will have equal familiarity and mastery of behaviour testing.
To bridge the gaps for those developers, this article discussed a set of questions related to behaviour testing in React based on my experience in multiple React engineering teams. These questions together with their respective answers serve as an introductory guide to this topic. By laying out the fundamentals, you can create a solid understanding of the topic and build on top of it in the future.