Even with good selectors and timeouts, tests can be hard to understand if assertions are scattered or redundant. Structuring assertions thoughtfully turns each test into a clear story about behaviour.
Organising Assertions for Clarity
A helpful pattern is “Arrange, Act, Assert”: set up state, perform an action, then group related assertions together. This makes it obvious what each test is proving.
// structuring-assertions.spec.ts
import { test, expect } from '@playwright/test';
test('user can update profile details', async ({ page }) => {
// Arrange
await page.goto('https://demo.myshop.com/profile');
// Act
await page.getByRole('textbox', { name: 'Display name' }).fill('New Name');
await page.getByRole('button', { name: 'Save changes' }).click();
// Assert
const status = page.getByRole('status');
await expect(status).toBeVisible();
await expect(status).toHaveText('Profile updated');
await expect(page.getByRole('textbox', { name: 'Display name' })).toHaveValue('New Name');
});
Group assertions by scenario rather than scattering them across helper functions where they become hard to see. When you do extract helpers, name them clearly so their intent is obvious.
Common Mistakes
Mistake 1 β Mixing many unrelated checks into a single long test
This makes failures ambiguous.
β Wrong: One test verifying login, profile update, and checkout all at once.
β Correct: Split flows into smaller tests focusing on specific outcomes.
Mistake 2 β Hiding important assertions deep inside helpers
This reduces transparency.
β Wrong: Having helpers that silently assert many things without the test author realising.
β Correct: Keep critical assertions visible in the main test body or clearly documented.