Test your DOM Markup with Data Attributes
It’s no secret that as developers we forget to make tests a first class citizen of our applications. We don’t write enough unit tests and let tests become “old tests.” For this myself I’m guilty.
A little while ago while scrolling through my Twitter timeline, I came across a neat pattern that deserves more recognition. Test with data attributes.
Here’s your current test:
// <span class="email">Welcome!</span> // <input class="email" type="email" value="firstname.lastname@example.org" /> // <input id="the-password" type="password" value="hunter12" /> expect($('.greeting').text()).toBe('Welcome!')); expect($('input[type="email"]').val()).toBe('hello@world')); expect($('#the-password').val()).toBe('hunter12'));
And here’s the problem. When you update your design or change the markup, your tests will most likely break. Element IDs, CSS selectors, and attributes are volatile to tests. How do we solve this problem and reduce technical debt?Use data attributes to designate testing selectors 👏
// <span data-test="greeting" class="email">Welcome!</span> // <input data-test="email" class="email" type="email" value="email@example.com" /> // <input data-test="password" id="the-password" type="password" value="hunter12" /> expect($('[data-test="greeting"]').text()).toBe('Welcome!')); expect($('[data-test="email"]').val()).toBe('hello@world')); expect($('[data-test="password"]').val()).toBe('hunter12'));
This simple change reduces the amount of times you have to update your tests when the UI changes. By using data attributes, we deliver the following:
- More reliable tests with zero impact because we know which UI is coupled to tests before they break.
- Reusable structures for selecting which elements to test.
- Avoiding loss of time spent debugging and updating tests.
This is important because it allows us to update our user interface, or change styles, while minimizing the impact that will have on our tests. This means that we will spend less time updating tests, and more time focusing on the next task at hand.If I’ve just sold you on this pattern, then I’ve done my job. Having seen this issue come up time after time I recalled this awesome pattern. Feel free to share any other patterns or tips for building reliable tests without technical debt.
Cover image by Johannes Plenio.