Learn Cypress - Security & Test Stability
Episode 13 of 23

Learn Cypress - Security & Test Stability

This episode covers isolating test data and environments, running tests with secure credentials, avoiding flakiness with stable selectors, and monitoring and maintaining suite reliability in the long term.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Stable and secure tests are two sides of the same coin. Episode 13 covers isolating test data and environments, managing secret credentials, choosing stable selectors, and monitoring practices to keep the suite reliable.

A suite that frequently fails makes the team lose trust and eventually ignore the tests. Poor security, on the other hand, can leak real data. Both must be addressed early.

Isolating Test Data and Environments

A Separate Test Environment

Never run tests against production. Set up a dedicated environment whose data can be reset without risk:

Running tests against the staging environment
npx cypress run --env apiBaseUrl=https://staging.example.com

--env apiBaseUrl=https://staging.example.com points tests at staging. Make sure staging uses a separate dataset that tests are allowed to destroy, not a copy of real user data.

Data That Does Not Leak Between Tests

Isolation also means test data should not affect each other. Use unique data per test and always clean up:

JSUnique data per test
it("membuat akun baru", () => {
  const email = `user-${Date.now()}@example.com`;
  cy.get("[data-cy=email]").type(email);
  cy.get("[data-cy=submit]").click();
  cy.contains(email).should("be.visible");
});

user-${Date.now()}@example.com guarantees a unique email on every run. Unique data prevents collisions with other tests running at the same time, especially when parallelizing in episode 14.

Running Tests with Secure Credentials

Do Not Put Secrets in Code

Credentials must not be written in spec files that end up in the repository. Store them in the environment and read them with Cypress.env:

Storing credentials in the environment
export CYPRESS_USER_PASSWORD='rahasia-yang-sangat-aman'
npx cypress run

CYPRESS_USER_PASSWORD is stored in the CI environment or on your local machine, not in the repository. Access it in tests with Cypress.env:

JSReading a secret from the env
cy.get("[data-cy=password]").type(Cypress.env("USER_PASSWORD"));

Cypress.env("USER_PASSWORD") reads the value from the environment. Make sure files holding secrets are in .gitignore and never committed.

Dummy Credentials for Tests

For most tests, use dummy credentials created specifically for testing — not real admin accounts. Separate accounts by role so tests do not depend on privileges that can change at any time.

Avoiding Flakiness with Stable Selectors

Selector Rules

Test stability is largely determined by selectors. Prioritize ones that do not change during development:

JSStable selectors with data-cy
cy.get("[data-cy=submit-login]").click();

[data-cy=submit-login] is an attribute made for testing. Unlike classes or ids that often change, data-cy is stable against styling changes and DOM refactors.

Avoiding Fragile Selectors

Some patterns should be avoided:

JSFragile selector patterns
cy.get(".btn.btn-primary.mx-auto").click();
cy.get("#password").type("x");
cy.get("div > div > form > button").click();

The selector .btn.btn-primary.mx-auto depends on classes that are prone to change, while the chain div > div > form > button is fragile against DOM structure changes. Replace all of them with team-agreed data-cy attributes.

Monitoring and Maintaining Reliability

Reliability is not a static state. Monitor your suite's metrics over time — pass rate, duration, number of flaky tests:

Monitored suite metrics
Pass rate: 98%
Durasi rata-rata: 6m 12s
Flaky test minggu ini: 3

The metric Pass rate: 98% gives a picture of suite health. If the number drops, do not let it slide; address it quickly before the team loses trust.

Flagging Flaky Tests

When a test fails occasionally for no clear reason, flag it and categorize it instead of silently deleting it:

JSFlagging a test under investigation
it.skip("masih diselidiki karena flaky", () => {
  cy.visit("/analitik");
});

it.skip(...) temporarily disables a test while recording the reason. A disabled test with a clear reason is better than a mislead failure in every run.

Info

Security and stability reinforce each other: secure credentials keep data under control, and controlled data makes tests more deterministic. Treat both as one habit, not two separate tasks.

Closing

Episode 13 strengthened the quality foundation: isolating test data and environments, secure credentials via env vars, stable data-cy selectors, and monitoring to keep the suite reliable in the long term.

Key takeaways:

  • Run tests in a dedicated environment, not production.
  • Use unique data per test to prevent collisions.
  • Store credentials in the environment, not the repository.
  • Prefer data-cy for stable selectors.
  • Monitor pass rate and flakiness regularly; flag fragile tests.

In the next episode, episode 14, we will cover CI/CD integration — integrating Cypress into GitHub Actions, GitLab CI, and Jenkins, headless mode versus headed runs, uploading video and screenshot artifacts, and parallelization and flaky test handling.

Learn Cypress - Security & Test Stability | Learn Cypress