Kas yra Selenium WebDriver ir kodėl jis tapo standartu
Jei kada nors bandėte rankiniu būdu testuoti web aplikaciją, tikrai žinote, koks tai nuobodus ir laikui imlus darbas. Spaudinėti tuos pačius mygtukus, užpildyti formas, tikrinti ar viskas veikia – tai gali varyti į neviltį. Čia ir ateina į pagalbą Selenium WebDriver, įrankis, kuris tapo de facto standartu naršyklės automatizavimui.
WebDriver – tai ne tiesiog įrankis testams rašyti. Tai galinga programavimo sąsaja, leidžianti jums valdyti naršyklę taip, tarsi būtumėte tikras vartotojas. Galite spausti mygtukus, įvesti tekstą, naršyti tarp puslapių, o svarbiausia – daryti tai automatiškai ir pakartotinai. Skirtingai nuo senesnių sprendimų, WebDriver tiesiogiai komunikuoja su naršykle per jos native palaikymą, o ne per JavaScript injekcijas ar kitus apėjimo būdus.
Kas įdomiausia – Selenium WebDriver palaiko beveik visas populiarias naršykles: Chrome, Firefox, Safari, Edge ir net Internet Explorer (nors tikėkimės, kad jums nebereikia su juo dirbti). Tai reiškia, kad galite testuoti savo aplikaciją keliose naršyklėse naudodami tą patį kodą, tik pakeisdami keletą konfigūracijos eilučių.
Kaip pradėti: pirmas žingsnis į automatizaciją
Pradėti su Selenium WebDriver nėra sudėtinga, bet reikia kelių dalykų. Pirma, jums reikės pasirinkti programavimo kalbą. Selenium palaiko Java, Python, C#, Ruby, JavaScript ir kitas kalbas. Python yra populiariausias pasirinkimas pradedantiesiems dėl savo paprastumo ir skaitomų sintaksės.
Štai kaip atrodo paprasčiausias Selenium WebDriver pavyzdys Python kalba:
„`python
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get(„https://www.example.com”)
search_box = driver.find_element(By.NAME, „q”)
search_box.send_keys(„Selenium WebDriver”)
search_box.submit()
driver.quit()
„`
Bet prieš tai galėsite paleisti šį kodą, jums reikės įdiegti Selenium biblioteką (`pip install selenium`) ir atsisiųsti atitinkamą driver’į jūsų naršyklei. Anksčiau tai buvo šiek tiek varginantis procesas – reikėdavo rankiniu būdu atsisiųsti ChromeDriver, GeckoDriver ar kitą, patalpinti jį tinkamoje vietoje ir nustatyti PATH. Dabar yra įrankiai kaip WebDriver Manager, kurie viską daro automatiškai.
Svarbu suprasti, kad kiekviena naršyklė turi savo driver’į – tai tarsi vertėjas tarp jūsų kodo ir naršyklės. ChromeDriver Chrome’ui, GeckoDriver Firefox’ui ir taip toliau. Šie driver’iai implementuoja W3C WebDriver specifikaciją, todėl jūsų kodas lieka beveik identiškas nepriklausomai nuo naršyklės.
Elementų paieška: menas rasti tai, ko reikia
Viena svarbiausių Selenium WebDriver dalių yra gebėjimas rasti elementus puslapyje. Galite ieškoti pagal ID, klasę, CSS selektorių, XPath, tag’o pavadinimą ar net teksto turinį. Kiekvienas metodas turi savo privalumų ir trūkumų.
ID yra greičiausias ir patikimiausias būdas, jei jūsų puslapyje elementai turi unikalius ID. Problema ta, kad daugelis modernių framework’ų generuoja dinaminius ID, kurie keičiasi kiekvieną kartą perkraunant puslapį. CSS selektoriai yra lankstesni ir greitesni nei XPath, bet XPath leidžia daryti sudėtingesnius užklausimus, pavyzdžiui, ieškoti elemento pagal jo tekstą ar santykį su kitais elementais.
Štai keletas praktinių pavyzdžių:
„`python
# Pagal ID (greičiausias)
element = driver.find_element(By.ID, „username”)
# Pagal CSS selektorių
element = driver.find_element(By.CSS_SELECTOR, „button.submit-btn”)
# Pagal XPath
element = driver.find_element(By.XPATH, „//button[contains(text(), ‘Prisijungti’)]”)
# Rasti kelis elementus
elements = driver.find_elements(By.CLASS_NAME, „product-item”)
„`
Patarimas iš praktikos: vengti XPath, kai tik įmanoma. Taip, jis galingas, bet lėtas ir trapus. Jei puslapio struktūra šiek tiek pasikeičia, jūsų XPath gali nustoti veikti. CSS selektoriai paprastai yra geresnis pasirinkimas – jie greitesni ir lengviau skaitomi.
Laukimas ir sinchronizacija: kantrybė – raktas į stabilius testus
Viena didžiausių problemų, su kuria susiduria pradedantieji, yra sinchronizacija. Jūsų kodas vykdomas labai greitai, bet puslapiui gali prireikti laiko užsikrauti, elementai gali atsirasti po AJAX užklausų, animacijos gali užtrukti. Jei bandysite sąveikauti su elementu, kuris dar neegzistuoja, gausite NoSuchElementException.
Yra trys pagrindiniai laukimo būdai Selenium’e:
**Implicit Wait** – nustatote vieną kartą ir WebDriver automatiškai lauks iki nurodyto laiko, kol elementas atsirastų DOM’e:
„`python
driver.implicitly_wait(10) # lauks iki 10 sekundžių
„`
**Explicit Wait** – laukiate konkretaus sąlygos įvykdymo:
„`python
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
element = wait.until(EC.presence_of_element_located((By.ID, „myElement”)))
„`
**Sleep** – tiesiog pristabdote vykdymą:
„`python
import time
time.sleep(5) # blogiausia praktika!
„`
Niekada nenaudokite `time.sleep()` produkciniame kode. Tai nepatikima ir lėtina testus. Jei elementas atsiranda po 1 sekundės, bet jūs laukiate 5, švaistysite 4 sekundes. Jei jam reikia 6 sekundžių, testas vis tiek nepavyks.
Explicit Wait yra geriausias pasirinkimas daugeliu atvejų. Galite laukti ne tik elemento atsiradimo, bet ir kol jis taps spaudžiamas (clickable), matomas, kol tekstas pasikeis ir daugelio kitų sąlygų. Tai daro testus greitesnius ir stabilesnius.
Sudėtingesnės operacijos: kada reikia daugiau nei click ir send_keys
Kartais paprasto mygtuko paspaudimo nepakanka. Modernios web aplikacijos turi dropdown meniu, drag-and-drop funkcionalumą, hover efektus, klaviatūros kombinacijas. Selenium WebDriver turi įrankius ir šiems scenarijams.
**ActionChains** leidžia kurti sudėtingas vartotojo veiksmų sekas:
„`python
from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(driver)
actions.move_to_element(menu).perform() # hover
actions.drag_and_drop(source, target).perform() # drag and drop
actions.key_down(Keys.CONTROL).click(element).key_up(Keys.CONTROL).perform() # Ctrl+Click
„`
Darbas su **dropdown** meniu yra paprastesnis naudojant Select klasę:
„`python
from selenium.webdriver.support.select import Select
dropdown = Select(driver.find_element(By.ID, „country”))
dropdown.select_by_visible_text(„Lithuania”)
dropdown.select_by_value(„LT”)
dropdown.select_by_index(2)
„`
**JavaScript vykdymas** – kai Selenium nepakanka, galite tiesiogiai vykdyti JavaScript:
„`python
driver.execute_script(„window.scrollTo(0, document.body.scrollHeight);”)
driver.execute_script(„arguments[0].click();”, element)
„`
Nors JavaScript vykdymas yra galingas įrankis, stenkitės jį naudoti tik kaip paskutinę išeitį. Jei jūsų testai remiasi JavaScript, jie nebetestuoja tikros vartotojo patirties – tikri vartotojai nenaudoja JavaScript konsolės.
Headless režimas ir našumo optimizavimas
Kai paleidžiate testus lokalioje mašinoje, matyti naršyklės langą yra naudinga – galite stebėti, kas vyksta. Bet CI/CD pipeline’uose ar serveriuose, kur nėra grafinio interfeiso, reikia headless režimo. Be to, headless naršyklės veikia greičiau, nes nereikia renderinti UI.
Įjungti headless režimą Chrome’e:
„`python
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument(‘–headless’)
options.add_argument(‘–disable-gpu’)
options.add_argument(‘–no-sandbox’)
driver = webdriver.Chrome(options=options)
„`
Keli patarimai testų našumui pagerinti:
– **Išjunkite vaizdus ir CSS**: jei testuojate funkcionalumą, o ne išvaizdą, galite sutaupyti daug laiko
– **Naudokite mažesnę langų rezoliuciją**: nebent testuojate responsive dizainą
– **Išjunkite plėtinius**: jie gali lėtinti naršyklę
– **Uždarykite nereikalingus tab’us**: kiekvienas tab’as naudoja resursus
– **Naudokite vieną driver instanciją keliems testams**: naršyklės paleidimas yra brangi operacija
Tačiau būkite atsargūs su per agresyviu optimizavimu. Kartais testai headless režime elgiasi kitaip nei su pilnu UI. Visada patikrinkite, ar jūsų testai veikia abiem režimais prieš diegiant į produkciją.
Klaidos, debug’inimas ir geros praktikos
Selenium testai gali būti trapūs. Puslapiai keičiasi, tinklo ryšys gali būti nestabilus, naršyklės gali užstrigti. Štai kelios geriausios praktikos, kurios padės išvengti problemų:
**Screenshot’ai ir logai** – kai testas nepavyksta, screenshot’as yra neįkainojamas:
„`python
try:
element = driver.find_element(By.ID, „submit”)
element.click()
except Exception as e:
driver.save_screenshot(„error.png”)
print(f”Klaida: {e}”)
raise
„`
**Page Object Model (POM)** – vietoj to, kad rašytumėte visą Selenium kodą testuose, sukurkite atskiras klases kiekvienam puslapiui:
„`python
class LoginPage:
def __init__(self, driver):
self.driver = driver
def enter_username(self, username):
self.driver.find_element(By.ID, „username”).send_keys(username)
def enter_password(self, password):
self.driver.find_element(By.ID, „password”).send_keys(password)
def click_login(self):
self.driver.find_element(By.ID, „login-btn”).click()
„`
Tai daro testus lengviau prižiūrėti. Jei pasikeičia elemento ID, jums reikia pakeisti tik vienoje vietoje.
**Išvenkite hard-coded laukimo** – jau minėjome, bet verta pakartoti: niekada nenaudokite `time.sleep()`.
**Testuokite izoliuotai** – kiekvienas testas turėtų būti nepriklausomas. Jei vienas testas nepavyksta, kiti neturėtų nukentėti.
**Valykite duomenis** – jei testas sukuria duomenis duomenų bazėje, išvalykite juos po testo. Naudokite setup ir teardown metodus.
Kada Selenium nėra geriausias pasirinkimas
Nors Selenium yra galingas, jis ne visada yra tinkamas įrankis. Yra situacijų, kai turėtumėte apsvarstyti alternatyvas.
**API testavimui** – jei testuojate backend funkcionalumą, naudokite įrankius kaip Postman ar requests biblioteką Python’e. Selenium yra per lėtas ir per sudėtingas šiam tikslui.
**Našumo testavimui** – Selenium nėra sukurtas našumo testams. Naudokite JMeter, Gatling ar panašius įrankius.
**Modernių JavaScript framework’ų testavimui** – jei dirbate su React, Vue ar Angular, galite apsvarstyti Cypress ar Playwright. Jie greičiau veikia su SPA (Single Page Applications) ir turi geresnę developer experience.
**Web scraping’ui** – nors Selenium gali būti naudojamas duomenų ištraukimui, paprastesniems atvejams Beautiful Soup ar Scrapy yra efektyvesni. Selenium naudokite tik jei svetainė labai remiasi JavaScript’u.
**Mobile testavimui** – nors Selenium palaiko mobile naršykles per Appium, natyvių mobile aplikacijų testavimui yra geresni įrankiai.
Playwright ir Cypress pastaraisiais metais įgavo daug populiarumo kaip Selenium alternatyvos. Jie greičiau veikia, turi geresnes debugging galimybes ir modernesnę API. Tačiau Selenium vis dar turi didžiausią bendruomenę, palaiko daugiausia naršyklių ir turi daugiausiai integracijos su kitais įrankiais.
Realūs scenarijai ir kaip juos automatizuoti
Teorija yra gera, bet pažiūrėkime į kelis realius scenarijus, su kuriais tikrai susidursite.
**Prisijungimo testavimas su įvairiais atvejais:**
„`python
def test_login_success():
login_page = LoginPage(driver)
login_page.enter_username(„valid_user”)
login_page.enter_password(„valid_pass”)
login_page.click_login()
assert „Dashboard” in driver.title
def test_login_invalid_password():
login_page = LoginPage(driver)
login_page.enter_username(„valid_user”)
login_page.enter_password(„wrong_pass”)
login_page.click_login()
error = driver.find_element(By.CLASS_NAME, „error-message”)
assert „Neteisingas slaptažodis” in error.text
„`
**Failų įkėlimas:**
„`python
file_input = driver.find_element(By.CSS_SELECTOR, „input[type=’file’]”)
file_input.send_keys(„/path/to/file.pdf”)
„`
**Darbas su iframe:**
„`python
driver.switch_to.frame(„iframe_name”)
# dabar galite sąveikauti su elementais iframe viduje
driver.find_element(By.ID, „inside_iframe”).click()
driver.switch_to.default_content() # grįžti atgal
„`
**Darbas su alert’ais:**
„`python
alert = driver.switch_to.alert
print(alert.text)
alert.accept() # arba alert.dismiss()
„`
**Naujų langų valdymas:**
„`python
original_window = driver.current_window_handle
driver.find_element(By.LINK_TEXT, „Atidaryti naujame lange”).click()
for window_handle in driver.window_handles:
if window_handle != original_window:
driver.switch_to.window(window_handle)
break
# dabar dirbate naujame lange
driver.close() # uždaryti naują langą
driver.switch_to.window(original_window) # grįžti į originalų
„`
Šie pavyzdžiai parodo, kad Selenium gali susidoroti su beveik bet kokiu scenarijumi, kurį gali įsivaizduoti tikras vartotojas.
Ateitis ir ko tikėtis
Selenium WebDriver nėra statiškas projektas – jis nuolat vystomas. W3C WebDriver standartas dabar yra oficialus, o tai reiškia geresnę naršyklių palaikymą ir stabilumą. Selenium 4 atsirado su naujomis funkcijomis: geresnė dokumentacija, relative locators, Chrome DevTools Protocol palaikymas, pageLoadStrategy parinktys.
Relative locators leidžia rasti elementus pagal jų santykį su kitais elementais:
„`python
from selenium.webdriver.support.relative_locator import locate_with
password_field = driver.find_element(locate_with(By.TAG_NAME, „input”).below({By.ID: „username”}))
„`
CDP (Chrome DevTools Protocol) integracija leidžia daryti dalykus, kurie anksčiau buvo neįmanomi: perimti tinklo užklausas, emuliuoti geografinę vietą, keisti tinklo greitį testavimui.
Konkurencija iš Playwright ir Cypress verčia Selenium tobulėti. Tai gera žinia visiems – geresnė developer experience, greitesnis vykdymas, stabilesni testai.
Tačiau nepriklausomai nuo naujų įrankių, Selenium lieka standartu daugelyje organizacijų. Jei mokate Selenium, tas žinias galėsite pritaikyti beveik bet kuriame projekte. Investicija į Selenium mokymąsi vis dar yra prasminga 2024 metais ir tikėtina, kad bus prasminga dar daugelį metų.
Automatizuoti testai nėra prabanga – tai būtinybė moderniam programinės įrangos kūrimui. Selenium WebDriver suteikia jums galią kurti patikimus, pakartojamus testus, kurie leidžia greitai išleisti kokybišką produktą. Taip, pradžioje gali atrodyti sudėtinga, bet kai įvaldysite pagrindus, galimybės yra beribės. Pradėkite nuo paprastų testų, mokykitės iš klaidų, skaitykite dokumentaciją ir nebijokite eksperimentuoti. Jūsų ateities aš dėkos už laiko investiciją šiandien.
