Blog
Preconditions in Test Cases: What They Are, How to Write

Abhilash
Published on

Table of contents
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum
Most test cases don’t fail at the start or the end. They fail somewhere in the middle. The test starts fine, gets a few steps in, then hits something the author assumed was true but never checked. The user was already logged out. The basket still had items from the last run. The currency was set to the wrong country.
The test fails, the team assumes the app is broken, and an hour later someone works out that the precondition was wrong, not the app.
That’s where a lot of wasted testing time goes. And most guides only give preconditions in test cases a couple of lines and a quick example.
In this guide, we’ll cover what preconditions are, why they decide whether your tests are reliable or flaky, the five types you need to handle, how to write them well, and how AI is changing the way they’re set up and checked.
What is a Precondition in a Test Case
A precondition in a test case is something that has to be true before the test can start. It might be a state, some data, a setting or another system being available. It isn’t part of what the test checks. It’s what the test stands on.
Take a test for “user can update their profile photo”. Before it can run:
A user account has to exist
The user has to be logged in
The app has to be on the profile page
There has to be an image file to upload
None of these are what the test checks. They just have to be true for the test to work.
The simplest way to think about it: a precondition is something the test relies on but doesn’t test. If it isn’t true, the test can’t run properly.
And if the test doesn’t check it, a failure could mean the app broke, or it could just mean the setup was wrong.
Here’s where preconditions sit in a typical test case:
Field | Example |
|---|---|
Test case ID | TC-PROF-012 |
Title | User can update their profile photo |
Preconditions | An active user account exists. The user is logged in and on the Profile page. A JPG under 2MB is available to upload. |
Test steps | Click “Change photo”, choose the file, click “Save” |
Expected result | The new photo shows on the profile and in the header |
Postconditions | The profile record stores the new photo |
Why Preconditions in Test Cases Matter
Preconditions can look like admin. They’re not. A lot of what makes a test suite healthy depends on them.
Why It Matters | What Goes Wrong Without Clear Preconditions |
|---|---|
Tests can run on their own | Tests rely on whatever the last test left behind, so they can’t run alone or in parallel, and they’re hard to debug |
Fewer flaky tests | Most “flaky” tests have hidden preconditions that are sometimes true and sometimes not. Write them down and check them, and the test becomes predictable |
Faster triage | The first question after a failure is “was the setup right?”. Tests that check their own preconditions answer that straight away |
Traceability | Without clear preconditions, it’s hard to link a test to a requirement, so teams end up rebuilding that link during audits |
Reliable automation | Automated tests that can’t set up their own preconditions break every time the environment changes |
The Five Types of Preconditions
Most guides treat preconditions as one thing. In practice, there are five types, and each one is written differently and breaks in different ways.
Type | What It Covers | Example | Why It Breaks |
|---|---|---|---|
Data | Records and data that need to exist | “An active customer record exists” | The most common cause of flaky tests, because it depends on test data, not the app |
State | Where the app or session needs to be | “The user is logged in as a Finance Manager on the Approvals dashboard” | The biggest cause of failures in automated tests, from navigation changes, timeouts and login issues |
Environment | The technical environment the test runs in | “The environment is UAT-2 and feature flag X is on” | The right test runs in the wrong environment, which is easy to miss and slow to debug |
Configuration | Settings the app needs | “The tax engine is set up for UK VAT” | Especially important in ERP and enterprise apps, where the setup is what customers actually use |
Dependencies | Other systems or tests that need to be ready | “The credit check API is reachable” | Common in integration testing, where the test relies on other systems being in a known state |
One test usually has preconditions from three to five of these types. Covering all five across your suite is a good sign your testing is in good shape.
What a Good Precondition Looks Like
Good preconditions in test cases have the same things in common, whatever type they are.
Specific: “User is logged in” is too vague. “User is logged in as a Procurement Manager with multi-factor authentication turned on” tells you exactly what you need.
Checkable: if you can’t check it, it’s just an assumption. A good precondition is something the test can confirm.
One thing per line: if you bundle several conditions together, you can’t tell which one failed.
Not dependent on test order: it shouldn’t rely on what ran before. If a session or data needs to exist, say so.
Easy to set up automatically: it can be created by code, an API call or a fixture, not just by someone clicking through the app.
Only what matters: leave out anything that doesn’t affect the result. You don’t need to describe the whole app.
How to Write Preconditions in Test Cases - Step by Step
Work Out What the Test Is Actually Checking
A login test checks logging in. A profile photo test checks updating the photo.
Once you know what’s being tested, it’s easy to see what’s just setup.
List Every Assumption the Test Makes
Go through the steps, and at each one ask, “what has to already be true here?”.
Every answer is a precondition.
Sort Each One into a Type
Put each precondition into one of the five types. The type tells you how to write it and how it’s likely to break.
Make Each One Specific and Checkable
Turn “user is on the right screen” into “the user is logged in as a Sales Manager and is on the Quotes dashboard with the Q2 filter applied”.
Check Each One Can Be Set Up Automatically
If a precondition can’t be created by code, an API or a fixture, decide how you’ll handle it. Anything that needs someone to do it by hand will hold your automation back.
Test Them Against Different Run Orders
Read your preconditions and imagine the test running first, last, in parallel with five others, and on a brand-new environment. If any precondition wouldn’t hold in all four, fix it.
Weak vs Strong Precondition Examples
Here’s the difference between a vague precondition and a useful one.
Test | Weak | Strong |
|---|---|---|
Login | “User is logged in.” | “A user account exists with email procurement.lead@example.com, the Procurement Manager role and active status, and the user has logged in through the normal login flow in this session.” |
Order creation | “Customer exists.” | “A customer record exists with ID 88234, a UK billing address, currency GBP, a credit limit of at least £5,000 and at least one delivery address.” |
Approval workflow | “Approval workflow is set up.” | “The Purchase Requisition workflow has two approval levels: the line manager approves up to £10,000 and a finance manager approves anything above that. Both approvers exist and are active.” |
Integration | “The downstream system is available.” | “The tax calculation service is reachable on UAT at /tax/v2/calculate and returns a 200 status within two seconds.” |
The strong versions are longer because they say what actually matters. Writing it properly once saves your team hours of debugging over the life of the test.
Also read: 100+ Login Page Test Cases: Functional, Security and API Testing.
Common Mistakes When Writing Preconditions
Mistake | Why It’s a Problem | What to Do Instead |
|---|---|---|
Mixing up preconditions and setup steps | Setup steps are the actions. The precondition is the result. Mixing them blurs what the test is checking | Write the state you need, then the steps that create it |
Relying on the last test | Test 2 assumes Test 1 left the user logged in, which only shows up when Test 2 runs alone and fails | Give every test its own preconditions |
Bundling preconditions | “Logged in, on the dashboard, with three saved searches” is three things, so a failure can’t say which one was missing | One condition per line |
Listing everything | Conditions that don’t affect the result are just noise | Only list what matters to the test |
Only writing them for people | If a precondition can’t be set up by code, someone has to do it by hand every time | Make every precondition automatable |
Never checking them | The test is exposed to environment changes | Check preconditions before the main test runs |
Copying the same preconditions everywhere | Thirty tests with the same five preconditions means thirty places to update | Move shared preconditions into a fixture or reusable component |
Preconditions vs Postconditions, Assumptions and Setup Steps
These four get mixed up a lot. Keeping them separate makes your test cases much clearer.
Term | What It Means | Example |
|---|---|---|
Precondition | What must be true before the test runs | “The user is logged in as an admin” |
Postcondition | What should be true after the test passes | “The new user appears in the user list” |
Assumption | Something the test relies on but never checks. Every assumption you find should become a checked precondition | “The email service is working” |
Setup step | The action that creates a precondition | “Log in with the admin account” |
Put simply, the setup step is the action and the precondition is the result. A good test case names all four where they apply, which makes it easier to read, debug and defend in an audit.
Preconditions in BDD and Gherkin
In Behaviour-Driven Development, and the Gherkin syntax used by tools like Cucumber and SpecFlow, preconditions go in the Given steps.
When several scenarios share the same preconditions, put them in a Background block, so they’re written once and run before each scenario.
Refer our article on BDD vs TDD to know the difference of Test-Driven and Behaviour-Driven Development in detail with practical examples.
Preconditions in Automated Tests
In automated testing, preconditions move from the test case description into code or configuration. Good automated suites tend to use these patterns.
Fixtures and Setup Methods
Framework hooks like setUp, BeforeEach or beforeAll set up preconditions before each test, so the test itself can assume they’re in place.
Test Data Builders
Builders create the data a test needs in one readable call. “Create a customer with a £10,000 credit limit in GBP” replaces a long list of manual inserts.
Set Up Through the API
Where you can, create preconditions through the app’s own APIs instead of clicking through the UI. It’s faster, more reliable and doesn’t break when the screens change.
Reusable Components
On platforms that support composable testing, common starting points, like an Order to Cash starting state or a new employee being onboarded, come as reusable building blocks you configure rather than write from scratch.
Checking Preconditions First
Good suites check their preconditions before the main test runs. That way, a setup problem shows up as a setup failure, not a misleading test failure.
How AI is Changing Preconditions in Test Cases
Preconditions used to be entirely down to whoever wrote the test. AI is changing that in a few ways:
Spotting Missing Preconditions
When AI drafts tests from requirements or user stories, it can include the setup each test needs, like a login state or a configuration setting someone might forget, for your team to review.
Test Data on Demand
AI test data generation creates realistic data with the details a test needs, so “I need a customer with these details” can be done automatically.
Fixing Broken Paths to a State
When the app changes and the path to a state precondition breaks, like a renamed button or a moved dashboard, AI can suggest a fix for your team to accept or reject.
Plain-Language Preconditions
When preconditions are written in plain language like the rest of the test, business users and product owners can review them too, not just the assertions.
How Virtuoso QA Handles Preconditions
Virtuoso QA makes preconditions clear, easy to set up and reliable.
Here’s how:
Plain English preconditions: you write preconditions in plain English alongside the rest of the test, so state, data and setup can be reviewed by the whole team, not locked away in code.
Preconditions drafted with the test: Touchstone reads your requirements and Jira stories and drafts tests from them, including the setup each test needs, showing the source for each one. A named person approves every requirement before anything gets built.
Test data on demand: AI test data generation creates the data each test needs, realistic and parameterised, without using real customer data.
Reusable preconditions: composable libraries include ready-made starting states for business processes like Order to Cash and Procure to Pay in Dynamics 365 and SAP, so you configure them instead of writing them.
Fixes you review: when the UI changes and the path to a state breaks, Virtuoso QA suggests a fix for your team to accept or reject, so preconditions keep working and nothing changes without someone checking it.
UI and API in one test: API calls and UI steps sit in the same journey, so you can set up preconditions through the API and test through the UI without switching tools.
Clear setup failures: every step records screenshots and data, so when a precondition doesn’t hold, you see it straight away instead of chasing a misleading failure.
To see how AI drafts tests, test data and setup while your team stays in control, take a look at Virtuoso QA’s AI-powered test automation.
Related Reads
Preconditions in Test Cases FAQs
How is a Precondition Different From a Setup Step
How Do You Write a Good Precondition
What is the Difference Between a Precondition and an Assumption
How Do Preconditions Affect Test Independence
Can Preconditions Be Automated
How Does AI Help With Preconditions












