Programming

Panduan Lengkap Selenium untuk Otomatisasi Browser Pemula

M
MUGHU
39 menit baca
Panduan Lengkap Selenium untuk Otomatisasi Browser Pemula
Daftar isi

Pernahkah Teman-Teman bayangin harus ngetik ulang ratusan kali buat ngecek apakah form login di web kamu masih berfungsi atau nggak? Nah, di sinilah Selenium masuk ke panggung. Selenium adalah suite tools open-source yang dipakai buat otomatisasi browser — dari ngetes aplikasi web, scrap data, sampai ngotomatisasi tugas administrasi berbasis web yang membosankan.

Selenium bukan cuma satu tool, tapi sekumpulan alat yang bikin kamu bisa ngendalin browser kayak Chrome, Firefox, Safari, dan Edge pakai kode. Mulai dari nulis script test otomatis, merekam interaksi pengguna, sampai jalanin test secara paralel di banyak mesin sekaligus — semua bisa dilakukan dengan Selenium.

Singkatnya: Selenium mengotomatisasi browser. Itu intinya. Apa yang kamu lakukan dengan kekuatan itu, terserah kamu.

Paket Selenium terdiri dari beberapa komponen utama: WebDriver buat ngerendah-level kontrol browser, Selenium IDE buat rekam dan mainkan ulang interaksi, serta Selenium Grid buat distribusi dan skala test lintas banyak environment. Buat kamu yang baru kenal dunia otomatisasi test, panduan ini bakal ngebawa kamu dari nol sampai bisa nulis dan jalanin script Selenium pertama kamu.


Kenapa Selenium Penting Buat Tim Developer

Sebelum MUGHU bahas cara pakainya, ada baiknya kita pahami dulu kenapa tool ini jadi standar de facto di industri pengujian web.

Dulu, MUGHU perngalamin banget capeknya ngetest manual tiap kali ada deploy baru. Bayangin, tiap release harus buka browser, isi form, klik tombol, tunggu loading, cek hasil — di tiga browser berbeda. Kalau satu siklus release butuh 30 menit buat regression test manual, dan kamu release tiap minggu, itu berarti dua jam per bulan habis cuma buat ngulang hal yang sama. Selenium ngubah semua itu jadi script yang jalan dalam hitungan detik.

Otomatisasi test dengan Selenium ngasih beberapa keuntungan strategis buat tim:

  • Hemat waktu signifikan — Test regression yang manual butuh jam bisa jadi menit

  • Konsistensi tinggi — Script jalan sama persis setiap kali, nggak ada "lupa ngetes satu kasus"

  • Cross-browser testing — Satu script bisa jalan di Chrome, Firefox, Safari, dan Edge

  • CI/CD friendly — Gampang diintegrasikan ke pipeline pipeline kayak Jenkins, GitHub Actions, atau GitLab CI

  • Skala lintas platform — Windows, macOS, Linux semua didukung

Dari sisi ROI (Return on Investment), investasi waktu buat setup Selenium test biasanya balik modal dalam Hitungan minggu — terutama kalau kamu punya banyak regression test yang berjalan manual. Tim yang udah adopt Selenium umumnya ngelihat peningkatan test coverage sekaligus pengurangan waktu release cycle secara signifikan.


Memahami Komponen Suite Selenium

Salah satu hal yang sering bikin bingung adalah "Selenium" itu sebetulnya payung buat beberapa tool. Tiap tool punya perannya masing-masing, dan penting buat pilih yang tepat sesuai kebutuhan kamu.

Selenium WebDriver

Ini jantung dari Selenium. WebDriver adalah kumpulan binding bahasa pemprograman yang bikin kamu bisa ngendalin browser secara langsung — kayak user asli ngeklik dan ngetik, tapi pakai kode. WebDriver mengimplementasi spesifikasi W3C WebDriver, jadi kode yang kamu tulis bisa jalan interchangeably antar browser.

Kalau kamu mau bikin regression test suite yang robust dan scalable, WebDriver jawabannya. Ini bukan cuma buat testing — tugas administrasi berbasis web kayak ngisi form berulang juga bisa diotomatisasi.

Selenium IDE

Selenium IDE adalah ekstensi browser (Chrome, Firefox, Edge) yang ngasih kamu kemampuan rekam dan mainkan ulang interaksi. Jadi kamu cukup buka browser, lakuin aksi yang mau dites, dan IDE bakal nerekam semuanya jadi script.

Ini cocok banget buat reproducibility bug cepat atau exploratory testing. Tapi untuk test suite yang kompleks, IDE punya keterbatasan dan biasanya nggak direkomendasiin sebagai solusi utama.

Selenium Grid

Bayangin kamu punya 200 test case dan harus jalan di 4 browser berbeda. Kalau jalan satu-satu di satu mesin, bisa jam-an. Selenium Grid bikin kamu bisa distribusikan test ke banyak mesin sekaligus, jadi semuanya jalan secara paralel.

Grid mengelola multiple environment dari titik pusat, jadi gampang buat ngejalankan test against banyak kombinasi browser dan OS. Buat tim yang udah skala, Grid itu game-changer.

Selenium Manager

Mulai versi 4.x, Selenium nambahin Selenium Manager — tool command-line yang ditulis pakai Rust dan otomatis ngurusin driver installation. Kamu nggak perlu lagi download chromedriver atau geckodriver manual. Tinggal instantiate, and it just works.


Perbandingan Komponen Selenium: Mana yang Pilih

Teman-Teman mungkin nanya, "Kalau gitu aku pakai yang mana?" Jawabannya tergantung use case. Biar gampang, ini perbandingan side-by-side:

Komponen

Bahasa yg Didukung

Tingkat Kesulitan

Best For

Skalabilitas

Selenium WebDriver

Java, Python, C#, Ruby, JavaScript, Kotlin

Menengah

Regression test suite, otomatisasi kompleks

Tinggi (dengan Grid)

Selenium IDE

Tidak perlu kode (record & playback)

Rendah

Quick bug repro, exploratory testing

Rendah

Selenium Grid

Semua bahasa WebDriver

Menengah-Tinggi

Paralel test lintas mesin/browsers

Sangat Tinggi

Selenium Manager

Built-in (Rust)

Otomatis

Manajemen driver/browser otomatis

N/A

Rekomendasi by use case:

  • Butuh test suite jangka panjang yang maintainable → WebDriver + Grid

  • Mau cepat rekam bug dan buat script tanpa nulis kode → Selenium IDE

  • Punya ratusan test dan mau percepat eksekusi → WebDriver + Selenium Grid

  • Baru pertama kali nyobain Selenium → Mulai dengan WebDriver, pakai Selenium Manager yang sudah built-in


Yang Kamu Butuhin Sebelum Mulai (Prerequisites)

Okay, sekarang kita masuk ke bagian teknis. Sebelum mulai ngoding, pastikan environment kamu siap. Berikut yang harus ada di mesin kamu:

1. Python 3.10 atau Yang Lebih Baru

Selenium versi terbaru (4.x) butuh Python 3.10 ke atas. Cek versi Python kamu dengan perintah:

BASH
python --version

Output yang diharapkan:

CODE
Python 3.10.0

Kalau versinya lebih lama, update dulu. Install Python dari python.org atau pakai package manager sesuai OS kamu.

Kenapa Python 3.10? Karena Selenium 4.x packcage di PyPI sudah set minimum version ke 3.10, dan beberapa fitur terbaru seperti union type hints dan pattern matching butuh versi ini.

2. Browser yang Terinstall

Kamu butuh setidaknya satu browser yang didukung:

  • Google Chrome

  • Mozilla Firefox

  • Microsoft Edge

  • Safari (khusus macOS)

Pastikan browser versi terbaru. Selenium Manager bakal otomatis download driver yang cocok dengan versi browser kamu.

3. pip (Python Package Installer)

pip biasanya udah include sama instalasi Python. Cek dengan:

BASH
pip --version

Kalau belum ada, install dengan:

BASH
python -m ensurepip --upgrade

4. Code Editor atau IDE

