The habit that separates people who get fast at this from people who stay slow is boring: read the failure before changing anything.
The common instinct is to tweak the selector and run again. That is guessing, and it is slow. The message almost always says what happened; it just says it in an unfamiliar shape.
Failures come in a small number of kinds. Learn to sort them and most red tests explain themselves.
"Element not found" or a timeout looking for something. The framework searched and never found it in time. Three real causes, in the order they actually happen:
- The element arrives later than you looked. This is a timing problem, and the fix is a proper wait, not a longer one.
- Your locator is wrong. Paste it into the browser console and see what it matches.
- The app is broken and never rendered it at all. Check the Console tab for a JavaScript error.
An assertion failure. The best kind. The framework tells you what it expected and what it got: expected "3", received "2". The app ran fine and produced the wrong answer, which is exactly the bug you wrote the test to catch. Read the two values before assuming your test is wrong. Sometimes the test is right and you found something.
"Element not visible" or "not clickable". The element exists but a user could not use it. Something covers it, it has no size, or it is disabled. A leftover invisible overlay from a dialog that did not close is the classic cause.
A stale element. You found the element, the page re-rendered, and your reference now points at something that no longer exists. Common in Selenium and covered in its track.
Now the method. Four questions, in this order.
1. Which test, and which line? Read the test name and the line number. Not the whole file. One line.
2. What did it expect, and what did it get? If the message contains both, you are usually nearly done.
3. Does it fail every time? Run it again. Consistent failure means a real bug or a wrong test. Intermittent failure means timing, and you should read the waiting lecture again.
4. Does it fail alone? Run just this test on its own. If it passes alone but fails in the suite, it is not a timing bug. Another test is leaving state behind, and you have an order dependency.
Question 4 catches something people waste days on. A test failing only inside the suite is a completely different investigation from one failing on its own, and knowing which you have saves the whole afternoon.
One more piece of advice from having got this wrong myself: when a test disagrees with your eyes, believe the test and go look at the DOM. Your eyes see the rendered picture. The test reads the tree. When they disagree, something interesting is true, and it is often the bug.
Remember this: read the message, find the line, then run it alone. Change code last.