Test Environments

A test environment is everything a test runs on. The ISTQB glossary describes it as the hardware, instrumentation, simulators, software tools and other support elements needed to conduct a test. Some teams call it a test bed.

The same build can behave differently in two environments: a refund form that accepts a 4 MB receipt on staging may reject it in production, where a server in front of the application limits upload size. So a result means something only together with its environment: "passed on build 3.8.0 in staging" is evidence; "passed" alone is not.

Why it matters

Teams test outside production for good reasons: customers must not see unfinished work, and tests must not move real money or touch real personal data. But every difference from production is a place where a defect can pass every test and still reach customers, or where a test fails for reasons unrelated to the product.

Knowing the environment tells a tester whether a failed test points to a product defect or to an environment problem, and whether a pass is real evidence. A tester who can say what was tested where, and what differs in production, gives the team an honest picture of the remaining risk.

What a test environment is made of

Think of it as layers around the build under test; each layer is a question you should be able to answer when you plan tests or report a defect.

  • Build: the exact version of every component under test, such as web 3.8.0, build 214.
  • Infrastructure: servers or containers, operating system, the number of instances (running copies of the application); on the client side, browsers and devices.
  • Configuration: settings that change behaviour without changing code, such as feature flags, time zone, locale and limits.
  • Dependencies: databases, queues and third-party services such as payment or SMS, each one real, a provider's sandbox (a test version of the service, run by the provider) or a stub.
  • Data and access: the test data baseline and accounts, plus the logs you can read.

Dev, test, staging and production

Most teams move a change through a chain of environments, each closer to production than the one before. The names are industry usage, not ISTQB terms, and vary: test may be called QA or SIT, staging pre-production or UAT, and small teams often have one environment between development and production.

In a healthy chain the build is created once and that same build is promoted; only the configuration changes. If each environment gets its own build, a pass on staging says little about production. A fix produces a new build, which goes through the chain again.

  • Development: developers' own machines, sometimes also a shared development server; component (unit) tests with mocked dependencies; the fastest feedback and the least like production.
  • Test (QA): shared by testers for system and integration testing on synthetic data that can be reset; new builds arrive often.
  • Staging: as close to production as practical in versions, topology and data volume; for release and acceptance testing and for rehearsing the deployment.
  • Production: real users, data and money; only planned, non-destructive checks after a deployment, with test accounts.
  • Many pipelines also create a short-lived environment for each pull request.
A change moves from development through test and staging to production; one build is promoted from test onwards with only its configuration changing, and each stop is closer to production than the last.
  1. 1Developmentlocal, devDevelopers' machines: component (unit) tests, mocked dependencies

    Gate: merged and built once

  2. 2Testalso called QA or SITSystem and integration testing on synthetic data that can be reset3.8.0+214

    Gate: same build promoted; only configuration changes

  3. 3Stagingalso called pre-production or UATAs close to production as practical: release and acceptance testing, deployment rehearsal3.8.0+214

    Gate: release decision

  4. 4ProductionReal users, data and money: only planned, non-destructive checks after deployment3.8.0+214

Back to step 1 defect found at any stop: fix, then a new build goes through the chain

Fastest feedback, least like productionClosest to real use, costliest place to find a defect

Outside the sequence
  • Per pull requestA short-lived environment, removed when the pull request is merged or closed

Names and number of environments differ by team.

Try it: API Health Checker

Configuration, versions and dependencies

Two environments running the same build differ through their configuration, the versions of the software around the build, and the dependencies it calls. Compare these first when something works in one place and not in another, and record them in an environment record or a version page.

Each line of such a record limits what your tests prove: if staging sends SMS to a stub, you proved that the application asks for a message to be sent, not that a customer receives it.

The ISTQB syllabus treats a test environment as a configuration item: configuration management records its parts, their relationships and their versions. Once approved for testing, that record becomes a baseline that changes only through change control, so earlier results can be reproduced.

  • Configuration usually lives outside the build, in environment variables or files, so it can drift between environments without anyone noticing.
  • Write full versions: PostgreSQL 16 and PostgreSQL 16.4 are different records.
  • Check the deployed build before testing: many applications show it on an about page or a version or health endpoint.
  • Sandboxes often answer faster and more predictably than the real service.

Try it: JSON Diff Try it: Text Diff

Environment parity problems

Environment parity means the environments differ from production as little as possible, and only in ways you know. Martin Fowler's article on continuous integration recommends testing in a clone of the production environment; the Twelve-Factor App calls the goal dev/prod parity and names three gaps to keep small: time, people and tools.

Gaps cause wrong results in both directions: a false pass (a false negative), where the environment hides a defect, and a false failure (a false positive), where a stale build or a sandbox that is down is reported as a product defect. Full parity is rarely possible, so aim for known differences: each gap that could affect the change is closed, tested another way, or recorded as a risk.

  • Time zone: a 20:00 cut-off is tested against the wrong clock.
  • One instance in test, several in production: files or sessions kept on one server go missing.
  • Small data: a report that is instant on 5,000 rows times out on a million.

Try it: Timezone Converter

Worked example: a receipt upload that passed on staging

Release 3.8.0 lets customers attach a receipt of up to 5 MB to a refund request. All 18 test cases passed on staging. Before sign-off, the tester compares the two environment records.

