CY
Elements of Automated Test Design

Score 100% on the quiz to continue

Lesson
Free Preview

Describing suites, sub-suites, and test cases

Write clear, specific, behavior-focused descriptions that double as living documentation.

Clear descriptions of test suites, sub-suites, and test cases are the foundation of a maintainable test suite. When descriptions are clear, you do not need to read the implementation details to understand what is being tested and what the expected result is.

Good descriptions also turn your tests into living documentation of how the system is supposed to behave.

✅ What to do

Use clear and specific descriptions. Each suite and sub-suite should have a name that reflects the area of the system or the feature under test. Each test case should make it immediately clear what is being tested and what the expected result is.

Focus on behaviors. Test cases that focus on specific behaviors are useful both for validation and as documentation of how the system should work.

A well-structured example:

describe('User Authentication', () => {
  context('Login', () => {
    it('redirects to the dashboard when logging in with valid credentials', () => { /* ... */ })
    it('shows an error message when logging in with an incorrect password', () => { /* ... */ })
  })

  context('Registration', () => {
    it('creates an account and sends a confirmation email when registering with valid information', () => { /* ... */ })
    it('shows an error message when registering with an email already in use', () => { /* ... */ })
  })
})
👨‍🏫 In Cypress, describe names the suite (the feature under test), context names a sub-suite (a sub-feature), and it names each test case. context is an alias of describe, so it behaves identically; using it for sub-features is purely a readability convention that makes the two levels distinguishable at a glance. Read top to bottom, each it forms a sentence with its parents: "User Authentication, Login, redirects to the dashboard when logging in with valid credentials."

❌ What not to do

Avoid generic or vague descriptions. Vague suite, sub-suite, and test case names make it harder to understand what is being tested and why. This reduces the value of the tests as documentation and makes failures harder to diagnose.

Avoid a lack of focus on expected results. Test cases without a clear expected result, or that try to cover many behaviors at once, are less effective and harder to maintain.

An example of what to avoid:

describe('Site tests', () => {
  context('Frontend tests', () => {
    it('test login', () => { /* ... */ })
    it('test registration', () => { /* ... */ })
  })

  context('Miscellaneous', () => {
    it('click all the buttons', () => { /* ... */ })
    it('submit random forms', () => { /* ... */ })
  })
})
👨‍🏫 Compare the two examples read as sentences. "Site tests, Frontend tests, test login" says almost nothing: which login? logging in how? expecting what? "Miscellaneous" is a warning sign on its own, a bucket for tests that were never given a real home. Vague names like these fail as documentation and, when one breaks, tell you nothing about what actually stopped working.

Tests must not lie

A test description is a promise. When the promise and the implementation disagree, the test becomes untrustworthy documentation and misleads whoever reads it.

✅ What to do: description matches implementation exactly

Make the description as specific as the implementation.

Example:

// Description is precise and matches implementation exactly
it("redirects to the dashboard when logging in with valid credentials", () => {
  cy.get('[data-testid="email"]').type("user@example.com")
  cy.get('[data-testid="password"]').type("password123")
  cy.get('[data-testid="login-button"]').click()

  // Implementation checks only what the description promises
  cy.url().should("include", "/dashboard")
})

The truth: The description says exactly what the test does. No hidden assertions, no missing behaviors.

❌ What not to do: description says more than implementation

If the description promises something the test doesn't actually verify, readers assume the behavior is tested when it is not.

Example:

// Description promises both redirect AND welcome message
it("redirects to the dashboard and displays a welcome message when logging in with valid credentials", () => {
  cy.get('[data-testid="email"]').type("user@example.com")
  cy.get('[data-testid="password"]').type("password123")
  cy.get('[data-testid="login-button"]').click()

  // Only verifies the redirect; never checks for the welcome message
  cy.url().should("include", "/dashboard")
})

The lie: The description says the welcome message is displayed, but the implementation never verifies it. The next developer may skip adding that assertion, thinking it's already tested.

❌ What not to do: description says less than implementation

If the description is vague while the implementation tests many behaviors, readers don't know what's actually covered.

Example:

// Description is vague
it("logs in with valid credentials", () => {
  cy.get('[data-testid="email"]').type("user@example.com")
  cy.get('[data-testid="password"]').type("password123")
  cy.get('[data-testid="login-button"]').click()

  // Implementation actually checks redirect, welcome message, session token, AND email
  cy.url().should("include", "/dashboard")
  cy.get('[data-testid="welcome-message"]').should("be.visible")
  cy.window().its("localStorage.sessionToken").should("exist")
  cy.get('[data-testid="user-email"]').should("contain", "user@example.com")
})

The lie: The description doesn't say what's actually being tested. Someone maintaining this test may not realize all four behaviors are covered, or accidentally remove a behavior-specific assertion thinking it's redundant.

Summary

Clear, specific test descriptions that match the implementation are the foundation of a maintainable and trustworthy test suite. When descriptions are precise and aligned with what the test actually verifies (neither overpromising nor understating), they become living documentation that accurately reflects the system's behavior. This makes tests a reliable tool for understanding how the software should work, helps teams maintain the suite without surprises, and ensures that failures are easier to diagnose and act on.

Show the world what you learned 🌎

To show your professional network what you have learned in this lesson, post the following on LinkedIn.

I am taking the "Elements of Automated Test Design" course by @Walmyr Lima e Silva Filho at the @Talking About Testing School, where I learned how to write clear, specific test descriptions that double as living documentation. #TalkingAboutTesting #TATSchool #ElementsOfAutomatedTestDesign #TestAutomation #TestDesign

👨‍🏫 Remember to tag me in your post. Here is my LinkedIn profile.

Quiz

Question 1 of 3
Score: 0

Beyond running, why are clear suite and test case descriptions valuable?

Score 100% on the quiz to continue