September 25, 2026

TestInspector isolates test data in concurrent runs through a three-tier variable hierarchy — test, suite, and organization scope — where each tier provides a distinct storage and resolution domain that does not share state between parallel executions. Variables defined at test scope exist only for that test run’s lifetime; variables defined at suite scope persist across runs within that suite but are not accessible to tests in other suites; organization-level variables provide shared defaults that individual tests can override without mutating the shared value. This tiered scoping, combined with encrypted storage for secrets and TOTP generation that derives values at runtime without shared state, means concurrent runs do not compete for variable ownership. The result is a test automation system that scales horizontally across parallel CI workers, scheduled trigger windows, and team members running tests simultaneously without producing the intermittent failures that plague shared-state test data approaches.
This guide explains how TestInspector’s variable system works in parallel execution contexts, how built-in variable types like {{ALPHANUMERIC}} and {{TIMESTAMP}} produce naturally isolated test data, how secrets and TOTP variables function without cross-contamination in concurrent runs, and how this compares to managing test data isolation in code-based frameworks. For context on how TestInspector fits into broader QA workflows, see the TestInspector product page and Astaqc’s test automation services. Teams evaluating whether a no-code platform can replace framework-level infrastructure for their use case can engage Astaqc’s software testing services for a capability assessment.
Parallel test execution introduces a class of failures that does not appear in sequential runs: data contention. When two test workers operate on the same data simultaneously without isolation, the results are non-deterministic. Worker A creates a user record with a specific email, Worker B checks whether that email exists and finds it unexpectedly, Worker A’s teardown deletes the record, Worker B’s next step fails with a 404. None of these steps contains a bug; the test logic is correct in isolation. The failure is produced entirely by the concurrent access pattern, and it is intermittent: it only appears when the two workers happen to schedule overlapping operations on the same record.
This category of failure is unusually expensive because it is hard to reproduce and hard to attribute. Intermittent failures that only appear in CI under parallel execution are invisible locally, where tests typically run sequentially. Without trace-level visibility into which operations ran concurrently during the failing run, the diagnosis path involves eliminating sequential ordering as a possible cause, identifying the shared resource, and then determining whether the solution is test data isolation, resource locking, or execution sequencing. For teams using Astaqc’s software testing services, test data isolation problems are among the most common root causes found in flakiness audits of maturing CI pipelines.
The problem compounds as test suites grow. A suite with 20 tests has limited concurrency, and the probability of two specific tests overlapping on the same record is low. A suite with 200 tests running across 8 CI workers has a much higher probability of overlap, and the addition of scheduled trigger windows — smoke tests running every 30 minutes, nightly full regression runs, developer-triggered runs on feature branches — means concurrent access occurs continuously rather than only during CI runs. Managing this at scale requires systematic test data isolation built into the test framework’s variable model, not ad-hoc workarounds applied test-by-test. See Astaqc’s complete software testing guide for a broader treatment of how test isolation fits into a QA strategy.
TestInspector structures variable storage at three levels, each with distinct scoping semantics that prevent parallel runs from sharing mutable state. Understanding which scope to use for which data type is the core mechanism for achieving test data isolation without custom infrastructure.
Test-scope variables are created or captured during a test run and exist only for that run’s lifetime. When a test step executes an HTTP request and captures the response body with {{CAPTURE:userId}}, that captured value is stored in the run’s isolated execution context. A concurrent run of the same test captures its own value into its own isolated context; neither run can read or write the other’s captured values. Test-scope variables are the primary mechanism for working with runtime-generated data such as response IDs, session tokens, and confirmation codes.
Suite-scope variables define configuration values shared across all tests in a suite — base URLs, test environment identifiers, shared API keys. These are read-only during execution: tests can override a suite variable in their local variable block, but the override applies only to that test’s execution and does not persist back to the suite-level definition. Two concurrent runs within the same suite read the same suite variable values but cannot write to them, preventing write conflicts at the suite level.
Organization-scope variables are defaults available to all suites and tests within the organization, also read-only during execution. They are useful for values that are consistent across all environments and tests — organization-wide service endpoints, shared test configuration constants — but inappropriate for test-specific data that changes between runs.
| Variable Scope | Writable During Run? | Shared Between Concurrent Runs? | Use Case |
|---|---|---|---|
| Test scope (captured) | Yes — isolated to run instance | No | Response IDs, session tokens, runtime values |
| Suite scope | No (read-only) | Read-only, no conflict | Base URLs, environment IDs, shared API keys |
| Org scope | No (read-only) | Read-only, no conflict | Organization-wide defaults, shared constants |
Beyond the three tiers, TestInspector provides built-in dynamic variables that produce unique values per execution without requiring any configuration. {{ALPHANUMERIC}} generates a random alphanumeric string on each use — suitable for email addresses, usernames, external reference IDs, and other values that must be unique across concurrent runs. {{TIMESTAMP}} produces the current Unix timestamp in milliseconds, useful for time-sensitive records and ordering assertions. Because these values are generated at execution time within each run’s isolated context, two concurrent runs using {{ALPHANUMERIC}} in the same field position will generate different values, preventing record collision without any test data management infrastructure. For teams scaling from a small suite to a CI-integrated pipeline, this zero-configuration uniqueness is the most practical starting point for test data isolation. See Astaqc’s manual vs. automated testing guide for context on where test data management decisions typically appear in the transition from manual to automated coverage.
Secrets — passwords, third-party API keys, private service credentials — require special handling in parallel execution because they must be available to multiple concurrent run instances simultaneously without being exposed in logs, accessible to unauthorized team members, or mutated by any individual run. TestInspector stores secrets in its encrypted variable system: values are stored encrypted at rest, transmitted to the execution environment using TLS, decrypted within the sandboxed execution context, and injected into test steps at runtime. They are never written to run logs, never visible in the live WebSocket run streaming output, and never persisted in plaintext anywhere in the execution path.
In parallel execution, multiple run instances may request the same secret simultaneously. Each request is handled independently by the variable resolution layer — there is no lock on a secret between concurrent requests, and one run’s use of a secret does not affect another run’s access to the same secret. This is possible because secrets are read-only at the variable level: no test step can overwrite the stored secret value during execution. The encrypted storage resolves each concurrent read independently, returning the same value to each requesting run without state contention.
TOTP variables require a different analysis because TOTP codes are time-dependent and rotate every 30 seconds. The {{TOTP:secret}} syntax takes the base32-encoded TOTP seed — stored encrypted in TestInspector’s variable system — and generates the current TOTP code using HMAC-SHA1 against the current timestamp. The key characteristic for parallel execution is that TOTP generation is stateless: the output is derived entirely from the seed and the current time, with no counter or shared state that changes between calls. Two concurrent runs requesting {{TOTP:secret}} in the same 30-second window will receive the same TOTP code, which is the correct behavior — the code is valid for the current window, and multiple runs legitimately sharing a test account’s TOTP authentication are expected to use the same valid code during that window.
The practical consideration for TOTP in parallel runs is sequencing, not state contention. If two runs are both testing a 2FA login flow against the same test account simultaneously, and both proceed to the step that consumes the TOTP code within the same 30-second window, the authentication service may reject the second login if it implements single-use TOTP validation. This is an application behavior constraint — not a TestInspector limitation — and the resolution is either to use distinct test accounts for parallel runs (each with its own TOTP seed stored as a distinct TestInspector variable) or to schedule concurrent 2FA tests to execute against the same account in separate time windows. For teams managing complex authentication test scenarios, Astaqc’s test automation services include test data architecture review as part of automation strategy engagements.
Code-based frameworks provide flexible mechanisms for test data isolation in parallel execution, but they require the engineering effort to configure and maintain those mechanisms. TestInspector provides isolation through its variable architecture without requiring test configuration code, which changes the cost model significantly for teams without a dedicated automation engineer. The comparison below covers the primary isolation mechanisms and the trade-offs between approaches.
| Capability | TestInspector | Playwright / Selenium |
|---|---|---|
| Per-run unique identifiers | Built-in: {{ALPHANUMERIC}}, {{TIMESTAMP}} — zero configuration | Custom: requires helper function or fixture to generate and inject unique values |
| Secret storage | Encrypted variable storage, never logged | Environment variables or .env files; logging exclusion must be configured explicitly |
| TOTP generation | Built-in: {{TOTP:secret}} with encrypted seed storage | Requires a TOTP library (speakeasy, pyotp) and manual seed management |
| Variable scoping model | Three-tier (test/suite/org), enforced by the platform | Framework-level fixtures (beforeEach/afterEach) or process.env, requiring discipline to not share mutable state |
| Parallel execution isolation enforcement | Automatic: each run instance gets an isolated execution context | Requires explicit configuration of worker isolation (Playwright workers, Selenium Grid session isolation) |
| Captured value scoping | Automatically scoped to the run instance; cannot leak between runs | Global variables or shared state can leak between test contexts if not explicitly reset |
The trade-off favoring code-based frameworks is flexibility: when test data requirements involve complex setup scenarios — pre-populating a database with a specific relational data set, generating test users with specific permission configurations across multiple services — a code-based fixture system gives you the full expressiveness of a programming language to implement that setup. TestInspector’s variable system handles point-in-time data well (unique identifiers, captured values, secrets, TOTP codes) but is not designed for orchestrated database setup sequences. Teams with primarily API and UI test workflows that need per-run unique data will find TestInspector’s built-in isolation sufficient; teams with complex relational data dependencies between tests may need a code-based fixture approach or a dedicated test data management service alongside their test execution platform. For teams evaluating both options, Astaqc’s performance testing and software testing services include test infrastructure architecture assessments that cover this trade-off in the context of a team’s specific application and data model.
Yes, with the caveat that both tests will operate on the same account’s state. If the tests read the account’s data without modifying it, concurrent runs are safe. If both tests create records in the account, both runs will see each other’s records during execution, which can cause assertion failures if a test asserts on a specific record count or list. The resolution is to use {{ALPHANUMERIC}} in any field used for assertion filtering (email prefix, reference ID, record name) so each run’s records are identifiable and assertable independently of what other runs have created.
TestInspector does not have an automatic teardown mechanism for application-level data — cleanup of records created during a test run is the responsibility of the test itself (typically via a DELETE HTTP request step at the end of the test) or of the application environment (reset on each CI deployment). The recommended pattern is to use {{ALPHANUMERIC}}-prefixed records so cleanup steps can filter by prefix to identify records created by the current run, and to structure cleanup as the final step in any test that creates persistent data. This pattern works reliably in parallel runs because each run’s records carry a unique prefix that does not collide with other runs’ records.
If a test step fails before capturing a variable — for example, if the HTTP request returns a 500 status and the response body does not contain the expected field — subsequent steps that reference the captured variable will use an empty string, which will cause those steps to fail as well. TestInspector logs the variable resolution result in the run log, so the cascade of failures from a missing capture is visible in the step-by-step trace. The correct handling is to add an assertion on the HTTP response status before the capture step, so the test fails at the assertion with a clear error message rather than failing silently at downstream steps.
Yes. TestInspector’s variable resolution follows a precedence order: test-level variables override suite-level variables, which override organization-level variables. If an organization-level variable defines a production endpoint and a specific test suite targets a staging environment, a suite-level variable with the same name will override the organization default for all tests in that suite. Individual tests can further override suite variables in their local variable block, making it possible to test against multiple environments within the same organization without changing shared configuration.
Tests that require a specific existing record — a product with a known ID, a user with a specific permission set — should reference that record through a suite or organization variable (e.g., {{KNOWN_PRODUCT_ID}}) rather than creating it during the test. If the record must be created fresh for each run (to avoid state accumulation from previous runs), the recommended approach is to create it in an HTTP request step at the start of the test, capture the returned ID, use it throughout the test, and delete it at the end. This setup-use-teardown pattern within a single test is fully compatible with parallel execution because each run creates its own instance of the required record.
TestInspector supports multiple suites, each of which can define its own variable set targeting a specific environment. A common configuration is one suite per environment — staging suite, production smoke suite — with each suite defining its own base URL and environment-specific credentials. Tests are shared across suites through test references, and the variable overrides at the suite level direct each test to the correct environment when run from that suite. This structure keeps environment configuration organized without duplicating test logic and works cleanly in parallel execution because each suite’s variable set is independent of the others.
TestInspector’s three-tier variable hierarchy — test, suite, and organization scope — means parallel runs never share mutable state. Built-in variables like{{ALPHANUMERIC}}and{{TIMESTAMP}}produce naturally isolated test data on each execution, and encrypted secret storage resolves concurrent requests independently without cross-contamination. Parallel execution at scale becomes a configuration decision, not an infrastructure problem.


Sign up to receive and connect to our newsletter