Pelajaran ini punya latihan. Latihannya berjalan di sandbox Academy Anda — proyek TestForge sungguhan berisi ShopMini, yang disimpan terpisah dari dasbor dan daftar proyek Anda.
Otomasi QAPelajaran 3 dari 12
EnglishPengujian Playwright pertama Anda
Pasang, rekam, jalankan, dan pahami setiap baris dari yang baru saja Anda tulis.
16 mntOtomasi QAPraktik
Dua puluh menit menuju suite yang berjalan
Pelajaran ini berakhir dengan pengujian browser yang berjalan di mesin Anda dan sebuah trace yang bisa Anda telusuri bingkai demi bingkai. Tidak ada yang sekali pakai di sini — empat perintah yang sama inilah yang dipakai proyek sungguhan di hari ke-400.
Playwright adalah pustaka otomasi browser milik Microsoft: satu API yang mengemudikan Chromium, Firefox, dan WebKit, dengan dua fitur yang paling penting bagi pemula tertanam di dalam alih-alih ditempelkan — auto-waiting dan trace. Berdua keduanya menyingkirkan dua hal yang membuat suite pertama menyiksa: sleep dan debugging buta.
Pasang
Di sebuah repositori — milik Anda, atau folder baru — jalankan:
npm init playwright@latest
Ia mengajukan empat pertanyaan. Jawaban yang masuk akal untuk percobaan pertama:
TypeScript, pengujian di tests/, ya untuk workflow GitHub Actions
(pelajaran CI akan memakainya), ya untuk mengunduh browser-nya. Playwright
membawa build browser-nya sendiri — itulah yang ~300 MB — sehingga semua orang di
tim dan di CI menjalankan biner yang identik. Itu saja sudah membunuh satu genre
"jalan kok di komputer saya".
Yang Anda dapatkan:
tests/example.spec.ts contoh pengujian
tests-examples/ demo lebih panjang yang bisa Anda hapus
playwright.config.ts satu berkas yang layak dibaca hari ini
.github/workflows/playwright.yml
Jalankan
npx playwright test # headless, semua browser, yang dijalankan CI
npx playwright test --ui # mode UI — pakai ini selagi menulis
npx playwright test --headed # tonton browser sungguhan mengerjakannya
npx playwright test tests/example.spec.ts:5 # satu pengujian, per baris
Tinggallah di --ui selagi Anda menulis. Ia memberi Anda mode pantau,
snapshot DOM di setiap langkah, locator picker, dan log jaringan, semuanya dalam
satu jendela. Run headless untuk CI dan untuk saat Anda sudah memercayai
pengujiannya.
Rekam draf pertama
npx playwright codegen https://example.com
Dua jendela terbuka: browser tempat Anda mengeklik-klik, dan panel yang menuliskan kode untuk klik Anda. Itu cara tercepat mulai bergerak, dan ia sungguh-sungguh bagus dalam memilih locator yang aksesibel.
Perlakukan hasilnya sebagai draf pertama, jangan pernah sebagai pengujiannya. Codegen merekam jalur yang kebetulan Anda tempuh, dalam urutan yang kebetulan Anda tempuh, tanpa asersi yang layak disebut asersi dan tanpa gagasan apa pun tentang klik mana yang menjadi intinya. Skrip rekaman adalah transkrip. Pengujian adalah transkrip plus sebuah klaim tentang apa yang seharusnya benar, dan hanya Anda yang tahu apa klaim itu.
Alur kerja yang bekerja: rekam untuk mendapat locator dan bentuknya, lalu hapus separuhnya dan tulis asersinya dengan tangan.
Setiap baris dari pengujian sungguhan
import { test, expect } from "@playwright/test";
test("a valid login lands on the dashboard", async ({ page }) => {
await page.goto("/login");
await page.getByLabel("Email").fill("ada@example.com");
await page.getByLabel("Password").fill("correct-horse");
await page.getByRole("button", { name: "Sign in" }).click();
await expect(page).toHaveURL(/\/dashboard/);
await expect(page.getByRole("heading", { name: "Dashboard" })).toBeVisible();
});
Baris demi baris, karena setiap satunya adalah sebuah keputusan:
test("...", ...)— namanya bukan hiasan. Ia yang muncul di laporan, di CI, dan (karya penutup track ini) di JUnit XML yang dicocokkan TestForge dengan case Anda. Tulislah sebagai kalimat tentang perilaku: "a valid login lands on the dashboard", bukan "login test 2".async ({ page })—pageadalah sebuah fixture: Playwright membuat konteks browser yang segar untuk pengujian ini dan memusnahkannya setelahnya. Cookie baru, penyimpanan baru, tanpa rembesan dari pengujian sebelumnya. Itulah sebabnya pengujian Playwright bisa berjalan paralel dengan aman, dan itulah sebabnya Anda nyaris tidak pernah menulis kode pembersihan untuk browser-nya.await page.goto("/login")— relatif, karenabaseURLtinggal di config-nya. Menanamkanhttps://staging.example.comke dalam 200 pengujian adalah cara sebuah suite jadi tidak bisa dijalankan di tempat lain.getByLabel("Email")— ditemukan dengan cara pembaca layar menemukannya, lewat labelnya. Ia selamat dari penggantian nama kelas, penulisan ulang gaya, dan penukaran komponen. Pelajaran berikutnya seluruhnya tentang pilihan ini..fill(...)— satu panggilan yang memfokuskan, mengosongkan, dan mengetik..type()ada untuk saat Anda butuh peristiwa per ketukan tombol;filladalah bawaannya.getByRole("button", { name: "Sign in" })— peran plus nama yang bisa diakses. Cocok dengan<button>,<input type=submit>, dan<a role="button">sama saja, dan ia gagal ketika tombolnya berhenti bisa dijangkau sebagai tombol — dan itu bug sungguhan yang layak digagalkan.await expect(...)— sebuah web-first assertion. Ia mencoba ulang sampai lulus atau kehabisan waktu, dan itulah yang membuat pengujiannya selamat menghadapi dashboard yang butuh 800 md untuk ter-render tanpa satu pun sleep.awaitpada semuanya. Setiap satunya mengembalikan sebuah Promise.awaityang hilang adalah bug klasik minggu pertama: pengujiannya lulus seketika, tanpa mengasersikan apa pun, dan error-nya muncul di pengujian lain belakangan.
Baris config yang benar-benar akan Anda sentuh
export default defineConfig({
testDir: "./tests",
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
reporter: [["html"], ["junit", { outputFile: "results.xml" }]],
use: {
baseURL: "http://localhost:3000",
trace: "on-first-retry",
screenshot: "only-on-failure",
},
projects: [
{ name: "chromium", use: { ...devices["Desktop Chrome"] } },
{ name: "firefox", use: { ...devices["Desktop Firefox"] } },
],
});
baseURL— setel sekarang, pakai jalur relatif di mana-mana.trace: "on-first-retry"— satu baris paling berharga di berkas itu. Lihat di bawah.forbidOnly— CI gagal kalau ada yang meng-committest.only. Tanpa itu, satu.onlyyang tersasar diam-diam menyusutkan suite Anda menjadi satu pengujian yang lulus.retries: 2hanya di CI — bawaan yang pragmatis dengan bahaya nyata terlekat: retry menyembunyikan kelabilan alih-alih memperbaikinya. Pertahankan, tapi tetaplah melihat pengujian mana yang hanya lulus di percobaan kedua. Pelajaran tentang pengujian labil membahas persis itu.reporter— entrijunit-lah yang diunggah karya penutupnya ke TestForge. Tambahkan sekarang; ia berbiaya satu baris.projects— browser-nya. Mulai dengan Chromium saja kalau run-nya terasa lambat, dan tambahkan yang lain ketika suite-nya sepadan dengan menit-menitnya.
Ketika ia gagal: trace viewer
npx playwright show-report # laporan HTML-nya
npx playwright show-trace trace.zip
Sebuah trace adalah rekaman run-nya: filmstrip, DOM di setiap langkah, panggilan jaringan, console, dan baris sumber untuk setiap aksi. Anda bisa menyorot langkah mana pun dan melihat halamannya persis seperti keadaannya — termasuk sorotan locator yang menunjukkan apa yang dikira Playwright sedang ia klik.
Ini mengubah cara Anda men-debug. Pertanyaannya berhenti menjadi "kenapa ia gagal
di CI padahal lulus di sini?" dan menjadi "inilah bingkai tempat elemennya belum
ada". Tester yang membaca trace memperbaiki bug otomasi dalam hitungan menit;
yang menambahkan waitForTimeout sampai hijau sedang menulis kelabilan esok
hari.
Masalah run pertama, dan artinya
| Gejala | Penyebab |
|---|---|
Timeout 30000ms exceeded waiting for locator | Elemennya tidak pernah cocok. Buka trace-nya dan lihat bingkainya — biasanya locator yang keliru, kadang halaman yang memang rusak |
strict mode violation: resolved to 3 elements | Locator Anda ambigu. Ini bukan bug untuk dibungkam — persempit (pelajaran berikutnya) |
net::ERR_CONNECTION_REFUSED | Aplikasinya tidak berjalan. Pakai webServer di config supaya npx playwright test yang menyalakannya |
| Pengujian lulus mencurigakan cepat, tanpa mengasersikan apa pun | await yang hilang |
| Lulus sendirian, gagal di dalam suite | State yang dibagi antarpengujian — biasanya akun atau catatan tetap yang diubah kedua pengujian |
Latihannya
Arahkan sebuah pengujian ke proyek sandbox TestForge Anda. Masuk, mendarat di proyeknya, dan asersikan sesuatu yang benar tentangnya:
npm init playwright@latestdi folder baru, dan setelbaseURLke host TestForge Anda.- Tulis satu pengujian: masuk, navigasi ke proyek sandbox Anda, dan asersikan nama proyeknya terlihat sebagai sebuah heading.
- Jalankan di
--ui, lalu headless. - Rusakkan dengan sengaja — ubah heading yang diharapkan menjadi sesuatu yang keliru — jalankan lagi lalu baca trace-nya. Temukan bingkai yang menunjukkan apa yang sebenarnya dikatakan halamannya.
Langkah terakhir itulah inti latihannya. Pengujian pertama yang lulus itu perasaan yang menyenangkan; bisa menjelaskan yang merah itulah keahliannya.
Jauhkan kredensial dari berkasnya — process.env.TF_EMAIL dan sebuah .env
yang ada di .gitignore. Meng-commit login yang bekerja ke sebuah repositori
adalah kekeliruan paling umum di proyek otomasi pertama, dan itu kekeliruan yang
disadari seorang pemberi kerja.
Di mana TestForge berperan
Sekarang Anda punya pengujian yang menghasilkan sebuah hasil di setiap
run. Hasil itu lebih berharga bila terlekat pada case yang dijalankannya
daripada sekadar duduk di terminal, dan untuk itulah baris reporter junit di
atas ada: ia menulis results.xml, dan karya penutupnya mengunggahnya ke
/api/v1/junit sehingga proyek sandbox Anda memperoleh sebuah run dengan
kelulusan, durasi, dan riwayat.
Namai pengujiannya sesuai case-nya sekarang — "TC-SHOP-12 a valid login lands on the dashboard", dengan SHOP adalah slug proyek Anda — dan pencocokannya
sudah dikerjakan untuk Anda ketika Anda sampai ke sana.
Selanjutnya: pilihan yang terus ditunda pelajaran ini — locator yang selamat dari sebuah refactor, dan kenapa rantai CSS yang ditawarkan editor Anda rusak setiap sprint.
Uji pemahaman Anda
3 pertanyaan. Tidak perlu akun, dan tidak ada yang dikirim ke mana pun selain ke pemeriksa jawaban.
1. Skrip codegen yang baru direkam berjalan hijau setiap kali. Apa hal terpenting yang harus dilakukan padanya sebelum di-commit?
2. Sebuah pengujian lulus dalam sekitar 200 md, jauh sebelum halaman yang disasarnya mungkin selesai dimuat, dan sebuah pengujian lain yang tak berhubungan mulai gagal kadang-kadang. Apa penyebab yang mungkin?
3. Mana di antara ini yang layak berada di playwright.config.ts alih-alih di berkas pengujian masing-masing?(pilih semua yang sesuai)