Prompt
How do I set up reusable API tests across dev and staging?
Latest observation
A good way to set up reusable API tests across dev and staging is to make the tests environment-agnostic and move all environment-specific values into configuration.
Recommended approach
1) Keep one test suite
Write tests once, and avoid hardcoding:
- base URLs
- credentials
- IDs
- tokens
- tenant names
- feature flags
Instead, inject them from env/config.
2) Use environment variables or config files
Example:
# dev
BASE_URL=https://dev.api.example.com
AUTH_TOKEN=...
# staging
BASE_URL=https://staging.api.example.com
AUTH_TOKEN=...
Your tests read from BASE_URL and AUTH_TOKEN rather than embedding values.
3) Centralize environment config
Create a config layer, for example:
const env = process.env.ENV || "dev";
const config = {
dev: {
baseUrl: "https://dev.api.example.com",
},
staging: {
baseUrl: "https://staging.api.example.com",
},
};
module.exports = config[env];
Then in tests:
const config = require("./config");
describe("Health check", () => {
it("returns 200", async () => {
const res = await fetch(`${config.baseUrl}/health`);
expect(res.status).toBe(200);
});
});
4) Use setup/teardown helpers
For data that must be created dynamically:
- create test users/orders/projects in setup
- store returned IDs
- clean up in teardown
That prevents dependency on pre-existing state in either environment.
5) Use API contracts and assertions that tolerate environment differences
For example, assert:
- status codes
- required fields
- types
- business rules
Avoid asserting:
- exact timestamps
- environment-specific IDs
- unstable ordering unless required
6) Parameterize tests when needed
If dev and staging differ slightly, make the same test run with different inputs:
const environments = ["dev", "staging"];
environments.forEach((env) => {
describe(`API tests in ${env}`, () => {
// run same tests with env-specific config
});
});
7) Run the same tests in CI
Typical pipeline:
- run on PR against dev
- run again after deploy to staging
- optionally use tags/suites for smoke vs full regression
8) Store secrets securely
Use:
- GitHub Actions secrets
- GitLab CI variables
- Vault / AWS Secrets Manager / Azure Key Vault
Never commit tokens or passwords.
Practical structure
Example layout:
tests/
api/
health.test.js
users.test.js
helpers/
client.js
config.js
auth.js
client.js handles common request logic, config.js handles env selection, and tests stay clean.
Best practice summary
The core idea is:
- one suite
- many environments via config
- dynamic test data
- clean setup/teardown
- CI-driven execution
If you want, I can show you:
- a JavaScript/Jest example,
- a Postman/Newman setup,
- or a Pytest version for reusable dev/staging API tests.