Introduction
In the previous chapters, we built a scalable Playwright API framework with reusable API Clients, Service Layers, Request Models, Response Models, and Schema Validation.
Our framework is already well organized. However, enterprise automation frameworks require much more than clean code. They also need to be fast, reliable, easy to debug, easy to maintain, CI/CD friendly, and parallel execution ready.
This is where Playwright's powerful fixtures and lifecycle hooks become invaluable. In this chapter, you'll learn how to build a professional automation framework using custom fixtures, global setup, logging, error handling, retry strategies, and parallel execution. These are the same techniques used by experienced SDETs in enterprise automation projects.
Why Fixtures Are Important
Imagine you have 500 API test cases. Every test needs authentication, base URL, API Client, test data, logger, and environment configuration. Without fixtures, every test would repeat the same setup code.
const token = await login();
const client = new UserApiClient(token);
const logger = new Logger();
const env = new Environment();Now imagine repeating this in hundreds of test files. That's exactly why Playwright provides Fixtures.
What Is a Fixture?
A Fixture is a reusable object that Playwright automatically creates before your test starts. Instead of writing setup code manually, Playwright injects everything your test needs.
test("Create User", async ({
authenticatedRequest,
userService,
logger
}) => {
});Notice how clean the test becomes. Everything is ready before the test begins.
Built-in Fixtures
Playwright already provides several useful fixtures. Some commonly used ones are page, browser, context, request, and browserName. For API automation, the request fixture is the most important.
test("Get Users", async ({ request }) => {
});Creating Custom Fixtures
Enterprise frameworks usually create their own reusable fixtures.
import { test as base } from "@playwright/test";
export const test = base.extend({
userService: async ({ authenticatedRequest }, use) => {
const service = new UserService(authenticatedRequest);
await use(service);
}
});Now every test automatically receives a configured UserService.
Using Multiple Fixtures
Playwright allows multiple fixtures in the same test.
test("Create User", async ({
userService,
productService,
logger
}) => {
});Everything is initialized automatically. This keeps tests focused only on business validation.
Global Setup
Many enterprise projects require setup before any tests execute. Examples include generating authentication tokens, seeding databases, creating test users, uploading files, and configuring environments. Instead of doing this inside every test, use Global Setup.
export default async function globalSetup() {
console.log("Preparing Test Environment");
}This runs only once before the entire test suite.
Global Teardown
Global Teardown performs cleanup after all tests finish. Typical tasks include deleting test users, removing temporary files, closing database connections, generating reports, and sending Slack notifications.
export default async function globalTeardown(){
console.log("Cleaning Test Environment");
}BeforeEach Hook
Sometimes every test requires the same preparation.
test.beforeEach(async () => {
console.log("Preparing Test");
});This executes before every test. Common uses include resetting test data, initializing objects, and starting timers.
AfterEach Hook
AfterEach runs after every test.
test.afterEach(async () => {
console.log("Test Completed");
});Typical tasks include logging responses, cleaning temporary data, capturing failed requests, and recording execution time.
BeforeAll Hook
BeforeAll executes once before the first test in a describe block.
test.beforeAll(async () => {
console.log("Login Once");
});It is useful for authentication, creating shared resources, and loading configuration.
AfterAll Hook
AfterAll executes once after all tests complete.
test.afterAll(async () => {
console.log("Cleanup");
});Logging API Requests
Logging is one of the most overlooked parts of API automation. When a test fails in CI, logs become your best friend.
A professional framework logs HTTP Method, URL, Headers, Request Body, Response Body, Status Code, and Response Time.
POST /users
Status : 201
Duration : 342 ms
Request Size : 580 bytes
Response Size : 690 bytesDetailed logs dramatically reduce debugging time.
Creating a Logger Utility
Instead of using console.log everywhere, centralize logging. Later, this logger can write to files, HTML Reports, Allure, Slack, or AWS CloudWatch.
export class Logger{
info(message:string){
console.log(message);
}
error(message:string){
console.error(message);
}
}Measuring Response Time
Performance is just as important as correctness. Many enterprise teams include response time validation in smoke tests.
const start = Date.now();
const response = await request.get("/users");
const end = Date.now();
expect(end - start).toBeLessThan(2000);Retry Strategy
Network failures happen. Temporary server outages happen. Instead of immediately failing CI, configure retries.
retries: process.env.CI ? 2 : 0Recommended approach: no retries for local development, and 2 retries in CI. Retries should never hide real defects. They should only protect against temporary infrastructure issues.
Error Handling
A professional framework should provide meaningful error messages. A message like Test Failed is not helpful.
Clear error messages save valuable debugging time.
POST /users failed.
Expected Status : 201
Actual Status : 500
Response:
Internal Server ErrorParallel Execution
One of Playwright's biggest strengths is parallel execution. Instead of running tests sequentially, Playwright can execute them at the same time.
Test 1
↓
Test 2
↓
Test 3Playwright can execute:
Test 1
Test 2
Test 3
At the Same TimeBenefits include faster execution, better CI performance, and reduced feedback time.
Writing Parallel-Friendly Tests
Parallel execution requires independent tests. Avoid chains where one test depends on another.
Create User
↓
Update User
↓
Delete UserThese tests depend on each other. Instead, write independent tests.
Create User
Create Product
Retrieve Customer
Delete OrderEach test manages its own data. This allows safe parallel execution.
Avoid Shared State
Never share mutable variables between tests.
let token;This is a bad example. Instead, use fixtures. Each test receives its own clean state.
Enterprise Best Practices
Experienced SDETs follow these guidelines:
- Use fixtures for reusable objects.
- Keep setup outside test methods.
- Log every request and response.
- Measure API response times.
- Use retries only in CI.
- Design tests for parallel execution.
- Avoid shared mutable state.
These practices create faster, more reliable automation suites.
Common Beginner Mistakes
Avoid these common issues:
- Logging in before every test.
- Using global variables.
- Mixing setup with business logic.
- Ignoring API logs.
- Sharing test data between tests.
- Writing sequential test dependencies.
These mistakes often lead to flaky tests and difficult debugging.
Interview Questions
What is the difference between Built-in Fixtures and Custom Fixtures?
Built-in Fixtures are provided by Playwright, such as page, request, and browser. Custom Fixtures are created by developers to provide reusable services, API clients, authentication, loggers, or other project-specific objects.
Why are Fixtures preferred over Global Variables?
Fixtures provide isolated, reusable, and automatically managed resources for each test. Global variables can introduce shared state, making tests unreliable and difficult to run in parallel.
Why is Parallel Execution important?
Parallel execution significantly reduces overall test execution time, improves CI/CD performance, and provides faster feedback to development teams.
Summary
Excellent work! Your Playwright API framework now includes many of the features expected in an enterprise automation solution.
In this chapter, you learned:
- Built-in Fixtures
- Custom Fixtures
- Global Setup & Teardown
- BeforeEach & AfterEach Hooks
- BeforeAll & AfterAll Hooks
- Request & Response Logging
- Logger Utilities
- Response Time Validation
- Retry Strategies
- Error Handling
- Parallel Execution
- Enterprise Best Practices
At this stage, your framework is robust, scalable, and ready for professional API automation projects.
In Part 8, we'll build a complete production-ready Playwright API Automation Framework by integrating Environment Management, Configuration Manager, Secrets Management, API Utilities, Custom Assertions, JSON Schema Utilities, Allure Reporting, GitHub Actions, Jenkins Pipeline, and Docker Integration.
Get Playwright tutorials in your inbox
Weekly tips, real-world examples, and framework patterns – no spam, unsubscribe anytime.
Playwright Framework Series
View all →- 1Getting Started with Playwright: Installation, Setup, and Your First Test
- 2Playwright Locators: The Complete Guide with Real-World Examples
- 3Playwright Actions: Complete Guide to Click, Fill, Hover, Keyboard, Mouse & File Upload
- 4Playwright Assertions: The Complete Guide with Real-World Examples
- 5Playwright Auto Waiting: The Complete Guide with Real-World Examples
- 6Playwright Fixtures: The Complete Guide with Real-World Examples
- 7Playwright Browser Context & Multiple Tabs: The Complete Guide with Real-World Examples
- 8Playwright Authentication & Session Management: Complete Guide with Enterprise Examples
- 9Playwright Network Interception & API Mocking: Complete Guide with Real-World Examples
- 10Playwright Page Object Model (POM): The Complete Guide with Enterprise Examples
- 11Page Object Model with Playwright: A Practical Guide
- 12How to Build a Robust Professional Playwright Framework from Scratch (Step-by-Step)
- 13Building an Enterprise Playwright Framework from Scratch
API Testing Series
View all →- 1Playwright API Testing: The Complete Guide with Real-World Examples
- 2Part 1 : Playwright API Testing Tutorial: Build Enterprise-Level API Automation Framework
- 3Part 2: Playwright API Testing Tutorial: Setting Up Project & Sending Your First API Request
- 4Part 3: Mastering CRUD Operations in Playwright API Testing
- 5Part 4: Authentication in Playwright API Testing (Bearer Token, JWT, API Key & Reusable Fixtures)
- 6Part 5: Building an Enterprise-Level Playwright API Automation Framework
- 7Part 6: API Models, Schema Validation & Test Data Management in Playwright
- 8Part 7: Custom Fixtures, Hooks, Logging & Parallel Execution in Playwright API Testing
- 9Part 8: Building a Production-Ready Playwright API Framework (Environment Management, CI/CD, Reporting & Best Practices)
- 10Part 9: Advanced Playwright API Testing Techniques for Enterprise Automation
- 11Part 10: Building a Complete Enterprise Playwright API Automation Framework (Final Part)
- 12API Testing with Playwright: Request Context, Auth, and Assertions