The build is the same, so what was tested is what will ship. Three differences matter for this change:

  • Proxy limit of 2 MB: in production a reverse proxy, a server in front of the application, rejects larger requests. Receipts above 2 MB passed on staging, but production would reject them, typically with HTTP status 413 (Content Too Large), before the application can show its own message. Raise it with DevOps now.
  • One instance storing files on its local disk, against three instances sharing object storage behind a load balancer, which spreads requests across them: the storage that production uses was never exercised, and because the upload and the display of a receipt may reach different servers, anything still kept on one server's disk would be missing. Ask for a staging run with two instances and shared storage, or check right after deployment.
  • Flag off in production: switching it on is a configuration change with its own risk. Test with the flag off too, and agree who switches it on.
  • Payment, SMS and data volume differ too, but the receipt upload does not depend on them: record them as known differences.
Item              staging                  production
----------------  -----------------------  ---------------------------
Build             web 3.8.0+214            web 3.8.0+214
App instances     1                        3, behind a load balancer
Reverse proxy     none                     request body limit 2 MB
File storage      local disk               shared object storage
Database          PostgreSQL 16.4          PostgreSQL 16.4
Time zone         Asia/Riyadh              Asia/Riyadh
refund_receipts   flag on                  flag off until release day
Payment           provider sandbox         live provider
SMS               stub, records messages   live provider
Orders in DB      5,000 synthetic          1.2 million real

Try it: API Response Comparator

Common mistakes

  • Recording "passed" without the build and the environment.
  • Calling staging production-like without ever comparing it with production.
  • Reporting a stale build or a sandbox that is down as a product defect, or dismissing a real defect as "just the environment".
  • Redeploying a shared environment in the middle of a test cycle without telling the people testing on it.
  • Treating a pass against a sandbox or a stub as proof that the real integration works.
  • Using production as a test environment, with real orders, real customers or real personal data.

The QA perspective

Testers rarely own environments; developers or DevOps engineers do. The tester states what the tests need and asks during test planning: which environment and build, what is shared, who fixes it when it breaks, and how does it differ from production? As in the lessons on test design and test implementation, these needs become test environment requirements, and the environment is built and verified before execution. ISO/IEC/IEEE 29119-3 defines a test environment requirements document and a test environment readiness report; agile teams keep the same answers in the test plan or a team wiki.

Write the build and the environment into every result and defect report (the ISTQB syllabus lists the test object and the test environment among a defect report's contents), and when many tests fail at once, check the environment first. Bring the list of known differences to the release decision: "passed on staging; uploads above 2 MB untested against the production proxy" lets the team decide with open eyes.

Practice exercise

Find the parity gaps for a delivery-slot release

Your task

Release 5.2.0 lets customers book a delivery slot for the next day. Booking closes at 20:00 Riyadh time, each slot takes at most 40 bookings, and a confirmation SMS is sent in Arabic or English. All tests passed in the test environment. Which differences in the records below could make production behave differently?

Material
Item              test environment         production
----------------  -----------------------  ---------------------------
Build             web 5.2.0+87             web 5.2.0+87
App instances     1                        2, behind a load balancer
Time zone         UTC                      Asia/Riyadh
Database          PostgreSQL 16.2          PostgreSQL 16.4
delivery_slots    flag on                  flag off until release day
SMS               stub, records messages   live provider
Orders in DB      2,000 synthetic          1.2 million real
Steps
  1. List every line where the two environments differ.
  2. For each difference, decide whether it can change a test result for this release.
  3. For each one that can, choose: align the environment, test another way, or record the risk.
Show the model answer
Model answer

The build is the same, which is good. Six lines differ.

Time zone (high risk): the cut-off was tested on UTC, three hours behind Riyadh. Run the environment in Asia/Riyadh and repeat the tests at 19:59 and 20:00 Riyadh time.

Instances (high risk): the 40-booking limit must hold when two customers book the last place through different servers. Ask how the limit is enforced, and test simultaneous bookings on two instances.

Feature flag (medium): test checkout with the flag off, and agree who switches it on.

SMS stub (medium): delivery is unproven; record the risk, and after release check one Arabic and one English SMS on the team's test numbers.

Data volume (medium): ask whether slot availability was checked on production-sized data. Database 16.2 against 16.4 (low): a minor release within the same major version; record it.

Frequently asked questions

Can we test in production?

Some checks belong there on purpose: smoke tests and health checks right after a deployment, monitoring, and gradual releases such as canary releases. They are planned, non-destructive, use test accounts and are agreed with the team. Testing in production complements testing before release; it does not replace it, and it never uses real customers' data or money to set up tests.

Does every team need all four environments?

No. The number depends on risk, team size and cost. A small team may have local development, one shared test environment and production; a regulated product may add separate environments for performance or acceptance testing. What every team needs is a place where the build is tested close enough to production for the risks that matter, and a clear list of the differences.

Why does a test pass on my machine and fail in the test environment?

For the same reasons staging and production differ, on a smaller scale: different configuration, versions, data, network access or browser. Compare the two setups item by item, starting with the build version and the configuration, before you report a defect or decide the environment is to blame.

References

Practise with Mutqan tools

Compare two API responses (e.g. staging vs production) and list every structural and value difference.

API Testing

Compare two JSON documents semantically and highlight added, removed and changed values.

JSON & Data

Compare two texts line by line or word by word and highlight differences.

Formatting

Check several API health endpoints at once and get status, latency and a pass/fail summary.

API Testing

Convert a date and time between timezones (Riyadh, Amman, Delhi, UTC, New York, London…).

Utilities

Go deeper

Your progress on this topic

Part of the QA Roadmap