How to Read Data from Excel in Playwright
Automating tests with Playwright is a game-changer, but hardcoding test data directly into your scripts can quickly turn your clean code into a maintenance nightmare. Tying your tests to data from an Excel spreadsheet is an elegant solution, allowing you to separate test logic from test data. This article will walk you step-by-step through how to read data from an Excel file and use it to power your data-driven Playwright tests.
Why Bother with Excel for Your Test Data?
Before diving into the "how," let's quickly cover the "why." Using external data sources, especially something as common as Excel, offers several practical advantages for test automation:
- Data-Driven Testing: This is the biggest win. You can design one test script, like a login flow, and run it dozens of times with different data sets (e.g., valid users, invalid users, users with different permission levels). You just add a new row to your spreadsheet to create a new test case.
- Separation of Concerns: Your test logic (the code that navigates, clicks, and asserts) remains separate from your test data. This makes your scripts cleaner, shorter, and much easier to read and maintain. If a username or password changes, you update the spreadsheet, not the code.
- Accessibility for Everyone: Not everyone on your team is a developer. Product managers, business analysts, and QA specialists are often more comfortable working in Excel than in a code editor. This approach empowers them to contribute to the testing process by creating and managing test scenarios directly in a spreadsheet.
- Better Scalability: Need to test 100 different product variations? Instead of writing 100 tests, you write one test and add 100 rows to your Excel file. This approach is far more scalable and efficient as your application grows in complexity.
Getting Started: Your Project Setup
To get things rolling, you first need a Playwright project and a library to handle the Excel file interaction. Playwright doesn't read Excel files out of the box, but a simple package from npm solves this easily.
1. Initialize Your Playwright Project
If you're starting from scratch, open your terminal and initialize a new Playwright project. If you already have one, you can skip this step.
npm init playwright@latestFollow the on-screen prompts to configure your project. Playwright will set up the necessary file structure and configuration for you.
2. Install a Library to Read Excel Files
There are several libraries for handling Excel files in Node.js. One of the most popular and straightforward is ExcelJS. It has great documentation and handles modern .xlsx files without any issues.
Install it in your project using npm:
npm install exceljsFree PDF · the crash course
AI Agents for Marketing Crash Course
Learn how to deploy AI marketing agents across your go-to-market — the best tools, prompts, and workflows to turn your data into autonomous execution without writing code.
3. Create Your Test Data File
Now, create a simple Excel file. Let's call it testData.xlsx and save it in the root of your project directory. For this tutorial, we'll create test data for a login form.
Open the spreadsheet and create two sheets: validUsers and invalidUsers. In the validUsers sheet, add the following data:
Sheet: validUsers
The column headers (username, password, expectedUrl) are important, as we'll use them to create structured data objects.
Creating a Reusable Function to Read Excel Data
To keep our code clean, we'll create a dedicated helper function to read the Excel file and parse its contents. This makes the logic reusable across multiple test files.
Create a new file in your project, perhaps in a utils folder, named excelReader.js.
// utils/excelReader.js
const ExcelJS = require('exceljs'),
const path = require('path'),
async function readExcel(fileName, sheetName) {
// Construct the absolute path to the Excel file
const filePath = path.join(__dirname, '..', fileName),
const workbook = new ExcelJS.Workbook(),
try {
await workbook.xlsx.readFile(filePath),
const worksheet = workbook.getWorksheet(sheetName),
if (!worksheet) {
throw new Error(`Sheet "${sheetName}" not found in ${fileName}`),
}
const data = [],
// The first row is the header row
const headerRow = worksheet.getRow(1).values,
// Start from the second row to read the actual data
worksheet.eachRow({ includeEmpty: false }, (row, rowNumber) => {
if (rowNumber > 1) {
let rowData = {},
// Map header names to row values
row.values.forEach((value, index) => {
const header = headerRow[index],
if (header) {
rowData[header] = value,
}
}),
data.push(rowData),
}
}),
return data,
} catch (error) {
console.error("Error reading Excel file:", error),
throw error, // Rethrow the error to fail the test if data can't be read
}
}
module.exports = { readExcel },Breaking Down the Code Script:
- Import Libraries: We import
exceljsto work with the spreadsheet andpathto help locate the file correctly, regardless of where we run the tests from. - Define the Function: The function is
asyncbecause file I/O operations are asynchronous in Node.js. It takesfileNameandsheetNameas arguments to make it versatile. - Load the Workbook: It creates a new
Workbookinstance and usesreadFile()to load ourtestData.xlsx. - Get the Worksheet: It grabs the specific sheet we're interested in using
getWorksheet(sheetName). - Parse the Data: It iterates through each row, identifies the first row as the header, and then creates a JavaScript object for each subsequent row, using the header values as keys.
- Return Data: It returns an array of these objects, perfect for looping through in our test.
- Error Handling: A
try...catchblock ensures that if the file doesn't exist or a sheet name is wrong, our test fails with a clear message.
Putting It All Together: Using the Data in a Playwright Test
With our helper function ready, let's wire it up to a Playwright test. We'll create a login test for the Sauce Demo website.
Create a new test file, for instance, in the tests folder, named login.spec.js.
// tests/login.spec.js
const { test, expect } = require('@playwright/test'),
const { readExcel } = require('../utils/excelReader'),
// Load Data From Excel
const testData = await readExcel('testData.xlsx', 'validUsers'),
test.describe('Sauce Demo Login Tests - Data-Driven from Excel', () => {
// Use a for...of loop to iterate over the test data
for (const data of testData) {
test(`should login successfully as ${data.username}`, async ({ page }) => {
await page.goto('https://www.saucedemo.com/'),
// Fill the login form using data from the current iteration
await page.locator('[data-test="username"]').fill(data.username),
await page.locator('[data-test="password"]').fill(data.password),
await page.locator('[data-test="login-button"]').click(),
// Assert that the login was successful by checking the URL
await expect(page).toHaveURL(data.expectedUrl),
}),
}
}),Free PDF · the crash course
AI Agents for Marketing Crash Course
Learn how to deploy AI marketing agents across your go-to-market — the best tools, prompts, and workflows to turn your data into autonomous execution without writing code.
How This Test Script Works:
- Import Dependencies: We import the necessary modules from Playwright and our new
readExcelhelper function. - Load Test Data: Crucially,
readExcel('testData.xlsx', 'validUsers')is called once at the top level of the file. This reads the spreadsheet and loads all the test cases into thetestDataarray before any tests start running. - Create Dynamic Tests with a Loop: Instead of a single
test()block, we use afor...ofloop to iterate through each object in thetestDataarray. In each iteration, a new test is generated. - Custom Test Titles: We use a template literal
test(should login successfully as ${data.username})to create a unique and descriptive title for each test run. - Use the Data: Inside the test function, we access the data for the current iteration using
data.username,data.password, anddata.expectedUrl.
Now, when you run your Playwright tests, it will execute the login test for every single row in your validUsers worksheet.
Final Thoughts
Integrating Excel with Playwright is a simple yet powerful technique that elevates your test automation strategy. It makes your tests more scalable, easier to maintain, and empowers non-technical team members to contribute directly to the testing process. By writing a reusable helper function, you can implement this data-driven approach cleanly across your entire test suite.
Automating tests saves you from manual repetition, and just as Playwright automates testing your application, your tools can automate the analysis of your business results. After you confirm your application is working, the next step is to understand how your customers are using it. Instead of manually stitching together data from Google Analytics, Salesforce, and Shopify, we built Graphed to connect all your data sources instantly. You can then ask questions in simple, natural language - like "show me which marketing campaigns are driving the most sales this month" - and get a real-time dashboard in seconds, skipping the reporting drudgery entirely.
Related Articles
How to Create Facebook Ads API for Claude Code
Create a Meta Marketing API access token that never expires, using a system user, so Claude Code can pull Facebook ad reports and manage campaigns.
ClickHouse vs Postgres: When to Switch to Columnar
Comparing ClickHouse vs PostgreSQL means matching storage architecture to workload. Row storage wins for transactions. Columnar wins for scan-heavy analytics.
Google Ads for Orthodontists: Get More Booked Consults
Most orthodontic Google Ads campaigns waste money on low-intent searches. The problem is structure, not the platform.