Belajar Selenium - Page Object Pattern & Test Structure
Episode 6 of 23

Belajar Selenium - Page Object Pattern & Test Structure

Episode ini membahas implementasi Page Object Model untuk merapikan test, meng-enkapsulasi interaksi halaman dan abstraksi locator, mengorganisasi folder tests, pages, dan utils, serta membuat helper yang bisa dipakai ulang demi test yang mudah dibaca dan dipelihara.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Episode 5 sudah membuat test kalian stabil secara timing. Episode 6 menangani masalah kedua yang sama krusialnya: kerapian. Test yang semua logika menempel di satu fungsi akan sulit dibaca, sulit diubah, dan cepat rusak ketika aplikasi berubah. Solusi yang sudah teruji selama lebih dari satu dekade adalah Page Object Model (POM).

POM adalah pola di mana setiap halaman direpresentasikan oleh satu class. Class itu menyimpan locator dan method interaksi khas halaman tersebut, sementara test hanya memanggil method dengan nama yang mudah dibaca. Hasilnya: ketika struktur HTML berubah, kalian cukup memperbaiki satu tempat, bukan ratusan baris test.

Episode ini membawa kalian membangun struktur project yang menjadi tulang punggung semua episode berikutnya: folder pages, tests, dan utils yang terpisah, plus contoh implementasi POM yang bisa langsung dipakai.

Konsep Page Object Model

Masalah yang Dipecahkan POM

Tanpa POM, test seperti ini adalah pemandangan umum:

PythonTest tanpa POM (buruk)
driver.find_element("id", "email").send_keys("user@example.com")
driver.find_element("id", "password").send_keys("rahasia123")
driver.find_element("id", "submit").click()

Setiap test login mengulang tiga baris locator yang sama. Jika tim mengubah id submit menjadi btn-masuk, semua test harus diubah. POM mengumpulkan locator ini di satu tempat.

Satu Halaman, Satu Class

Prinsip POM: satu class mewakili satu halaman atau satu komponen besar. Class berisi dua hal — atribut locator dan method interaksi. Test tidak boleh melihat find_element langsung; dia cukup memanggil method.

Implementasi POM di Python

Class Halaman Login

PythonPage object LoginPage
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
 
 
class LoginPage:
    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(driver, 10)
 
    EMAIL = (By.ID, "email")
    PASSWORD = (By.ID, "password")
    SUBMIT = (By.ID, "submit")
    ERROR = (By.CLASS_NAME, "alert-error")
 
    def isi_email(self, teks):
        self.wait.until(EC.visibility_of_element_located(self.EMAIL)).send_keys(teks)
 
    def isi_password(self, teks):
        self.driver.find_element(*self.PASSWORD).send_keys(teks)
 
    def klik_masuk(self):
        self.wait.until(EC.element_to_be_clickable(self.SUBMIT)).click()
 
    def pesan_error(self):
        return self.driver.find_element(*self.ERROR).text

Perhatikan self.EMAIL = (By.ID, "email") — locator ditulis sebagai tuple dan dipakai ulang dengan *self.EMAIL. Ini membuat seluruh locator halaman terpusat di atas class, mudah diubah bila struktur HTML berubah.

Menggunakan Page Object dari Test

PythonTest memakai page object
from selenium import webdriver
from pages.login_page import LoginPage
 
 
def test_login_gagal():
    driver = webdriver.Chrome()
    try:
        driver.get("https://app.example.com/login")
        halaman = LoginPage(driver)
        halaman.isi_email("salah@example.com")
        halaman.isi_password("salah")
        halaman.klik_masuk()
        assert "Email atau password salah" in halaman.pesan_error()
    finally:
        driver.quit()

Test test_login_gagal(driver) di atas tidak lagi berisi locator. Alur test menjadi narasi: isi email, isi password, klik masuk, cek error. Ini adalah tujuan utama POM — test terbaca seperti dokumen bisnis.

Organisasi Project: tests, pages, utils

Struktur Direktori

Struktur yang kita gunakan sejak episode 2 kini diisi dengan POM:

Struktur project dengan POM
belajar-selenium/
├── conftest.py          -> fixture driver bersama
├── pages/               -> satu file per halaman
│   ├── __init__.py
│   ├── login_page.py
│   └── dashboard_page.py
├── tests/               -> file test pytest
│   ├── test_login.py
│   └── test_dashboard.py
├── utils/               -> helper dan wrapper
├── data/                -> data test (episode 9)
└── requirements.txt     -> dependency

Aturan singkatnya: file pages/*_page.py hanya berisi locator dan interaksi, tests/ hanya berisi skenario, dan utils/ berisi kode yang dipakai lintas halaman.

Utilitas dan Helper

Helper wait disimpan di utils agar konsisten:

PythonHelper di utils/waits.py
from selenium.webdriver.support.ui import WebDriverWait
 
 
def tunggu_klik(driver, locator, timeout=10):
    return WebDriverWait(driver, timeout).until(
        lambda d: d.find_element(*locator)
    )

Fungsi tunggu_klik(driver, locator, timeout=10) dipakai oleh semua page object. Dengan cara ini, perubahan kebijakan wait cukup dilakukan satu kali di satu file.

Meningkatkan Readability dengan Reusable Method

Method page object sebaiknya mengembalikan objek halaman berikutnya, sehingga test bisa dirantai:

PythonMethod yang mengembalikan halaman berikutnya
from pages.dashboard_page import DashboardPage
 
 
class LoginPage:
    def login_berhasil(self, email, password):
        self.isi_email(email)
        self.isi_password(password)
        self.klik_masuk()
        return DashboardPage(self.driver)

Dengan login_berhasil(...) yang mengembalikan DashboardPage, test menulis dashboard = halaman.login_berhasil(...) dan langsung melanjutkan interaksi di halaman baru. Pola ini menjaga alur test tetap linear dan mudah dibaca.

Tip

Jangan membuat page object menjadi terlalu besar. Jika sebuah halaman punya banyak bagian, pecah menjadi komponen terpisah — misalnya NavbarComponent — lalu gunakan dari page object utama.

Penutup

Episode 6 mengubah cara kalian menulis test: dari script linear yang menumpuk locator menjadi arsitektur halaman yang rapi. Kalian memahami mengapa POM dibutuhkan, bagaimana membuat class page object, bagaimana mengorganisasi folder pages, tests, dan utils, serta bagaimana merancang method yang bisa dirantai.

Inti yang harus dibawa pulang:

  • POM menyatukan locator dan interaksi per halaman dalam satu class.
  • Test hanya memanggil method, tidak menyentuh find_element langsung.
  • Pisahkan folder pages, tests, dan utils dengan tanggung jawab yang jelas.
  • Simpan helper lintas halaman di utils agar mudah diubah.
  • Rancang method page object untuk mengembalikan halaman berikutnya.

Di episode 7 selanjutnya kita akan membahas assertions dan test validation — memakai assertion library, memvalidasi state halaman, teks, visibilitas elemen, dan perilaku, menyusun dynamic assertions untuk UI responsif, serta menambahkan error reporting dan screenshot otomatis saat test gagal.