Getting more value from tests with Angular Testing Library
We’ve been using Angular Testing Library and we love it. If you’re looking to write integration tests, but not too many of them, it could be what you’re looking for.
Even better, we’re happy to share our lessons learned to save you a bit of time. Take a look at our key findings and see if you could apply this library to your own projects.
What is the Angular Testing Library?
The Angular Testing Library (ATL) is a streamlined, lightweight way to test your Angular components. It’s built on the common-sense philosophy that testing which emulates how products are used in real life produces greater confidence in your software.
For one thing, that means working with DOM elements themselves instead of instances of Angular components. But that sounds familiar, doesn’t it? How does this library differ from others in the grand scheme of things?
React Testing Library vs Angular Testing Library: What’s different?
Angular, owned by Google, and Facebook’s React represent two different ideas of how a website should be built.
Angular is a framework, it gives you a command line interface you can use, for example, to create a new component template. You’ll get the component code, the style file, the component’s HTML, and (importantly) a skeleton test file. Using these, you create your modules with greater support.
React is a JavaScript library you can use to generate HTML, its philosophy is much simpler by comparison. It lets you get from JavaScript to creating HTML as fast as possible. It also contains the concept of virtual DOM, where you can make lots of small changes to the HTML on the page and have them all batched up for you.
ATL was ported from Kent C. Dodds’ React Testing Library (RTL). Being in the same area, they effectively perform the same task for components written in Angular or React respectively.
Sorry to interrupt…
If you like what you've read so far, join us on LinkedIn to talk all things digital product development with our team of experts.
Why use Angular Testing Library?
The benefits of using ATL are speed and confidence. Once you’ve put the time in to write your tests (you’ll be dealing with more state transitions and complex events) it takes less time overall to rewrite tests in response to changing components.
As we’ll discuss shortly, it also encourages you to test in a way that mirrors user behaviour, but for the most part it’s simply really straightforward to pick up. ATL needs less setup, less code for each test.
If you’re used to coding in React, you’ll also find the similarities with RTL are so striking that simple muscle memory will guide you through the process. The syntax is largely identical so you get started with minimal disruption to your daily flow.
These similarities go deeper. Knowing how to write your RTL tests for React code can shape your approach to writing ATL tests in Angular.
Get extra help writing Angular code
Since Angular is a framework, projects built in it come pre-loaded with two different test runners. The first is an end-to-end test runner called Protractor, the second is a unit test runner called Karma.
When you create your component, the command line interface gives you a spec file, an automated test file which checks the component’s bare bones functionality using ‘ng g c <component-name>’.
Because React doesn’t come with a command line interface out of the box, create-react-app gives you the first test to copy and paste. Angular will create a test with the right naming for each component, saving wear and tear on your Ctrl, C, and V keys.
However, the intertwined destinies of Angular and React mean it’s still hard to talk about one without the other.
Integration testing focus
ATL, just like RTL, encourages you to write integration tests over unit tests. Instead of writing smaller, fiddly tests unit by unit, you’re testing how a component and its children work together. How do they create the rendered DOM output your test interacts with?
The front-end focus is key here. Back-end code has well-specified inputs and outputs, once you’ve written your unit you may never need to change it. Front-end components (which we mostly work with) aren’t so fixed, you’ll often find yourself moving them in and out of one another, restructuring them.
Then there’s the human factor. Humans break things. In the front end, you need to test the kind of interactions a machine couldn’t possibly dream of. ATL incorporates everything a user can see and do on a page.
It’s not like testing an API where you can anticipate input and output strings. An integration test using ATL behaves like users, beyond just asking, ‘have they put the data in the field?’
Instead, you’re seeing if the HTML elements which make up this part of the interface are properly connected. You miss that by interacting directly with the methods and properties of the underlying component.
Developers more used to server-side work might not gel with this methodology, but we relish the challenge of user-facing stuff. It’s not fast, but it’s thorough and it creates robust apps that survive contact with people.
Integration testing vs unit testing vs end-to-end testing
We’ve found integration testing makes tests more useful, more quickly. The bigger the integration test, the more code we can rewrite inside, while the test can still pass. The smaller the test, the more you have to change the test while you rewrite the code, which obviously doesn’t scale well.
Applying this principle to Angular code, it lets you do more than just extend the tests you’re given for free if you don’t think those tests are looking at the right things.
More importantly, integration testing strikes the right balance between unit testing and end-to-end testing. As we’ve discussed, unit testing is great when you want to know if one element works in isolation, but becomes less useful for the kind of complex projects we tend to work on.
End-to-end testing, meanwhile, simulates and renders a copy of the actual front-end environment users will see. It’s still automated, but it automates everything from the movement of a mouse to the pressing of keys.
Now, we’re the first to champion properly investing in testing, but not to the point of overkill and wasted budget. We’ve got nothing against end-to-end testing when duty calls. But if you can do an end-to-end job with integration testing, simulating the process and flow rather than the environment itself, that’s a fantastic compromise.
The Fluent approach: Better testing for better digital products
All this has been music to our ears. The decision to use a testing library, rather than simply making do with the tools Angular gives us for free, lets us apply industry best practice. We can make decisions based on where development is really at, rather than taking a ‘good enough’ approach.
That’s where we found ATL gelled so well with the way we work. Ensuring all our projects have a bespoke testing library lets us stay proactive and meticulously focused on a quality output for clients.
After all, instead of this:
…Wouldn’t you rather have this:
Using these instructions right here, you can make it happen. Try it for yourself.
Always moving, always learning
With all this glowing praise for ATL, we bet you’re eager to see our next project which used it? Well… we're currently testing an alternative approach so stay tuned for a future piece to find out what we’re using now. But this blog has hopefully given you some tips we picked up to save you time on trial and error. We’re always moving forward, but always more than happy to share the best of what we find along the way.
Want more tips on digital product development from people at the cutting edge? Follow Fluent on LinkedIn and keep learning
Ready to solve your problems?
We'll help meet the challenges facing your growing business. Get in touch and tell us what you need, the team can't wait to hear from you.