Lesson 2
Data-Driven Testing with Playwright
Introduction to Data-Driven Testing with Playwright

Welcome to the next step in enhancing your test automation skills with Playwright! Previously, you've learned about structuring tests using the Page Object Model and creating reusable components. Now, we're diving into the world of data-driven testing. This lesson will show you how to write more dynamic tests by using different data sets. It's a powerful concept that allows you to run the same test logic with multiple inputs to validate more scenarios and edge cases. Understanding this can go a long way in making your automated test suites more robust and comprehensive.

What You'll Learn

In this lesson, you'll discover how to implement data-driven testing using Playwright in a TypeScript environment. We'll start by showing you how to define test data as an array of objects, where each object contains inputs and expected results.

Here's a glimpse of what the code looks like:

TypeScript
1import { test, expect } from '@playwright/test'; 2 3// Define separate expectations for dialog and page text 4const loginTestData = [ 5 { username: 'user1', password: 'pass1', pageMessage: 'Welcome to the BookStore' }, 6 { username: 'wronguser', password: 'wrongpass', dialogMessage: 'Login Failed' }, 7]; 8 9test.describe('Data-Driven Login Tests for BookStore', () => { 10 for (const data of loginTestData) { 11 test(`Login test for ${data.username}`, async ({ page }) => { 12 await page.goto('http://localhost:3000/login'); 13 14 await page.fill('#username', data.username); 15 await page.fill('#password', data.password); 16 17 if (data.dialogMessage) { 18 // Set up the dialog listener before triggering the action 19 page.once('dialog', async dialog => { 20 expect(dialog.message()).toBe(data.dialogMessage); 21 await dialog.dismiss(); 22 }); 23 } 24 25 await page.click('button[type="submit"]'); 26 27 if (data.pageMessage) { 28 // Verify the page content for a successful login 29 const welcomeMessage = await page.locator('h1.text-4xl'); 30 await expect(welcomeMessage).toHaveText(data.pageMessage); 31 } 32 }); 33 } 34});

The provided code is set up as a suite of data-driven tests for a login page using Playwright. Here's the breakdown:

  • Test Suite with test.describe: The code uses test.describe to group related tests together into a test suite named 'Data-Driven Login Tests for BookStore'. This effectively packages all the contained tests so they can be executed collectively and their results can be reported as a group.

  • Data Array and Loop: The loginTestData array consists of objects, each representing a set of input data and corresponding expected outcomes for the tests. For example, { username: 'user1', password: 'pass1', pageMessage: 'Welcome to the BookStore' } signifies valid credentials that should result in a positive login message. { username: 'wronguser', password: 'wrongpass', dialogMessage: 'Login Failed' } represents invalid credentials with an expected failure dialog.

    Within the test.describe block, a for...of loop iterates over each object in the loginTestData array. This is how data-driven testing is achieved: by dynamically generating a test case for each set of data inputs.

  • Dynamic Test Execution: For each iteration of the loop, a test is dynamically created using test, referring to the data object from the current loop iteration. This allows each test case to be named uniquely (e.g., Login test for user1), and uses that iteration's values to perform the test's logic.

  • Test Logic: Within each test:

    • The page is loaded using page.goto.
    • User inputs are simulated by filling in the username and password fields with page.fill.
    • A dialog listener is conditionally set up using page.once('dialog') if a dialogMessage is expected. Unlike page.on, which listens for events continuously, page.once captures a single occurrence of the dialog event and removes the listener automatically afterward. This is efficient for scenarios where a dialog is expected just once during the test. The listener verifies the message and dismisses the dialog.
    • After clicking the submit button, the code checks for a pageMessage which confirms the success of the login by verifying text content on the page.

By using this structure, the code efficiently tests different login scenarios by reusing the same logic against various input data sets, ultimately increasing test coverage with minimal additional code.

Why It Matters

Data-driven testing significantly enhances the efficiency of your test suite. By using various data inputs, you can cover more test cases with less code. This not only saves time but also reduces redundancy and increases the coverage of potential issues. It allows you to simulate real-world scenarios more effectively, which can lead to healthier and more reliable applications.

Exciting stuff, right? Armed with these strategies, you'll be better equipped to build more reliable and scalable tests. Let’s get started with the practice section and see this in action!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.