Structuring Tests for Enhanced Readability and Maintenance

Structuring Tests for Readability and Maintenance

Welcome to this essential section on structuring tests for readability and maintenance. As you progress through mastering test patterns with Playwright, it's crucial to learn how to organize your tests effectively. This lesson builds upon previous concepts like Page Object Models (POM) and data-driven testing. Here, you will understand how to organize your test code to make it clean and maintainable — a skill that will greatly benefit you in the long run.

What You'll Learn

In this section, you will dive deep into the organization of test scripts to enhance readability and maintainability. You will learn to:

  1. Utilize Descriptive Test Names: Understand how to use descriptive names for your tests and test suites so they clearly indicate what they verify. This allows anyone reading the code to quickly understand what each test does.

  2. Implement Setup and Teardown Methods: Discover how leveraging beforeEach and afterEach methods in Playwright helps automate repetitive setup or cleanup tasks, like logging users in or out. This reduces redundancy and makes your test scripts more concise.

  3. Structure Tests for Clarity: Learn to break down complex test scenarios into smaller, easier-to-understand parts. This makes each individual test focused and clear, enabling anyone reviewing the code to pinpoint issues or understand assumptions more straightforwardly.

Here's an example from a bookstore application to illustrate these concepts:

import { test, expect } from '@playwright/test';

test.describe('Bookstore Search Functionality with Authentication', () => {

  test.beforeEach(async ({ page }) => {
    // Navigate to the login page and log in before each test
    await page.goto('http://localhost:3000/login');
    await page.fill('#username', 'user1');
    await page.fill('#password', 'pass1');
    await page.click('text=Submit');
    await page.waitForLoadState('networkidle');
    await expect(page).toHaveURL('http://localhost:3000/home');

    // Navigate to the books page
    await page.goto('http://localhost:3000/books');
  });

  test('search for a book by title', async ({ page }) => {
    // Search for '1984'
    await page.fill('#search-box', '1984');

    // Verify that '1984' is displayed and other books are filtered out
    const bookTitle = page.locator('.book-title');
    await expect(bookTitle).toHaveCount(1);
    await expect(bookTitle).toHaveText('1984');
  });

  test('search for a book by author', async ({ page }) => {
    // Search for 'George Orwell'
    await page.fill('#search-box', 'George Orwell');

    // Verify that '1984' by George Orwell is displayed
    const bookTitle = page.locator('.book-title');
    await expect(bookTitle).toHaveCount(1);
    await expect(bookTitle).toHaveText('1984');
  });

  test('search with no results', async ({ page }) => {
    // Search for a non-existent book
    await page.fill('#search-box', 'Nonexistent Book');

    // Verify that no books are displayed
    const bookTitle = page.locator('.book-title');
    await expect(bookTitle).toHaveCount(0);
  });

  test.afterEach(async ({ page }) => {
    // Log out after each test
    await page.click('text=🚪 Logout');
  });
});
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal