Test preview environments
A preview environment is a full Zuplo deployment of a branch, on the same edge network as production, at its own URL. That makes it the highest-fidelity place to run your test suite before a change merges — closer to production than any local server, and without the queueing and drift of a shared staging environment.
Because zuplo test takes the target as a flag, the files you run against
http://localhost:9000 are the files you run against the preview URL. Nothing
in the suite changes.
How branches become environments
Push a branch to a connected repository and Zuplo deploys it:
- The repository's default branch deploys to Production.
- Every other branch deploys to a Preview environment with its own URL.
For the full mapping, see branch-based deployments. For how preview environments differ from working copies, see environments.
Get the URL into your tests
Preview URLs are derived from the branch name and project, so hard-coding one is a maintenance problem. Read the URL from the environment instead.
From the Zuplo GitHub integration
The integration reports a GitHub Deployment for each build, and the deployment
status carries the environment URL. In a workflow triggered by the
deployment_status event, that value is
github.event.deployment_status.environment_url. This is the mechanism used in
testing GitHub deployments, and it is the
approach to prefer: no URL construction, and the tests cannot start before the
deployment exists.
From your own pipeline
If you deploy from your own CI with zuplo deploy, capture the URL from the
deploy command's output and pass it through:
Code
For the complete workflow, see GitHub Actions: deploy and test. For pipeline patterns for other providers, see custom CI/CD.
Wait for the environment before testing
A deployment reporting success is not the same as a gateway serving traffic, and the gap between the two is the single most common cause of "flaky" gateway tests. The first few requests fail, the run is retried, and the real problem — a race in the pipeline — is filed as test flakiness.
Poll a cheap unauthenticated route with a hard deadline instead of sleeping:
Code
If your gateway has no health route, add one. See health checks.
Per-environment services and secrets
Preview environments have their own configuration, and a test that passes locally can fail on a preview for reasons that have nothing to do with your change:
- Environment variables. Values are set per environment in the Zuplo Portal. A variable that exists in production but not on the preview is a real defect the preview run catches — but assert on the behavior, not on the variable.
- API key buckets. API key authentication is backed by a bucket tied to the environment. Keys minted for one environment do not authenticate against another, so CI needs a fixture key for the environment it is testing.
- Rate limit buckets. Rate limit state is per environment too. This works in your favor: a preview environment's limits are not being consumed by production traffic, which is part of what makes the rate limit recipe deterministic.
Keep fixture credentials in your CI provider's secret store and pass them to
zuplo test as environment variables. Inside the test they are available on
TestHelper.environment:
Code
Scope what runs where
The same files can run everywhere, but that does not mean every test runs everywhere:
| Target | What to run |
|---|---|
http://localhost:9000 | Everything. Fast feedback while editing. |
| Preview deployment | Everything. This is the run that gates the merge. |
| Production | A small, read-only smoke subset selected with --filter. |
Name the production-safe tests consistently — a smoke: prefix works well — and
select them by name:
Code
Nothing with side effects belongs in that subset. See gateway test recipes for the test data hygiene rules that make this safe.
Clean up preview environments
Preview environments outlive the branch unless something removes them. Delete the branch and the environment goes with it when you use the GitHub integration. If you deploy from your own pipeline, add an explicit cleanup step on branch delete. See cleanup on branch delete.