Using CSS selectors to get elements in end-to-end tests is the most common way (besides xpath), but it can also be tricky and hard to maintain. One day everything could work fine and another a CSS class could be renamed. Styles could change without touching the business flow and then we could have a problem - we'll need to maintain the tests. Of course, the developers could do those changes for us, but they don't know our scenarios, our tests etc. It would be time-consuming for them, because they don't always know if their changes could affect our tests. And for these problems, I think I might have a solution.

But first let's talk about CSS a bit.

What are the common problems with CSS selectors?

Imagine that one day, you had to write a very ugly selector. The element you wanted to use was nested and the only solution available was to base it on CSS classes and HTML structure. And then, a developer made a little refactor that removed some useless HTML tags, which were of course, used in your selector. But he didn't change the business flow. And guess what will happen? Yes, you're right! The test will fail. Your selector will be broken and will need maintenance.

But let's take a step back and think about what are CSS classes designed for? For sure, not to use them in end-to-end tests. Why? Because they're designed to style elements. Everyday there might be changes in the application that don't affect the business flow - which is the most important part in end-to-end tests - but are related with class names changes. That hurts when we need to maintain a test that didn't involve any user flow changes.

Two examples, one simple solution - find better a mechanism to get elements.

What do I recommend? Read below!

Use data-test-id for help!

For sure, they're controversial but there are two main advantages of using them.

First one is that they're bulletproof. What? I mean, when we use this attribute with an element, no matter if the developer changes the HTML structure or CSS classes, we still get what we want. Unless they remove the element or change the business flow, our test should work fine.

And second, as you may notice, the developer will see that attribute while working with the code. It could help because they can notify us about possible changes or just maintain the tests if needed - using data-test-id makes it easier find occurrences in tests. And if we have more people working on end-to-end tests we can build more reliable solutions. That's what we all want to achieve - always working product:)

More about working closely with developers below:)

But should I use them everywhere?

Nope. Only with the elements used in tests. We don't want a mess in the code where almost every element has this attribute and only a few of them is used in tests. We want to build trust towards the tests and somehow show the devs that their changes could break our work.

Of course, we'll add some code, but with babel or similar solution we'll get rid of data-test-id on production version. Also, you can take a look at facebook where these attributes are used;).

A little bit of extra work can bring us many benefits.

What are the benefits of using them?

For sure, we can build communication between us and developers. How? Talk. If they see this kind of attribute with an element they want to refactor, they have to maintain the test (in the best case) or just notify us that something could affect it. It's beneficial to know when something can break our tests before running them on testing environment. It'll build trust to the tests. They won't fail because of changes which don't affect the business flow. It will help all of us.

The only thing we need to do is give the developers an opportunity and reason to maintain the tests.

Conclusion

Code structure can always change and it shouldn't affect our tests unless the business flow changes. With selectors based on CSS it could. That's why we decided to go with data-test-id which seems like a reliable solution.

They have some shortcomings but overall I think there is more pros. If you use them you'll work closely with devs which could result in other interesting solutions:) Just remember to add them wisely - only in the elements you're using in tests:)

Have a nice day! 🥳