Pilih yang paling nyaman buat kamu — VS Code, PyCharm, Sublime Text, atau bahkan vim. Yang penting support syntax highlighting buat Python.

Alasan kenapa hal-hal di atas penting: Selenium WebDriver butuh Python runtime buat jalanin script, browser buat target otomatisasi, pip buat install library Selenium, dan editor buat nulis kode dengan nyaman. Kalau salah satu nggak ada, prosesnya bakal terhenti di tengah jalan.


Step 1: Install Library Selenium di Python

Sekarang saatnya install. Buka terminal atau command prompt, jalankan perintah berikut:

BASH
pip install -U selenium

Flag -U artinya "upgrade" — kalau kamu sudah pernah install sebelumnya, ini bakal update ke versi terbaru.

Output yang diharapkan:

CODE
Collecting selenium
  Downloading selenium-4.45.0-py3-none-any.whl (9.5 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 9.5/9.5 MB 25.3 MB/s eta 0:00:00
Installing collected packages: ... selenium-4.45.0
Successfully installed selenium-4.45.0

Kenapa step ini penting? Tanpa library ini terinstall, kamu nggak bisa import selenium di kode Python kamu. Library ini isinya binding resmi buat Selenium WebDriver dalam bahasa Python — semua API yang kamu butuhin buat ngendalin browser ada di sini.

Pada versi terbaru (4.45.0 saat tulisan ini dibuat), Selenium Manager sudah built-in. Artinya kamu nggak perlu repot download chromedriver atau geckodriver manual — semuanya diurus otomatis.

Tips: Pakai Virtual Environment

MUGHU selalu recommend pakai virtual environment biar dependency project nggak campur aduk sama sistem global. Caranya:

BASH
# Buat virtual environment
python -m venv selenium-env

# Aktivasinya
# Windows:
selenium-env\Scripts\activate
# macOS/Linux:
source selenium-env/bin/activate

# Baru install Selenium di dalam venv
pip install -U selenium

Dengan begini, kalau nanti kamu butuh versi berbeda di project lain, nggak bakal bentrok.


Step 2: Tulis Script Selenium Pertama Kamu

Saatnya momen yang ditunggu-tunggu — bikin script pertama. Kita akan lakuin tiga hal sederhana:

  1. Buka browser Chrome

  2. Load sebuah halaman web

  3. Tutup browser

Buka code editor kamu, buat file baru bernama first_test.py, lalu ketik kode berikut:

PYTHON
from selenium import webdriver

driver = webdriver.Chrome()

driver.get("https://selenium.dev")

print("Judul halaman:", driver.title)

driver.quit()

Simpan file, lalu jalankan:

BASH
python first_test.py

Output yang diharapkan:

CODE
Judul halaman: Selenium

Plus, kamu bakal ngeliat jendela Chrome terbuka sebentar, load halaman selenium.dev, lalu nutup sendiri. Itu otomatisasi browser paling basic yang bisa kamu lakuin dengan Selenium.

Mari kita bedah apa yang terjadi di tiap baris:

  • from selenium import webdriver — Mengimpor modul WebDriver dari library Selenium

  • driver = webdriver.Chrome() — Membuat instance Chrome browser. Di balik layar, Selenium Manager otomatis download chromedriver yang cocok kalau belum ada

  • driver.get("https://selenium.dev") — Perintah browser untuk navigate ke URL tersebut

  • print("Judul halaman:", driver.title) — Mengambil judul halaman dan menampilkannya

  • driver.quit() — Menutup browser dan mengakhiri session. Penting: quit() lebih lengkap dari close() karena juga membersihkan resource WebDriver

Kenapa urutan ini penting? Karena setiap script Selenium selalu punya lifecycle yang sama: inisialisasi → interaksi → cleanup. Kalau kamu skip quit(), browser tetap kebuka dan process driver tetap jalan di background — ngerjain resource mesin kamu.


Step 3: Interaksi dengan Elemen Web

Membuka browser dan nutup emang keren, tapi itu baru permulaan. Kekuatan Selenium sebetulnya ada di kemampuannya berinteraksi dengan elemen-elemen di halaman web.

Kita coba skenario lebih lengkap: buka halaman dokumentasi Selenium, cari sebuah link, klik link tersebut, lalu verifikasi hasilnya.

Buat file baru bernama interact_test.py:

PYTHON
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()

# Buka halaman dokumentasi
driver.get("https://selenium.dev/documentation")

# Verifikasi judul halaman
assert "Selenium" in driver.title
print("✓ Halaman dokumentasi terbuka dengan benar")

# Cari link berdasarkan ID
elem = driver.find_element(By.ID, "m-documentationwebdriver")

# Klik link tersebut
elem.click()

# Verifikasi sudah di halaman WebDriver
assert "WebDriver" in driver.title
print("✓ Berhasil navigasi ke halaman WebDriver")

print("Judul akhir:", driver.title)

driver.quit()

Jalankan:

BASH
python interact_test.py

Output yang diharapkan:

CODE
✓ Halaman dokumentasi terbuka dengan benar
✓ Berhasil navigasi ke halaman WebDriver
Judul akhir: WebDriver | Selenium

Mari kita bah konsep-konsep baru di sini:

Cara Mencari Elemen

find_element adalah metapode paling fundamental. Parameter pertamanya adalah strategi locator, dan parameter kedua adalah nilai yang dicari. Berikut locator strategies yang tersedia:

Strategi

Contoh

Kapan Pakai

By.ID

find_element(By.ID, "button-submit")

Kalau elemen punya atribut id unik

By.NAME

find_element(By.NAME, "username")

Buat form input yang punya atribut name

By.XPATH

find_element(By.XPATH, "//div[@class='header']")

Kalau elemen nggak punya ID atau name unik

By.CSS_SELECTOR

find_element(By.CSS_SELECTOR, ".btn-primary")

Selektor CSS, fleksibel dan powerful

By.CLASS_NAME

find_element(By.CLASS_NAME, "menu-item")

Kalau class name cukup spesifik

By.TAG_NAME

find_element(By.TAG_NAME, "h1")

Mencari berdasarkan tag HTML

By.LINK_TEXT

find_element(By.LINK_TEXT, "Login")

Mencari link berdasarkan text persisnya

By.PARTIAL_LINK_TEXT

find_element(By.PARTIAL_LINK_TEXT, "Log")

Mencari link berdasarkan teks parsial

Kenapa pilihan locator penting? Karena struktur DOM sering berubah. Kalau kamu pakai ID yang stabil, test kamu lebih resilient. Sebaliknya, kalau terlalu bergantung pada XPath yang kompleks, test mudah broke tiap kali UI berubah.

Aksi pada Elemen

Setelah elemen ditemukan, kamu bisa lakuin berbagai aksi:

PYTHON
# Klik tombol atau link
element.click()

# Ketik teks ke input field
element.send_keys("[email protected]")

# Hapus teks dari input field
element.clear()

# Ambil teks dari elemen
text = element.text

# Ambil atribut
href = element.get_attribute("href")

Step 4: Menangani Wait dan Timing

Ini salah satu topik yang bikin banyak orang kesel. Browser butuh waktu buat load halaman, dan kalau script kamu langsung nyari elemen sebelum halaman selesai loading, kamu bakal kenyang error NoSuchElementException.

Dulu MUGHU sering banget kena masalah ini. Terutama kalau ngetest web app yang banyak AJAX call-nya. Script jalan terlalu cepat, elemen belum muncul, boom — error. Solusi naifnya adalah time.sleep(5) — tunggu 5 detik. Tapi itu bad practice karena:

  • Terlalu lama → test jadi lambat

  • Terlalu pendek → test tetap flaky

  • Tidak adaptif → kadang butuh 1 detik, kadang 3 detik

Solusi yang benar adalah pakai WebDriverWait:

PYTHON
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("https://selenium.dev/documentation")

# Tunggu maksimal 10 detik sampai elemen muncul
wait = WebDriverWait(driver, 10)

element = wait.until(
    EC.presence_of_element_located((By.ID, "m-documentationwebdriver"))
)

element.click()

print("Element ditemukan dan diklik!")

driver.quit()

Kenapa ini lebih baik? Karena WebDriverWait bakal ngecek setiap 500ms apakah elemen sudah muncul. Begitu muncul, langsung lanjut — nggak nunggu kaku 10 detik penuh. Tapi kalau sampai 10 detik elemen belum muncul, baru raise TimeoutException.

Expected Conditions yang Sering Dipakai

Condition

Kegunaan

presence_of_element_located

Elemen ada di DOM (belum tentu visible)

visibility_of_element_located

Elemen terlihat di layar

element_to_be_clickable

Elemen siap diklik

title_contains

Judul halaman mengandung teks tertentu

url_contains

URL mengandung string tertentu

text_to_be_present_in_element

Teks tertentu muncul di dalam elemen

Pemilihan condition yang tepat bikin test kamu stabil tanpa nambah waktu eksekusi yang nggak perlu.


Step 5: Membuat Test Suite dengan unittest Framework

Okay, sekarang kita level up. Nulis script satu-satu enak, tapi di dunia nyata kamu butuh test suite yang terstruktur. Python udah punya built-in framework bernama unittest yang cocok banget dipadukan dengan Selenium.

Buat file test_suite.py:

PYTHON
import unittest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class SeleniumWebTest(unittest.TestCase):

    def setUp(self):
        """Dijalankan sebelum setiap test method."""
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(10)  # Implicit wait 10 detik
        self.addCleanup(self.driver.quit)

    def test_halaman_utama_selenium(self):
        """Test: Halaman utama selenium.dev bisa diakses."""
        self.driver.get("https://selenium.dev")
        self.assertIn("Selenium", self.driver.title)
        print(f"✓ Test 1 - Judul halaman: {self.driver.title}")

    def test_navigasi_dokumentasi(self):
        """Test: Bisa navigasi ke halaman dokumentasi."""
        self.driver.get("https://selenium.dev/documentation")
        self.assertIn("Selenium", self.driver.title)
        print(f"✓ Test 2 - Dokumentasi terbuka")

    def test_cari_elemen_link(self):
        """Test: Elemen link WebDriver di halaman dokumentasi bisa ditemukan."""
        self.driver.get("https://selenium.dev/documentation")

        wait = WebDriverWait(self.driver, 10)
        elem = wait.until(
            EC.presence_of_element_located((By.ID, "m-documentationwebdriver"))
        )
        self.assertTrue(elem.is_displayed())
        print(f"✓ Test 3 - Elemen ditemukan dan visible")

if __name__ == "__main__":
    unittest.main(verbosity=2)

Jalankan:

BASH
python test_suite.py

Output yang diharapkan:

CODE
test_cari_elemen_link (__main__.SeleniumWebTest) ...
✓ Test 3 - Elemen ditemukan dan visible
ok
test_halaman_utama_selenium (__main__.SeleniumWebTest) ...
✓ Test 1 - Judul halaman: Selenium
ok
test_navigasi_dokumentasi (__main__.SeleniumWebTest) ...
✓ Test 2 - Dokumentasi terbuka
ok

----------------------------------------------------------------------
Ran 3 tests in 12.45s

OK

Kenapa struktur seperti ini penting? Karena:

  • setUp otomatis jalan sebelum tiap test — browser selalu fresh

  • addCleanup(self.driver.quit) otomatis tutup browser setelah tiap test, walau test gagal

  • Setiap method test_* jadi test case terpisah dan independen

  • verbosity=2 ngasih output yang lebih informatif — kamu tau test mana yang pass dan butuh berapa lama

Sekali waktu MUGHU lupa pakai addCleanup dan cuma pakai tearDown. Bedanya, addCleanup tetap jalan walau setUp gagal di tengah jalan, sedangkan tearDown nggak. Buat testing dengan browser, ini perbedaan penting karena kalau browser kebuka tapi test gagal, kamu butuh pastikan browser tetap tutup.


Step 6: Pakai pytest untuk Testing yang Lebih Ekspresif

unittest oke, tapi kalau kamu pernah cobain pytest, kamu bakal ngerasa kalau pytest lebih ekspresif dan less boilerplate. Selain itu, pytest juga support fixtures yang lebih fleksibel buat managament resource.

Install pytest dulu:

BASH
pip install pytest

Lalu buat file test_pytest_selenium.py:

PYTHON
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

@pytest.fixture
def driver():
    """Fixture yang menyediakan WebDriver untuk setiap test."""
    driver = webdriver.Chrome()
    yield driver
    driver.quit()

def test_judul_halaman_selenium(driver):
    """Verifikasi judul halaman utama Selenium."""
    driver.get("https://selenium.dev")
    assert "Selenium" in driver.title

def test_dokumentasi_terbuka(driver):
    """Verifikasi halaman dokumentasi bisa diakses."""
    driver.get("https://selenium.dev/documentation")
    assert "Selenium" in driver.title

def test_klik_link_webdriver(driver):
    """Verifikasi link WebDriver bisa diklik."""
    driver.get("https://selenium.dev/documentation")

    wait = WebDriverWait(driver, 10)
    elem = wait.until(
        EC.element_to_be_clickable((By.ID, "m-documentationwebdriver"))
    )
    elem.click()

    assert "WebDriver" in driver.title

Jalankan:

BASH
pytest test_pytest_selenium.py -v

Output yang diharapkan:

CODE
============================= test session starts =============================
collected 3 items

test_pytest_selenium.py::test_judul_halaman_selenium PASSED           [ 33%]
test_pytest_selenium.py::test_dokumentasi_terbuka PASSED             [ 66%]
test_pytest_selenium.py::test_klik_link_webdriver PASSED              [100%]

============================== 3 passed in 11.23s ==============================

Kenapa pytest sering lebih dipilih? Sederhananya — fixture pytest lebih clean daripada setUp/tearDown di unittest. Assert juga lebih natural: cukup assert "Selenium" in driver.title, nggak perlu self.assertIn(). Plus, output pytest lebih informatif dan komunitasnya udah mature banget di ecosystem Python testing.


Step 7: Mengkonfigurasi Browser Options

Di dunia nyata, kamu sering perlu kustomisasi cara browser jalan. Misalnya jalanin dalam mode headless (tanpa GUI — penting buat CI/CD), atur window size, atau disable notifikasi. Berikut caranya:

PYTHON
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()

# Mode headless - browser jalan tanpa GUI
options.add_argument("--headless=new")

# Atur ukuran window
options.add_argument("--window-size=1920,1080")

# Disable notifikasi
options.add_argument("--disable-notifications")

# Disable infobars ('Chrome is being controlled by automated software')
options.add_argument("--disable-infobars")

# User agent kustom
options.add_argument("--user-agent=Mozilla/5.0 (Test Agent)")

# Jalanin dalam mode incognito
options.add_argument("--incognito")

driver = webdriver.Chrome(options=options)

driver.get("https://selenium.dev")

print("Judul:", driver.title)
print("Ukuran window:", driver.get_window_size())

driver.quit()

Output yang diharapkan (headless mode):

CODE
Judul: Selenium
Ukuran window: {'width': 1920, 'height': 1080}

Kenapa ini penting? Dalam pipeline CI/CD kayak GitHub Actions atau Jenkins, server biasanya nggak punya display. Mode headless wajib pakai di situ. Tanpa opsi ini, Selenium bakal coba buka jendela browser yang nggak ada display-nya — dan gagal.

MUGHU dulu pernah setup test di Jenkins yang terus-terusan gagal dengan error WebDriverException: unknown error: Chrome failed to start: exited abnormally. Setelah berhari-hari debugging, ternyata cuma lupa kasih --headless. Pelajaran mahal: selalu set headless mode kalau jalanin di environment tanpa display.


Step 8: Mengambil Screenshot untuk Debugging

Salah satu hal yang paling membantu saat debugging test failure adalah screenshot. Begitu test gagal, kamu pengen tahu halaman kayak gimana saat itu.

PYTHON
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import os

options = Options()
options.add_argument("--headless=new")

driver = webdriver.Chrome(options=options)
driver.get("https://selenium.dev/documentation")

# Screenshot full page
driver.save_screenshot("screenshot_full.png")
print("✓ Screenshot full page tersimpan")

# Screenshot elemen tertentu
elem = driver.find_element("id", "m-documentationwebdriver")
elem.screenshot("screenshot_elem.png")
print("✓ Screenshot elemen tersimpan")

driver.quit()

Saat pakai save_screenshot, file PNG bakal tersimpan di working directory. Kalau test kamu flaky atau gagal intermitent, screenshot adalah bukti visual yang nggak terbantahkan kondisi halaman saat kejadian.

Beberapa praktik baik soal screenshot:

  • Kasih nama file yang descriptive, misal: test_login_gagal_{timestamp}.png

  • Taruh di folder khusus, misal screenshots/, dan tambahkan ke .gitignore

  • Hanya simpan screenshot saat test gagal, bukan saat pass — keluwes

  • Kombinasi dengan logging buat trace yang lengkap


Step 9: Menangani Multiple Browser (Cross-Browser Testing)

Salah satu keuntungan utama Selenium adalah dukungan untuk banyak browser. Berikut cara bikin test yang jalan di beberapa browser:

PYTHON
import pytest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium.webdriver.edge.options import Options as EdgeOptions

def create_driver(browser_name, headless=True):
    """Factory function buat bikin WebDriver sesuai browser yang dipilih."""
    if browser_name == "chrome":
        options = ChromeOptions()
        if headless:
            options.add_argument("--headless=new")
        return webdriver.Chrome(options=options)

    elif browser_name == "firefox":
        options = FirefoxOptions()
        if headless:
            options.add_argument("--headless")
        return webdriver.Firefox(options=options)

    elif browser_name == "edge":
        options = EdgeOptions()
        if headless:
            options.add_argument("--headless=new")
        return webdriver.Edge(options=options)

    else:
        raise ValueError(f"Browser {browser_name} tidak didukung")

@pytest.fixture(params=["chrome", "firefox", "edge"])
def driver(request):
    """Fixture yang jalan untuk tiap browser."""
    driver = create_driver(request.param, headless=True)
    yield driver
    driver.quit()

def test_judul_selenium(driver):
    """Test yang otomatis jalan di Chrome, Firefox, dan Edge."""
    driver.get("https://selenium.dev")
    assert "Selenium" in driver.title
    print(f"✓ {driver.capabilities['browserName']}: judul = {driver.title}")

def test_dokumentasi_terbuka(driver):
    """Test dokumentasi di semua browser."""
    driver.get("https://selenium.dev/documentation")
    assert "Selenium" in driver.title

Jalankan:

BASH
pytest test_cross_browser.py -v

Output yang diharapkan:

CODE
============================= test session starts =============================
collected 6 items

test_cross_browser.py::test_judul_selenium[chrome] PASSED            [ 16%]
test_cross_browser.py::test_judul_selenium[firefox] PASSED           [ 33%]
test_cross_browser.py::test_judul_selenium[edge] PASSED              [ 50%]
test_cross_browser.py::test_dokumentasi_terbuka[chrome] PASSED       [ 66%]
test_cross_browser.py::test_dokumentasi_terbuka[firefox] PASSED      [ 83%]
test_cross_browser.py::test_dokumentasi_terbuka[edge] PASSED          [100%]
============================== 6 passed in 28.91s ==============================

Lihat bagaimana parameter params=["chrome", "firefox", "edge"] di fixture pytest otomatis bikin test jalan tiga kali — sekali di tiap browser. Ini pattern yang sangat powerful dan hemat kode.

Catatan: Pastikan browser-browser tersebut sudah terinstall di mesin kamu. Selenium Manager otomatis download driver yang sesuai, tapi browser-nya sendiri harus ada.


Step 10: Form Interaction yang Realistis - Login Test

Sekarang kita masuk ke skenario yang lebih realistis: test form login. Form login adalah salah satu flow yang paling sering dites di web app manapun.

Buat file test_form_interaction.py:

PYTHON
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
import time

# Setup browser
options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
driver = webdriver.Chrome(options=options)

try:
    # Buka halaman demo login
    driver.get("https://the-internet.herokuapp.com/login")

    # Verifikasi halaman login terbuka
    wait = WebDriverWait(driver, 10)
    heading = wait.until(
        EC.visibility_of_element_located((By.TAG_NAME, "h2"))
    )
    assert "Login Page" in heading.text
    print("✓ Halaman login terbuka")

    # Cari input username dan isi
    username = driver.find_element(By.ID, "username")
    username.send_keys("tomsmith")
    print("✓ Username diisi")

    # Cari input password dan isi
    password = driver.find_element(By.ID, "password")
    password.send_keys("SuperSecretPassword!")
    print("✓ Password diisi")

    # Klik tombol login
    login_button = driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
    login_button.click()
    print("✓ Tombol login diklik")

    # Tunggu flash message muncul
    flash = wait.until(
        EC.visibility_of_element_located((By.ID, "flash"))
    )
    assert "You logged into" in flash.text
    print(f"✓ Login berhasil! Pesan: {flash.text.strip()}")

    # Verifikasi halaman setelah login
    assert "secure" in driver.current_url
    print(f"✓ URL sekarang: {driver.current_url}")

    # Logout
    logout_button = driver.find_element(By.CSS_SELECTOR, "a.button")
    logout_button.click()
    print("✓ Logout diklik")

    # Verifikasi kembali ke halaman login
    flash_logout = wait.until(
        EC.visibility_of_element_located((By.ID, "flash"))
    )
    assert "You logged out" in flash_logout.text
    print(f"✓ Logout berhasil! Pesan: {flash_logout.text.strip()}")

finally:
    driver.quit()
    print("Browser ditutup.")

Output yang diharapkan:

CODE
✓ Halaman login terbuka
✓ Username diisi
✓ Password diisi
✓ Tombol login diklik
✓ Login berhasil! Pesan: You logged into a secure area!
✓ URL sekarang: https://the-internet.herokuapp.com/secure
✓ Logout diklik
✓ Logout berhasil! Pesan: You logged out of the secure area!
Browser ditutup.

Skenario ini nunjukin flow yang lebih lengkap: mengisi form, submit, verifikasi flash message, navigasi ke secure area, lalu logout. Ini adalah pattern test end-to-end yang umum banget.

Beberapa hal penting dari kode di atas:

  • try/finally — Pastikan browser selalu ditutup walau ada error di tengah

  • send_keys("teks") — Cara mengisi input field, bisa juga pakai Keys.RETURN buat submit

  • EC.visibility_of_element_located — Lebih ketat daripada presence_of karena elemen harus visible di layar

  • driver.current_url — Mengambil URL saat ini buat verifikasi navigasi


Step 11: Menghadapi Alert, Popup, dan Frame

Web gak cuma tentang halaman datar. Kadang kamu harus berurusan dengan alert, popup window, dan iframe. Selenium punya cara khusus buat masing-masing.

JavaScript Alerts

PYTHON
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.alert import Alert

driver = webdriver.Chrome()
driver.get("https://the-internet.herokuapp.com/javascript_alerts")

# Trigger JS Alert
driver.find_element(By.CSS_SELECTOR, "button[onclick='jsAlert()']").click()

# Tunggu alert muncul
wait = WebDriverWait(driver, 10)
alert = wait.until(EC.alert_is_present())

# Ambil teks alert
print(f"Teks alert: {alert.text}")

# Klik OK
alert.accept()
print("✓ Alert diterima")

# Trigger JS Confirm
driver.find_element(By.CSS_SELECTOR, "button[onclick='jsConfirm()']").click()
confirm = wait.until(EC.alert_is_present())
print(f"Teks confirm: {confirm.text}")
confirm.dismiss()  # Klik Cancel
print("✓ Confirm di-dismiss")

# Trigger JS Prompt
driver.find_element(By.CSS_SELECTOR, "button[onclick='jsPrompt()']").click()
prompt = wait.until(EC.alert_is_present())
prompt.send_keys("Halo dari Selenium!")
prompt.accept()
print("✓ Prompt diisi dan diterima")

driver.quit()

Beralih ke iframe

PYTHON
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://the-internet.herokuapp.com/iframe")

# Switch ke iframe
iframe = driver.find_element(By.ID, "mce_0_ifr")
driver.switch_to.frame(iframe)

# Sekarang bisa interaksi dengan elemen di dalam iframe
editor = driver.find_element(By.ID, "tinymce")
print(f"Teks di iframe: {editor.text}")

# Kembali ke main content
driver.switch_to.default_content()
print("✓ Kembali ke main content")

driver.quit()

Kenapa ini penting? Karena iframe adalah konteks terpisah — kamu nggak bisa langsung find_element buat elemen yang ada di dalam iframe tanpa switch dulu. Ini salah satu error paling umum: NoSuchElementException padahal elemen ada di layar — tapi di dalam iframe.


Step 12: Integrasi dengan CI/CD Pipeline

Untuk tim yang serius, test hanya berguna kalau jalan otomatis tiap ada code baru. Berikut contoh setup GitHub Actions buat jalanin Selenium test:

Buat file .github/workflows/selenium-tests.yml:

YAML
name: Selenium Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.10"

      - name: Install Chrome
        uses: browser-actions/setup-chrome@v1

      - name: Install dependencies
        run: |
          pip install -U selenium pytest

      - name: Run tests
        run: |
          pytest -v --tb=short

      - name: Upload screenshots on failure
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: test-screenshots
          path: screenshots/

Commit file ini ke repository, dan mulai sekarang, tiap push atau pull request bakal otomatis trigger test Selenium. Kalau ada yang fail, screenshot bakal diupload sebagai artifact.

Kenapa CI/CD integration penting? Karena test yang nggak jalan otomatis pada akhirnya bakal di-skip. Manusia itu malas by nature — kalau harus ngejalanin test manual tiap deploy, lama-lama bakal dilupain. Dengan CI/CD, test jalan whether you like it or not.


Error dan Troubleshooting: Masalah yang Sering Muncul

Sekarang MUGHU mau bahas error-error yang paling sering bikin anteng jadi uring-uring saat nulis script Selenium. Teman-Teman bakal sering ketemu hal-hal ini di lapangan.

1. NoSuchElementException

CODE
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element

Penyebab:

  • Elemen belum muncul di DOM (halaman belum selesai loading)

  • Locator salah — ID, class, atau XPath berubah

  • Elemen ada di dalam iframe yang belum di-switch

Solusi:

  • Pakai WebDriverWait dengan expected condition yang tepat

  • Verifikasi locator manual via DevTools (F12 → Console → document.getElementById("id-anda"))

  • Cek apakah elemen ada di dalam iframe

2. TimeoutException

CODE
selenium.common.exceptions.TimeoutException: Message:

Penyebab:

  • Elemen benar-benar nggak ada di halaman

  • Halaman load terlalu lambat (server lambat atau jaringan lemot)

  • Elemen ada tapi nggak visible (hidden, display:none)

Solusi:

  • Tingkatkan timeout value kalau memang halaman lambat

  • Kombinasikan dengan explicit wait yang spesifik

  • Cek apakah ada loading overlay yang nutup elemen

3. WebDriverException: Chrome Failed to Start

CODE
selenium.common.exceptions.WebDriverException: Message: unknown error: Chrome failed to start: exited abnormally

Penyebab:

  • Browser tidak terinstall atau versi driver tidak cocok

  • Jalanin di environment tanpa display (CI server) tanpa mode headless

  • Konflik dengan process Chrome yang sudah jalan

Solusi:

  • Pastikan browser terinstall dan versinya terbaru

  • Tambahkan --headless=new ke options

  • Kill semua process Chrome yang tertinggal (taskkill /f /im chrome.exe di Windows atau pkill chrome di macOS/Linux)

  • Tambahkan --no-sandbox dan --disable-dev-shm-usage kalau jalanin di Docker

PYTHON
options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--disable-gpu")

4. StaleElementReferenceException

CODE
selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document

Penyebab:

  • Elemen yang kamu simpan referensinya sudah dihapus dari DOM atau di-render ulang (re-render)

Solusi:

  • Cari ulang elemen sebelum berinteraksi dengannya

  • Pakai retry logic dengan exception handling

PYTHON
from selenium.common.exceptions import StaleElementReferenceException

def find_and_click(driver, by, value, retries=3):
    for attempt in range(retries):
        try:
            elem = driver.find_element(by, value)
            elem.click()
            return
        except StaleElementReferenceException:
            if attempt == retries - 1:
                raise
            import time
            time.sleep(0.5)

5. SessionNotCreatedException

CODE
selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version XXX

Penyebab:

  • Versi chromedriver tidak cocok dengan versi Chrome yang terinstall

Solusi:

  • Kalau pakai Selenium 4.x, Selenium Manager harusnya otomatis download driver yang cocok

  • Kalau tetap error, update Chrome ke versi terbaru

  • Atau manual download driver yang sesuai dari ChromeDriver page

Dulu sebelum ada Selenium Manager, masalah versi driver ini bikin MUGHU uring-uring tiap kali Chrome auto-update. Selalu harus cek versi Chrome, cari chromedriver yang cocok, download, taruh di PATH. Sekarang dengan Selenium Manager, semua itu jadi automated — alasan kuat buat pastikan kamu selalu pakai versi Selenium terbaru.


Studi Kasus: Implementasi Selenium di Tim E-commerce

Biar lebih applicable, MUGHU mau bagikan pengalaman implementasi Selenium di salah satu project. Ini bukan fiksi — ini pattern yang umum di tim engineering Indonesia. Mari kita telusuri dari background sampai hasilnya.

Background

Sebuah tim engineering di sebuah e-commerce yang di Jakarta punya regression suite manual yang butuh hampir 4 jam buat jalan lengkap. Setiap kali ada deploy ke staging, satu QA engineer harus duduk depan laptop, buka browser, jalanin test case satu per satu — dari login, pencarian produk, add to cart, checkout, sampe payment flow. Kalau ada bug, mereka harus screenshot, catat step-by-step replay, lalu submit ke developer.

Challenge

  • Waktu test manual terlalu lama — 4 jam per cycle, dua minggu sekali

  • Flaky karena human error — kadang QA lupa ngetes satu edge case

  • Sulity scale ke multiple browsers — harus test di Chrome, Firefox, dan Safari manual

  • CI/CD belum integrated — nggak ada automated gate sebelum deploy ke production

Approach

Tim akhirnya putuskan buat adopt Selenium WebDriver dengan pytest sebagai framework. Mereka mulai dengan test yang paling critical dulu — login, search, dan checkout flow.

Implementation

Minggu 1-2: Setup dasar

  • Install Selenium dan pytest

  • Bikin base fixture yang reusable untuk WebDriver setup

  • Konfigurasi headless mode untuk CI

  • Mulai test suite dengan 5 test case paling critical

PYTHON
# conftest.py — Shared fixtures
import pytest
from selenium import webdriver

@pytest.fixture(scope="session")
def browser():
    """Browser instance yang dipakai selama satu test session."""
    options = webdriver.ChromeOptions()
    options.add_argument("--headless=new")
    options.add_argument("--no-sandbox")
    options.add_argument("--disable-dev-shm-usage")

    driver = webdriver.Chrome(options=options)
    driver.implicitly_wait(5)
    yield driver
    driver.quit()

@pytest.fixture
def logged_in_user(browser):
    """Fixture yang sudah pre-logged-in, siap pakai."""
    browser.get("https://shop.contoh.co.id/login")
    browser.find_element("id", "email").send_keys("[email protected]")
    browser.find_element("id", "password").send_keys("password123")
    browser.find_element("css", "button[type='submit']").click()
    yield browser
    # Logout setelah tiap test
    browser.get("https://shop.contoh.co.id/logout")

Minggu 3-6: Scale test suite

  • Tambahkan test untuk search, product detail, add to cart

  • Implementasi Page Object Model buat bikin test lebih maintainable

  • Integrate ke GitHub Actions

Minggu 7-8: Cross-browser dan parallel

  • Tambahkan Firefox dan Edge ke test matrix

  • Setup Selenium Grid buat paralel execution

Results

Setelah dua bulan implementasi, ini hasil yang didapat:

Metrik

Sebelum Selenium

Setelah Selenium

Peningkatan

Waktu regression test

4 jam

12 menit

95% lebih cepat

Browser yang dites

1 (manual Chrome)

3 (Chrome, Firefox, Edge)

3x lipat

Test coverage

~60% (manual)

~85% (automated)

+25%

Bug post-deploy

3-5 per release

0-1 per release

~70% drop

Waktu QA per cycle

4 jam

15 menit (review)

94% lebih efisien

Key Learnings

Beberapa pelajaran berharga dari implementasi ini:

  • Mulai dari test yang paling critical — jangan target 100% coverage di hari pertama. Login dan checkout dulu, sisanya menyusul

  • Page Object Model itu game changer — pisahkan logic page interaction dari test case bikin test jauh lebih gampang di-maintain

  • Headless mode wajib untuk CI — tanpa itu, test nggak bakal jalan di server pipeline

  • Flaky test harus segera di-fix atau di-isolasi — jangan biarkan satu test flaky bikin seluruh suite nggak reliable

  • Screenshot saat fail adalah MUY importante — debugging tanpa screenshot itu kayak nyari kucing dalam ruang gelap


Best Practices yang Wajib Kamu Tahu

Berdasarkan pengalaman ngoding Selenium tahun-tahun ini, berikut best practices yang udah MUGHU validasi di lapangan:

1. Gunakan Page Object Model (POM)

POM adalah pattern yang ngepisahin logic interaksi halaman dari test case. Contohnya:

PYTHON
# pages/login_page.py
from selenium.webdriver.common.by import By

class LoginPage:
    def __init__(self, driver):
        self.driver = driver
        self.url = "https://shop.contoh.co.id/login"

        # Locators
        self.email_input = (By.ID, "email")
        self.password_input = (By.ID, "password")
        self.submit_button = (By.CSS_SELECTOR, "button[type='submit']")
        self.error_message = (By.CLASS_NAME, "error-msg")

    def load(self):
        self.driver.get(self.url)

    def login(self, email, password):
        self.driver.find_element(*self.email_input).send_keys(email)
        self.driver.find_element(*self.password_input).send_keys(password)
        self.driver.find_element(*self.submit_button).click()

    def get_error(self):
        return self.driver.find_element(*self.error_message).text

# tests/test_login.py
from pages.login_page import LoginPage

def test_login_valid(driver):
    login_page = LoginPage(driver)
    login_page.load()
    login_page.login("[email protected]", "password123")
    assert "dashboard" in driver.current_url

def test_login_invalid(driver):
    login_page = LoginPage(driver)
    login_page.load()
    login_page.login("[email protected]", "salah")
    assert "Email atau password salah" in login_page.get_error()

Kenapa POM penting? Kalau UI berubah — misal ID input berubah dari email ke user-email — kamu cukup update di satu tempat (di kelas Page), bukan di semua test case.

2. Hindari Implicit Wait yang Terlalu Tinggi

PYTHON
# AVOID:
driver.implicitly_wait(30)  # Terlalu tinggi, bikin test lambat

# BETTER:
driver.implicitly_wait(3)  # Default reasonable
# Lalu pakai explicit wait buat kasus yang butuh waktu lebih
wait = WebDriverWait(driver, 15)
elem = wait.until(EC.element_to_be_clickable((By.ID, "slow-loading-btn")))

Implicit wait itu global dan nunggu penuh kalau elemen nggak ditemukan. Kalau diset 30 detik dan ada satu elemen yang memang nggak ada, tiap test yang nyari elemen itu bakal nunggu 30 detik percuma.

3. Bersihkan Data Test Sebelum dan Sesudah

Test yang bergantung pada data dari test sebelumnya adalah resep flaky. Selalu pastikan tiap test dimulai dengan state yang bersih.

PYTHON
@pytest.fixture
def clean_cart(browser):
    """Reset cart sebelum tiap test."""
    browser.get("https://shop.contoh.co.id/cart/clear")
    yield browser
    browser.get("https://shop.contoh.co.id/cart/clear")

4. Jangan Test Hal yang Sama Dua Kali

Kalau di unit test kamu udah ngetest logic calculation, jangan test lagi di Selenium. Selenium itu buat test integration dan UI behavior, bukan bisnis logic. Test yang overlap bikin suite lambat dan susah di-maintain.

5. Beri Nama Test yang Deskriptif

PYTHON
# BAD:
def test_1(driver): ...
def test_login(driver): ...

# GOOD:
def test_login_dengan_email_dan_password_valid_arah_ke_dashboard(driver): ...
def test_login_dengan_email_tidak_terdaftar_tampilkan_pesan_error(driver): ...

Nama test yang deskriptif bikin laporan test failure jauh lebih actionable. Kamu tau persis apa yang gagal dan dalam konteks apa.


Kesalahan yang Sering Dilakukan dan Cara Menghindarinya

Buat melengkapi pembahasan, ini beberapa kesalahan yang sering MUGHU lihat di tim — dan mungkin kamu juga pernah ngelakuin ya (MUGHU juga dulu gitu).

1. Pakai time.sleep() Sebagai Wait

PYTHON
# BAD:
import time
driver.get("https://contoh.co.id")
time.sleep(5)  # Nunggu halaman load
button = driver.find_element(By.ID, "submit")

# GOOD:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver.get("https://contoh.co.id")
wait = WebDriverWait(driver, 10)
button = wait.until(EC.element_to_be_clickable((By.ID, "submit")))

time.sleep() itu kaku — nunggu penuh walau elemen udah muncul. WebDriverWait otomatis lanjut begitu kondisi terpenuhi.

2. Lupa Tutup Browser

Kalau kamu pakai webdriver.Chrome() tapi lupa driver.quit(), process Chrome dan chromedriver bakal tetap jalan di background. Lama-lama, memory mesin kamu habis.

Selalu pakai pattern try/finally atau fixture yang otomatis cleanup.

3. XPath yang Terlalu Rapuh

PYTHON
# BAD — kalau DOM berubah sedikit, langsung broke:
elem = driver.find_element(By.XPATH, "/html/body/div[3]/div[2]/ul/li[5]/a")

# GOOD — lebih resilient:
elem = driver.find_element(By.XPATH, "//a[contains(@class, 'product-link')][contains(text(), 'Sepatu')]")

XPath yang hardcode posisi node (div[3]/ul/li[5]) adalah jaminan test kamu bakal broke setiap kali ada perubahan kecil di layout.

4. Test Depends on Test Lain

Test A bikin user di database. Test B pakai user dari Test A buat login. Kalau Test A gagal, Test B otomatis fail juga. Tiap test harus independen.

5. Tidak Test di Environment yang Sama dengan Production

Test yang pass di local Windows tapi production jalan di Linux Docker — bisa beda hasil. Selalu test di environment yang se-mirip mungkin dengan production, terutama untuk browser version dan OS.


Selenium Grid: Scaling Test ke Level Berikutnya

Sekarang kita masuk ke topik yang lebih advanced tapi penting kalau test suite kamu udah tumbuh besar.

Selenium Grid memungkinkan kamu jalanin test secara paralel di banyak mesin. Bayangin punya 100 test case yang di jalan satu-satu butuh 30 menit. Kalau di-distribusi 10 parallel di 10 mesin, 3 menit selesai.

Konsep Dasar Grid

Grid punya dua peran utama:

  • Hub — Central point yang menerima test request dan distribute ke node yang tersedia

  • Node — Mesin yang jalanin test dengan browser yang terinstall

Setup Grid dengan Docker

Cara paling gampang buat nyobain Grid adalah pakai Docker:

BASH
# Jalankan Selenium Grid dalam mode standalone
docker run -d -p 4444:4444 --name selenium-grid selenium/standalone-chrome

# Atau pakai docker-compose untuk setup yang lebih kompleks

Buat file docker-compose.yml:

YAML
version: "3"
services:
  selenium-hub:
    image: selenium/hub:latest
    ports:
      - "4444:4444"

  chrome-node:
    image: selenium/node-chrome:latest
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_CONSUME_PORT=4443

  firefox-node:
    image: selenium/node-firefox:latest
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_CONSUME_PORT=4443

Jalankan:

BASH
docker-compose up -d

Buka browser dan ke http://localhost:4444 buat lihat Grid console. Dari situ kamu bisa lihat node yang tersedia dan session yang aktif.

Pakai Remote WebDriver

Setelah Grid jalan, kamu bisa connect ke Grid pakai Remote WebDriver:

PYTHON
from selenium import webdriver
from selenium.webdriver.common.options import ArgOptions

# Hub URL
hub_url = "http://localhost:4444"

# Chrome options
options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")

# Connect ke Grid
driver = webdriver.Remote(
    command_executor=hub_url,
    options=options
)

driver.get("https://selenium.dev")
print("Title:", driver.title)
print("Browser:", driver.capabilities["browserName"])
print("Platform:", driver.capabilities["platformName"])

driver.quit()

Kenapa Grid penting dari perspektif bisnis? ROI dari Grid datang dari pengurangan test execution time. Kalau kamu punya 500 test case yang masing-masing butuh rata-rata 5 detik:

  • Sequential (1 node): ~42 menit

  • Paralel 10 nodes: ~4.2 menit

  • Paralel 25 nodes: ~1.7 menit

Waktu yang dihemat ini langsung berdampak ke waktu feedback loop developer — semakin cepat tau ada bug, semakin murah fix-nya.


Alternatif Selenium: Kapan Mempertimbangkan yang Lain

Jujur saja, Selenium emang powerful tapi nggak selalu jawaban terbaik buat semua skenario. MUGHU mau jujur soal ini.

Alternatif

Kelebihan

Kekurangan

Best For

Playwright

Lebih cepat, built-in auto-wait, API modern

Komunitas lebih kecil

Test modern web app (SPA)

Cypress

Developer experience keren, real-time reload

Browser terbatas (Chromium-based), test berbayar untuk fitur paralel

Small-to-medium team, MVP testing

Puppeteer

Sangat cepat, native Chrome DevTools Protocol

Chrome-only (Firefox support terbatas)

Scraping, Chrome-specific automation

Selenium

Cross-browser solid, ekosistem besar, support banyak bahasa

Setup lebih ribet, API kadang verbose

Cross-browser testing yang serius, tim multi-bahasa

Rekomendasi by use case:

  • Tim kecil yang 100% JavaScript/TypeScript dan cuma butuh test Chromium → Playwright atau Cypress

  • Enterprise yang butuh cross-browser comprehensive dan multi-bahasa → Tetap Selenium

  • Butuh otomatisasi non-test (scraping, repetitive task) → Selenium atau Puppeteer

  • Just starting out and want industry standard → Selenium, karena dokumentasi, komunitas, dan tenaga kerja yang udah familiar dengan tool ini

Salah satu alasan Selenium tetap jadi pilihan banyak enterprise adalah dukungan multi-bahasa. Tim yang punya developer Java, QA yang nulis Python, dan devops yang pakai JavaScript — semua bisa pakai Selenium dengan API masing-masing yang familiar.


Strategi Membangun Test Suite yang Maintainable

Dari pengalaman MUGHU nulis ratusan test case Selenium, ini framework mental yang MUGHU pakai:

Mulai Kecil, Tumbuh Organik

Jangan langsung bikin 200 test case di awal. Mulai dengan 5-10 test yang paling critical — login, checkout, atau flow bisnis utama. Kalau pattern-nya udah solid dan stabil, baru tambah lebih banyak.

Sekali MUGHU bikin kesalahan dengan langsung bikin 50 test case dalam seminggu. Setengahnya flaky karena belum paham timing halaman, dan bikin tim enggak percaya sama test suite. Butuh dua minggu buat stabilize semua test itu. Kalau mulai dari 5 test dan validasi pattern-nya dulu, masalahnya jadi jauh lebih kecil.

Prioritaskan Berdasarkan Business Impact

Test yang paling penting adalah test yang ng-cover flow bisnis paling critical. Buat e-commerce, itu checkout. Buat SaaS, itu signup dan onboarding. Buat banking, itu transfer dan balance inquiry.

Kalau jumlah test terbatas, fokus yang bikin duit keluar kalau broke. Test yang cek warna tombol kurang penting daripada test yang verifikasi transaksi berhasil.

Test harus Bisa Di-trust

Kalau test suite sering false-fail (flaky), developer bakal mulai menggalkan dan mengabaikan alert. Dan kalau mereka mengabaikan alert, test suite praktis nggak berguna. Lebih baik punya 50 test yang reliable daripada 200 test yang flaky.

Aturan MUGHU: kalau satu test fail lebih dari sekali tanpa code change, masuk ke "flaky list" untuk di-fix atau di-quarantine.

Invest di Infrastructure

  • Bikin test data yang consistent dan terisi otomatis

  • Setup CI/CD pipeline sejak hari pertama

  • Bikin reporting yang jelas — HTML report, Slack notification, atau Dashboard

  • Monitor test execution time — kalau suite mulai lambat, cari cara buat paralel


Kesalahan Setup yang Umum di Environment Tim

Beberapa masalah yang MUGHU sering lihat di tim, khususnya yang baru mulai adopt Selenium:

1. Versi Selenium yang Berbeda di Mesin Berbeda

Developer A pakai Selenium 4.20, Developer B pakai 4.40, CI pakai 4.30. Setiap orang dapat beda hasil. Solusi: Lock version di requirements.txt:

TEXT
selenium==4.45.0
pytest==8.0.0

Dan pakai virtual environment + requirements.txt (atau pyproject.toml) di setiap mesin, termasuk CI.

2. Hardcode URL di Setiap Test File

PYTHON
# BAD:
driver.get("https://staging.contoh.co.id/login")
driver.get("https://staging.contoh.co.id/dashboard")

Kalau environment berubah dari staging ke production, harus replace di semua file. Solusi: Pakai config file atau environment variable.

PYTHON
# config.py
import os

BASE_URL = os.getenv("BASE_URL", "https://staging.contoh.co.id")

# test file
from config import BASE_URL

driver.get(f"{BASE_URL}/login")

3. Test Data yang Tidak Konsisten

Test register pakai email [email protected] yang sudah ada di database dari test lalu. Error terus. Solusi: Bikin test data dinamis dengan timestamp atau UUID.

PYTHON
import uuid

test_email = f"test_{uuid.uuid4().hex[:8]}@contoh.co.id"
test_user.register(email=test_email)

Performance Tuning untuk Selenium Test

Kalau test suite mulai terasa lambat, ada beberapa trik buat mempercepat:

1. Headless Mode

Headless browser jalan sekitar 30% lebih cepat karena nggak render GUI. Selalu pakai headless di CI.

2. Paralel Execution dengan pytest-xdist

BASH
pip install pytest-xdist
pytest -n 4  # Jalan 4 test secara paralel

Atau otomatis detect CPU cores:

BASH
pytest -n auto

3. Matikan Fitur yang Tidak Perlu

PYTHON
options = webdriver.ChromeOptions()

# Block image loading — hemat bandwidth dan waktu
prefs = {"profile.managed_default_content_settings.images": 2}
options.add_experimental_option("prefs", prefs)

# Disable extension
options.add_argument("--disable-extensions")

# Disable GPU (headless)
options.add_argument("--disable-gpu")

Memblok image loading bisa mempercepat test sampai 40% untuk halaman yang banyak gambar — asal test kamu nggak mau verifikasi visual image.

4. Reuse Browser Session untuk Test yang Berurutan

Kalau banyak test butuh setup yang mahal (login, load data berat), pertimbangkan buat share browser session:

PYTHON
@pytest.fixture(scope="session")
def browser():
    """Browser hidup sepanjang test session."""
    driver = webdriver.Chrome()
    yield driver
    driver.quit()

@pytest.fixture(scope="class")
def logged_in(browser):
    """Login sekali per class test."""
    browser.get("https://contoh.co.id/login")
    browser.find_element("id", "email").send_keys("[email protected]")
    browser.find_element("id", "password").send_keys("pass123")
    browser.find_element("css", "button[type='submit']").click()
    yield browser

Tapi hati-hati — sharing session berarti test jadi tidak fully independen. Trade-off antara speed dan isolation harus dipertimbangkan.


Selenium untuk Web Scraping: Bukan Hanya Testing

Satu hal yang jarang dibahas — Selenium juga sangat powerful buat web scraping, terutama buat site yang pakai JavaScript rendering berat.

Kasusnya gini: kamu mau ambil data dari site e-commerce buat compare harga. Tapi site-nya pakai React/Next.js, jadi kontennya di-render setelah JS jalan. requests library Python nggak bisa handle ini karena HTML yang diterima masih kosong.

PYTHON
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")

driver = webdriver.Chrome(options=options)

driver.get("https://books.toscrape.com/")

# Tunggu produk card muncul
wait = WebDriverWait(driver, 10)
product_cards = wait.until(
    EC.presence_of_all_elements_located((By.CLASS_NAME, "product_pod"))
)

products = []
for card in product_cards:
    title = card.find_element(By.CSS_SELECTOR, "h3 a").get_attribute("title")
    price = card.find_element(By.CSS_SELECTOR, ".price_color").text
    availability = card.find_element(By.CSS_SELECTOR, ".instock").text

    products.append({
        "title": title,
        "price": price,
        "availability": availability
    })

print(f"Ditemukan {len(products)} produk:")
for p in products[:5]:
    print(f"  - {p['title']} | {p['price']} | {p['availability']}")

driver.quit()

Output yang diharapkan:

CODE
Ditemukan 20 produk:
  - A Light in the Attic | £51.77 | In stock
  - Tipping the Velvet | £53.74 | In stock
  - Soumission | £50.10 | In stock
  - The Sharp Objects | £47.82 | In stock
  - Sapiens: A Brief History of HumanKind | £25.17 | In stock

Tapi ingat — Selenium bukan tool scraping paling efisien. Kalau site bisa di-scrape tanpa JS rendering, requests + BeautifulSoup jauh lebih cepat dan hemat resource. Selenium jadi pilihan kalau tidak ada cara lain selain render JS.


Penutup Teknis: Checklist Sebelum Test Kamu Go-Live

Sebelum kamu anggap test suite kamu siap dipakai tim, MUGHU punya checklist yang biasa dipakai buat memvalidasi:

  • Semua test jalan di mode headless tanpa error

  • Test di-install di fresh environment (dan lulus)

  • requirements.txt atau pyproject.toml menentukan semua dependency dengan version pin

  • CI/CD pipeline dikonfigurasi dan jalan green

  • Screenshot disimpan saat test fail

  • Test data setup dan teardown berfungsi

  • Tidak ada time.sleep() sebagai wait strategy

  • Locators pakai strategi yang stabil (ID > CSS > XPath)

  • Test di jalan minimal 3x berturut-turut dan hasilnya konsisten

  • Test run time masih dalam batas wajar (target: <15 menit untuk full suite)

  • Dilakukan setidaknya satu code review oleh teammate

Catatan tambahan untuk tim yang di Indonesia: Jika infrastruktur test kamu berlokasi di server local Jakarta atau cloud region Singapore, latency ke situs internasional umumnya 50-100ms yang cukup baik. Untuk situs lokal (.co.id), latency bisa lebih rendah dan test umumnya lebih cepat jalan. Pertimbangkan lokasi server Selenium Grid agar dekat dengan target application kamu untuk hasil yang konsisten.


Dunia otomatisasi browser dengan Selenium luas banget, dan MUGHU baru nguping permukaannya di panduan ini. Dari setup environment, interaksi dasar, framework testing, cross-browser, CI/CD, Grid scaling, sampai scraping — Selenium punya ekosistem yang mature dan terbukti di industri.

Kunci sukses bukan ada di menulis script Selenium yang pertama, tapi di membangun test suite yang reliable, maintainable, dan terintegrasi dengan workflow tim kamu. Mulai kecil, lakukan dengan benar, tumbuh organik.

Jika kamu ingin belajar lebih lanjut, dokumentasi resmi di selenium.dev cukup komprehensif, dan halaman Wikipedia Selenium (software) memberikan konteks historis yang bagus.

Kesimpulan

Perjalanan kita dari baris kode driver.get() pertama sampai konfigurasi Selenium Grid yang terdistribusi menunjukkan satu hal jelas: Selenium bukan sekadar tool, tapi ekosistem lengkap untuk otomasi browser. Dalam pengalaman MUGHU, perbedaan antara tim yang sukses dan yang terjebak bukan ada di versi library atau bahasa pemrograman yang dipilih — melainkan pada disiplin membangun test suite yang stabil, strategi locator yang konsisten, dan integrasi CI/CD yang benar-benar berjalan. Checklist go-live yang kita bahas tadi bukan formalitas, tapi jaring pengaman antara "test jalan di laptop saya" dan "test bisa dipercaya seluruh tim."

Dari sisi praktis, ada satu kebenaran yang sering diabaikan: pilih tool yang tepat untuk masalah yang tepat. Selenium bersinar saat kamu butuh interaksi browser nyata — form submission, rendering JS dinamis, validasi alur UI lintas browser. Tapi ketika halaman statis dan requests + BeautifulSoup sudah cukup, paksa diri kamu pakai Selenium justru memboroskan resource dan memperlambat eksekusi. Mengetahui kapan berhenti menggunakan Selenium sama pentingnya dengan mengetahui kapan memulainya. Untuk konteks tim di Indonesia, faktor infrastruktur seperti lokasi server Grid dan latency ke target aplikasi juga berperan besar dalam konsistensi hasil — jangan remehkan aspek geografis ini.

Setelah semua konsep, contoh kode, dan praktik yang kita bahas, langkah berikutnya ada di tangan kamu. Ambil satu kasus nyata dari proyek kamu sekarang — entah itu validasi form login, monitoring perubahan harga, atau regression test untuk fitur critical path — dan tulis satu test case dengan benar. Lalu jalankan ulang besok, dan besok lagi. Test yang lulus sekali mungkin kebetulan; test yang lulus sepuluh kali adalah fondasi. Komunitas Selenium dan dokumentasi resmi Selenium selalu terbuka sebagai referensi, tapi yang mengubah test suite kamu dari konsep jadi produksi hanyalah konsistensi kamu sendiri.


Referensi

Selenium. (2026). Selenium WebDriver: Robust Browser-Based Regression Automation and Testing.

Selenium. (2026). The Selenium Browser Automation Project: Tools and Libraries for Web Browser Automation.

WebMD. (2026). Selenium: Benefits, Uses, Side Effects, Dosage, and More.

Wikipedia. (2026). Selenium: Chemical Element, Isotopes, and Properties.

Wikipedia. (2026). Selenium (Software): Open-Source Browser Automation Tools and Framework.

WebMD. (2026). Selenium: Overview, Uses, Side Effects, Precautions, and Dosage.

Selenium. (2026). What Is Selenium? Open-Source Tool Suite for Web Application Test Automation.

TutorialsPoint. (2026). Selenium Tutorial: Components, Features, and Usage with Examples.

Office of Dietary Supplements. (2026). Selenium: Health Professional Fact Sheet.

PyPI. (2026). Selenium: Automated Browser and Driver Management for Python.

Komentar (0)

Belum ada komentar. Jadilah yang pertama berbagi pendapat!

Tinggalkan komentar