Test Automation Best Practices in Action ( Part 4)

Core Framework & Test Design – Data-Driven Testing

So far, we’ve built a robust architecture with the Page Object Model, bridged the communication gap using BDD, and eliminated flaky tests by ditching static waits. Today, we are focusing on keeping our codebase pristine, scalable, and incredibly DRY (Don’t Repeat Yourself).

Over my 15 years in Quality Engineering, one of the most common beginner mistakes I see is copy-paste programming. You need to test a login form with an admin user, a standard user, and a guest user. So, what do you do? You write the login test, copy it, paste it twice, and just change the username strings.

Suddenly, your test suite is bloated, and when the login flow changes, you have to update the exact same logic in three different places.

There is a much better way: Data-Driven Testing (DDT). Let’s look at how beautifully simple this is to implement in Playwright.


What is Data-Driven Testing?

Data-Driven Testing is a design pattern where you separate your test logic from your test data. Instead of writing multiple identical tests for different inputs, you write one test template and feed it an array or a file full of datasets.

Playwright handles this elegantly. By wrapping your test block in a standard JavaScript loop, Playwright’s runner will dynamically generate a completely independent test execution for every piece of data.

Seeing it in Action

In our Test Automation Best Practices repository, we have a feature that changes the background color. We need to test this for Turquoise, Red, and Yellow.

Here is how we do it in data-driven.spec.ts:

import { test, expect } from '../baseFixtures'

// 1. Define the dataset for the data-driven tests
const testData = [
  { name: 'Turquoise', expectedHex: '#1abc9c', expectedRgb: 'rgb(26, 188, 156)' },
  { name: 'Red', expectedHex: '#e74c3c', expectedRgb: 'rgb(231, 76, 60)' },
  { name: 'Yellow', expectedHex: '#f1c40f', expectedRgb: 'rgb(241, 196, 15)' }
]

test.describe('Data-Driven Testing', () => {
  test.beforeEach(async ({ homePage }) => {
    await homePage.goto()
  })

  // 2. Loop over the dataset to dynamically generate tests
  for (const data of testData) {
    
    // 3. Dynamically inject the data into the test name
    test(`changing color to ${data.name} should reflect in UI and DOM`, async ({ homePage }) => {
      
      // Act
      await homePage.clickColorButton(data.name)

      // Assert Text updates correctly
      await expect(homePage.currentColorText).toContainText(data.expectedHex)

      // Assert DOM styling updates correctly
      await expect(homePage.header).toHaveCSS('background-color', data.expectedRgb)
    })
  }
})

💡 Expert Best Practices Applied Here:

  1. Dynamic Test Naming: Notice the backticks in the test title: test(`changing color to ${data.name}...`). This is critical! When you run this file, Playwright won’t just report “one test passed.” It will report three distinctly named tests. If the “Red” dataset fails, it fails in isolation, and your Allure report will tell you exactly which permutation broke.
  2. Infinite Scalability: Imagine tomorrow your product manager adds 15 new colors to the app. How many lines of code do you have to write to test them? Zero. You just add 15 JSON objects to the testData array, and your coverage scales instantly.
  3. Externalizing Data: While we defined the array directly in the file for this simple example, enterprise frameworks often move this data out into external .json or .csv files. This means you can update test data without even touching the TypeScript files!

Summary

Data-Driven Testing is one of the easiest “quick wins” for junior and mid-level SDETs to adopt, immediately making their codebase look more senior. It eliminates boilerplate, isolates failures, and proves that you understand how to write maintainable software, not just scripts.

Do you want to do an exploration on this example together?

You can book some time with me to discuss your current situation and do exploratory testing of the sample of this post or any other kind of issue you met regarding Software Testing & Quality Engineering.