How to Write Test Cases That Don’t Suck

Published on July 15, 2025

Software testing is an indispensable part of the software development life cycle — it helps ensure that the end product meets its intended requirements and functions properly.

To achieve this goal QAs write test cases to cover all conditions — negative, positive, boundary, etc. While explicitly written test cases have been the traditional approach, they fall short in meeting the evolving demands of the modern software development landscape. Let’s talk about the shortcomings of explicit test cases, why they generally are not the best choice for effective software testing, and why using “declarative” test cases could work better. But before we do, subscribe and interact with the article in some way for me, please!

First — here’s an example of an explicit test case: testing a basic login for a banking application

Scenario: Verify that the login for web banking works

  1. Open the web browser (Google Chrome).
  2. Navigate to the application’s login page by typing “https://www.exampleapp.com/login" into the browser’s address bar and pressing Enter.
  3. Verify that the login page has loaded completely by checking for the presence of the HTML element with the ID “login-form.”
  4. Enter the username into the input field with the ID “username” by clicking on it and typing “testuser”.
  5. Enter the password into the input field with the ID “password” by clicking on it and typing “testpassword”.
  6. Click on the “Login” button with the ID “login-button.”
  7. Wait for the application to process the login request and redirect to the user’s dashboard.
  8. Verify that the user’s dashboard has loaded completely by checking for the presence of various HTML elements, including but not limited to profile picture, username, and navigation menu.
  9. Verify that the user’s balance is displayed correctly by locating the element with the ID “balance” and comparing its value with the expected value “ $500.00.”
  10. Log out of the application by clicking on the “Logout” link or button.
  11. Wait for the application to process the logout request and redirect back to the login page.
  12. Verify that the login page has loaded completely by checking for the presence of the HTML element with the ID “login-form.”
  13. Close the web browser.

This explicit test case provides a step-by-step description of how to test the login functionality. While the level of detail may appear to be great as “anyone” could now test this functionality, it casues more problems than it solves, such as:

Lack of Flexibility

Explicit test cases are often rigid and lack the flexibility needed in dynamic software development environments. In an era where changes to requirements and features are frequent, explicit test cases can become a burden, requiring substantial rework with each alteration. Their step-by-step nature makes them ill-suited for adapting to the changing demands of a project. They’re also brittle — let’s say the balance wasn’t $500.00 on the nose. What happens? That step fails even though the balance might be correct? If the balance is different you might go try to update it, only to find that it becomes a:

Maintenance Nightmare

Maintaining explicit test cases can be a real nightmare. As software evolves and grows, explicit test cases tend to accumulate details and dependencies on the current system state, like the $500.00 example. This leads to a situation where minor changes in the application can render a large portion of the test suite obsolete. Testers must invest significant time and effort in keeping these test cases up-to-date, which can be both time-consuming and frustrating, and is ultimately:

Inefficient

Explicit test cases can be inefficient in terms of execution. Since they specify every single action, they can lead to duplicated efforts and actions in different test cases. This redundancy not only increases the execution time but also makes the test suite harder to maintain and understand. At a certain point a QA might not bother trying to understand, leading to:

Reduced Abstraction

Explicit test cases often fail to abstract the essence of what needs to be tested. Testers get bogged down in the nitty-gritty details, making it challenging to focus on the big picture and the core functionality being tested. This lack of abstraction can result in unnecessarily complex and lengthy test cases. This ultimately boils down to:

Bad Test Design Quality

When using explicit test cases, testers often get lost in the step-by-step procedure and lose sight of the overall test design. Test case design becomes a mere checklist of actions rather than a thoughtful evaluation of what needs to be tested. This leads to suboptimal test coverage and can result in crucial areas being overlooked.

So, what would “declarative” test design look like? Take a look:

  1. Open the web browser and navigate to the application’s login page.
  2. Log in using valid credentials (stored in our credential management system).
  3. Verify that the user is redirected to their dashboard.
  4. Ensure that the user’s balance is displayed correctly based on recent transactions.
  5. Log out and verify you are returned to the login page.
  6. Close the web browser.

We’ve reduced the number of steps to 6 from 13, and more importantly, engaged the tester by making them think through appropriate test results instead of just “following the script”. Maintenance is reduced as following test cases can be below this in the hierarchy and not inherit the steps, saving untold amounts of time and effort.

Wrap Up

While explicit test cases have their place in certain scenarios, such as when outsourcing testing to a third party that does not understand your application or use cases, they are otherwise inadequate for the demands of modern software testing. Their rigidity, maintenance challenges, inefficiency, lack of abstraction, and lack of tester engagement makes them subpar for agile and dynamic software development environments. To meet the evolving needs of the industry, testers are better served by exploring more flexible and maintainable testing approaches, such as declarative test case writing, which can offer the adaptability and efficiency required to effectively test software in today’s fast-paced development landscape.

If you liked the article, please subscribe and interact with the article in some way for me!