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.
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:
TypeScript1import { 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 usestest.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, afor...of
loop iterates over each object in theloginTestData
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 thedata
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 adialogMessage
is expected. Unlikepage.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.
- The page is loaded using
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.
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!