adamwitko 🖐💻

The simple ramblings of an often grumpy developer.

Why I dislike custom HTML attributes for tests

December 1, 2020

Ask any member of my team if Adam likes using data- attributes in his tests and I can foresee the answer you will get.

He hates them. - His Team

I agree, I hate them. I know, I know, that is quite an emotion to have over such a little thing like a data-, but hear me out.

What are data- attributes?

A data- attribute is a unique and custom attribute specified on HTML elements for use in automated tests (usualy). Many different testing frameworks may have the similar concept such as Cypress.io that talks about data-cy attributes. I will talk about data-testid as an example given my recent React testing development exposure.

If you were to take a snippet of HTML using data-testid attributes it may look like the following:

<div>
<button name="previous">Previous</button>
<button name="next">Next</button>
</div>

All looks good so far, nothing too controversial. The markup is simple and standard for two HTML buttons.

What is the problem?

My main gripe with data-testid attributes is how they are often abused and used as a cheap way to select HTML elements. When there are useful selectors such as selecting by text, by role, by element type, why would you want to rely on a custom attribute that exists purely for your test?

A good test is one that interacts with your application as a user would interact with it. This means you should be interacting with your appication in the same way a customer would.

Attributes such as data-testid are not how users interact with your application. They are there as a way to help you out as the writer of tests when no other selector will suffice. So, in the previous example of two buttons, you should prefer to select by the visual aspects of the element if you can, or by as widely supported and accesible identifier.

Here are some selector examples using the Testing Library, but you will find similar in many other testing libraries such as TestCafe, Enzyme, and Cypress.io. CSS selector support is quite common, but some of these libraries may offer first-class API abstractions on selecting elements.

const container = /* render of your html */
const button = getByRole(container, 'button', { name: 'first' })
const button = getByText(container, 'first')

Easy, right? Well, I have witnessed these selectors being stepped over in preference for data-testid attributes:

<div>
<button data-testid="first" name="first">First</button>
<button data-testid="second" name="second">Second</button>
</div>
const button = getByTestId(container, 'first')

Some guides or best practice blog posts will talk about using these attributes and selecting them over standard means. I do not believe they have your best interest at heart when you are aiming to create maintanable test suites that represent real user interaction.

What is the solution?

Only use data- attributes when it is your only option. Prefer selectors that are accessible to the majority of techonologies such as by text, roles, display values, labels. Then move down to more unusual selectors that have limited HTML element support.

If you find yourself reaching for data- attributes more and more, step back and see if there is a better way to design your markup. By rethinking your markup you may improve your testing experience but also the experience for your users. Those who utilise accessibility features should also benefit. This is a gain for all consumers of your application.

If you are reviewing code that is using these attributes, call out a better way to select the HTML elements. Push your peers for common selector usage. Try to learn about the testing library APIs and how they can be used to do what you require. Don't jump straight to custom attributes.

Conclusion

I have only scratched the surface of a testing problem that I believe can grow into a pile of testing mess. Some may say it is an inconsequential descision to go with dcustom attributes or not, but I think they are missing the point that using these attributes for testing purposes only describes a bigger problem with your approach to designing your application.

Down with data- attributes, up with standard HTML and selectors that are available for all.

Contact me