Episode ini membahas custom test fixtures dan helpers, perpanjangan Playwright dengan plugins dan custom reporters, serta berbagi utilities antar project.

Saat suite bertumbuh, kebutuhan kalian akan melebihi kemampuan bawaan Playwright. Episode 18 ini membahas custom tooling: membangun lapisan di atas Playwright — fixtures kustom, helper methods, custom reporters, dan plugins — agar suite mencerminkan kebutuhan spesifik project.
Kemampuan ini menandai peralihan dari pengguna menjadi pembangun test infrastructure. Alih-alih mengulang boilerplate di setiap test, kalian merancang foundation yang bisa dipakai ulang, diuji sendiri, dan dibagikan antar project.
Fixture bukan hanya memasok objek — mereka juga mengelola siklus hidup. Contoh fixture yang membuat user test lalu membersihkannya:
import { test as base, expect } from '@playwright/test';
import { UserApi } from './api/UserApi';
export const test = base.extend({
user: async ({ request }, use) => {
const userApi = new UserApi(request);
const user = await userApi.createTestUser();
await use(user);
await userApi.deleteUser(user.id);
},
});
export { expect };base.extend({ user: ... }) menciptakan fixture user yang membuat data, menyerahkannya ke test lewat use(user), lalu membersihkannya setelah test selesai — bahkan jika test gagal. Ini menghilangkan boilerplate setup/cleanup dari setiap test.
Helper adalah fungsi murni yang membungkus logika berulang. Pisahkan ke modul sendiri agar bisa dipakai tanpa test runner:
export function formatRupiah(nominal: number) {
return new Intl.NumberFormat('id-ID', {
style: 'currency',
currency: 'IDR',
}).format(nominal);
}
export async function waitForToast(page) {
await page.getByRole('status').waitFor();
}formatRupiah(nominal) memformat angka menjadi Rupiah, dan waitForToast(page) menunggu notifikasi. Helper yang terpusat membuat test lebih ringkas dan konsisten.
Reporter menentukan bagaimana hasil test disajikan. Kalian bisa membuat reporter kustom yang mengirim hasil ke sistem internal:
import type { Reporter, TestCase, TestResult } from '@playwright/test/reporter';
class SlackReporter implements Reporter {
onTestEnd(test: TestCase, result: TestResult) {
if (result.status !== 'passed') {
console.log(`[ALERT] ${test.title} ${result.status}`);
}
}
}
export default SlackReporter;class SlackReporter implements Reporter memanfaatkan interface Reporter dari @playwright/test/reporter. Dengan memakai custom reporter, hasil suite bisa diarahkan ke Slack, dashboard, atau database — sesuai kebutuhan tim.
export default defineConfig({
reporter: [
['html', { outputFolder: 'playwright-report' }],
['./custom-reporter.ts'],
],
});reporter menerima daftar reporter yang berjalan berurutan. Gabungkan reporter bawaan (html, list) dengan reporter kustom untuk kombinasi output yang lengkap.
Untuk pekerjaan sebelum semua test — misalnya menyiapkan database atau token — gunakan global setup:
export default defineConfig({
globalSetup: './global-setup.ts',
globalTeardown: './global-teardown.ts',
});globalSetup menjalankan kode sekali sebelum seluruh suite. Ini tempat yang tepat untuk menyiapkan environment bersama — seed data, build aplikasi, atau menyiapkan service.
Playwright tidak hanya untuk test — ia bisa dipakai sebagai library dalam script apa pun. Integrasi ini membuka pintu bagi tooling internal:
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({ path: 'preview.png' });
await browser.close();
})();Script di atas memakai playwright (bukan @playwright/test) sebagai library murni — ideal untuk job terjadwal, generator preview, atau pipeline internal.
npx playwright codegen bukan hanya untuk membuat test — ia juga menghasilkan sketsa interaksi yang bisa disempurnakan menjadi script. Rekam alur yang rumit, lalu ekstrak logika pentingnya ke dalam script automation atau helper untuk test.
Karena berjalan sebagai Node.js biasa, library Playwright bisa dipanggil dari script yang dijalankan cron, Lambda, atau pipeline data. Pola yang sama dengan chromium.launch() berlaku di mana pun Node.js berjalan.
Ketika beberapa repository memakai helper yang sama, kemas dalam modul NPM internal:
playwright-utils/
├── fixtures/
│ └── index.ts
├── helpers/
│ └── index.ts
└── index.tsModul ini di-publish ke registry internal atau dipakai sebagai dependency git. Semua project test lalu mengimpor helper dari satu sumber — perubahan cukup dilakukan sekali.
import { test, expect } from '@acme/playwright-utils';
test('memakai fixture bersama', async ({ user, page }) => {
await page.goto('/profil');
await expect(page.getByText(user.email)).toBeVisible();
});import { test, expect } from '@acme/playwright-utils' menggantikan impor dari @playwright/test. Seluruh fixture dan helper bersama tersedia langsung — konsistensi terjamin di semua repository.
Modul bersama hanya bermanfaat jika terdokumentasi dan berversi dengan baik. Tulis dokumentasi untuk setiap fixture dan helper, rilis dengan versioning semantik, dan pastikan ekspor tetap kompatibel lewat type-check (npx tsc --noEmit) sebelum dipublikasikan. Konsumen mengikuti perubahan lewat changelog, bukan menebak.
Episode 18 mengangkat kalian dari pemakai menjadi pembangun tooling: fixtures kustom mengelola siklus hidup data, helper terpusat mengurangi duplikasi, custom reporters dan global setup memperluas perilaku runner, dan packaging modul internal memungkinkan berbagi utilities antar project secara terstruktur.
Inti yang harus dibawa pulang:
use mengelola setup dan cleanup secara otomatis.playwright sebagai library membuka script automation di luar test runner.Di episode 19 selanjutnya kita akan membahas operational readiness dan runbooks — runbook untuk flaky tests, environment drift, dan browser failures, mengelola kesehatan suite dan ownership tim, strategi recovery saat baseline berubah, serta jadwal maintenance dan cleanup.