WebDriver+Selenium實現(xiàn)瀏覽器自動化

前言

Selenium是一款可以自動化操作瀏覽器的開源項目,最初的目的是瀏覽器功能的自動化測試压彭,但是隨著項目的發(fā)展,人們根據(jù)它的特性也用來做一些更多的有意思的功能而不僅僅是UI的自動化測試工具辱匿。就像Selenium官方網(wǎng)站上描述的那樣灶泵,Selenium可以自動化操縱瀏覽器。完了补箍!你想用它的能力做什么事情完全取決于你改执。

使用場景

針對瀏覽器的自動化測試有三個場景:

  • Selenium WebDriver:如果您想創(chuàng)建健壯的、基于瀏覽器的回歸自動化套件和測試坑雅、在許多環(huán)境中擴展和分發(fā)腳本辈挂,那么您需要使用 Selenium WebDriver,它是一組特定于語言的綁定來驅(qū)動瀏覽器——這就是它的本意驅(qū)動的
  • Selenium IDE:如果您想創(chuàng)建快速的錯誤重現(xiàn)腳本裹粤,創(chuàng)建腳本以幫助自動化輔助探索性測試终蒂,那么您想使用 Selenium IDE; Chrome遥诉、Firefox 和 Edge 插件拇泣,可以對與瀏覽器的交互進行簡單的記錄和回放
  • Selenium Grid:如果您想通過在多臺機器上分發(fā)和運行測試來擴展并從一個中心點管理多個環(huán)境,從而可以輕松地針對大量瀏覽器/操作系統(tǒng)組合運行測試突那,那么您需要使用 Selenium Grid

原理

早期的Selenium目的是實現(xiàn)web應用的UI自動化測試挫酿,實現(xiàn)方式是通過三方的服務器注入js達到控制瀏覽器行為的目的,核心的組件叫Selenium-RC(Remote Control)
包含兩個部分:

  • 客戶端側(cè)的編寫控制瀏覽器邏輯的庫
  • 實現(xiàn)控制瀏覽器啟動和關(guān)閉的服務器

架構(gòu)如下

image.png

這種架構(gòu)被證明是復雜的愕难,而且有諸多限制早龟,比如:

  • 復雜的架構(gòu)
  • 執(zhí)行測試腳本非常耗時,因為 Selenium RC 使用 JavaScript 命令作為瀏覽器的指令猫缭。這會導致性能下降
  • API不太面向?qū)ο?/li>
  • 不支持 Headless HTMLUnit 瀏覽器(不可見的瀏覽器)

Selenium RC 的局限性導致了新的自動化框架 Selenium WebDriver 的開發(fā)葱弟。在 2006 年引入 WebDriver 后,RC 中出現(xiàn)的復雜問題可以得到解決和解決
Selenium 結(jié)合WebDriver簡化了瀏覽器的控制行為猜丹,將中間環(huán)節(jié)的服務器去掉芝加,直接在系統(tǒng)層級本地化控制瀏覽器,優(yōu)化后的架構(gòu)如下:


image.png

環(huán)境準備

如果你不想在編碼層實現(xiàn)你的功能射窒,可以下載Selenium IDE插件藏杖,支持錄制回放,過程腳本導出脉顿。

image.png

如果需要通過代碼實現(xiàn)更多靈活自定義功能蝌麸,建議使用python,環(huán)境準備
python3艾疟、pip3

brew install python3

selenium

pip3 install selenium

install browser drivers
設(shè)置您的系統(tǒng)以允許瀏覽器自動化来吩。
通過 WebDriver敢辩,Selenium 支持市場上所有主流瀏覽器,例如 Chrome/Chromium弟疆、Firefox戚长、Internet Explorer、Edge怠苔、Opera 和 Safari同廉。在可能的情況下,WebDriver 使用瀏覽器的內(nèi)置自動化支持來驅(qū)動瀏覽器


image.png

開發(fā)

First Script

通過webdriver實現(xiàn)控制瀏覽器自動訪問功能


def test_eight_components():
    driver = webdriver.Chrome()
    
    driver.get("https://google.com")
    
    title = driver.title
    assert title == "Google"
    
    driver.implicitly_wait(0.5)
    
    search_box = driver.find_element(by=By.NAME, value="q")
    search_button = driver.find_element(by=By.NAME, value="btnK")
    
    search_box.send_keys("Selenium")
    search_button.click()
    
    search_box = driver.find_element(by=By.NAME, value="q")
    value = search_box.get_attribute("value")
    assert value == "Selenium"
    
    driver.quit()

WebDriver API

webDriver操縱瀏覽器的API大致可以分為兩個部分嘀略,控制瀏覽器行為的比如恤溶,打開、關(guān)閉帜羊、前進咒程、后退、刷新等和控制頁面元素的如讼育,點擊帐姻、輸入、獲取元素內(nèi)容等

瀏覽器

獲取瀏覽器信息

// title
driver.getTitle(); 
// url
driver.getCurrentUrl();

導航

//打開
driver.get("https://selenium.dev");

//跳轉(zhuǎn)
driver.navigate().to("https://selenium.dev");

// 后退
driver.navigate().back();

// 前進
driver.navigate().forward();

// 刷新
driver.navigate().refresh();

彈框

//根據(jù)條件找到頁面中的彈框并點擊
driver.findElement(By.linkText("See an example alert")).click();

//等待彈框展示并保存到變量中
Alert alert = wait.until(ExpectedConditions.alertIsPresent());

//獲得彈框內(nèi)容文本
String text = alert.getText();

//點擊確定按鈕
alert.accept();
  

Alert奶段、Confirm饥瓷、Prompt功能類似
Cookies
可以支持cookies的添加刪除操作

import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;

public class addCookie {
    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();
        try {
            driver.get("http://www.example.com");

            // Adds the cookie into current browser context
            driver.manage().addCookie(new Cookie("key", "value"));
        } finally {
            driver.quit();
        }
    }
}

Frames
支持針對Frames內(nèi)元素的獲取及操作
Windows
WebDriver 不區(qū)分窗口和選項卡。如果您的站點打開一個新選項卡或窗口痹籍,Selenium 將允許您使用窗口句柄來處理它呢铆。每個窗口都有一個唯一標識符,該標識符在單個會話中保持不變蹲缠。您可以使用以下方法獲取當前窗口的窗口句柄:

driver.getWindowHandle();

元素

識別和使用DOM中的元素
大多數(shù)人的 Selenium 代碼大部分都涉及使用 Web 元素棺克。這部分功能和寫前端代碼的document.getElementById作用差不多,思想比較簡單线定,就是找到頁面中的元素然后執(zhí)行模擬用戶行為的操作
支持絕對定位和相對定位的策略娜谊,針對復雜頁面ID,Tag斤讥,Class不好定位的情況可以使用xPath方式纱皆,非常靈活,其實也不用死記硬背芭商,當某元素不好定位時派草,可以去官網(wǎng)查API的方式去實現(xiàn)
相對定位

image.png

def relative():
    # Above
    email_locator = locate_with(By.TAG_NAME, "input").above({By.ID: "password"})
    # Below
    password_locator = locate_with(By.TAG_NAME, "input").below({By.ID: "email"})
    # Left of
    cancel_locator = locate_with(By.TAG_NAME, "button").to_left_of({By.ID: "submit"})
    # Right of
    submit_locator = locate_with(By.TAG_NAME, "button").to_right_of({By.ID: "cancel"})
    # Near
    email_locator = locate_with(By.TAG_NAME, "input").near({By.ID: "lbl-email"})
    # Chaining relative locators
    submit_locator = locate_with(By.TAG_NAME, "button").below({By.ID: "email"}).to_right_of({By.ID: "cancel"})

傳統(tǒng)定位

<ol id="vegetables" style="margin-top: 20px">
      <li class="potatoes">potatoes</li>
      <li class="onions">onions</li>
      <li class="tomatoes"><span>Tomato is a Vegetable</span></li>
    </ol>
    <ul id="fruits">
      <li class="bananas"></li>
      <li class="apples"></li>
      <li class="tomatoes"><span>Tomato is a Fruit</span></li>
     </ul>

def finders():
    # Evaluating entire DOM
    vegetable = driver.find_element(By.CLASS_NAME, "tomatoes")
    print(vegetable)
    # Evaluating a subset of the DOM
    fruits = driver.find_element(By.ID, "fruits")
    fruit = fruits.find_elements(By.CLASS_NAME, "tomatoes")
    print(fruit)
    # Optimized locator
    fruit = driver.find_element(By.CSS_SELECTOR, "#fruits .tomatoes")
    fruit2 = driver.find_element(By.CSS_SELECTOR, "ul .tomatoes")
    print(fruit == fruit2) # True
    # All matching elements
    plants = driver.find_elements(By.TAG_NAME, "li")
    print(plants)
    # Get all the elements available with tag name 'p'
    elements = driver.find_elements(By.TAG_NAME, 'span')
    for e in elements:
        print(e.text)


def xPath():
    ol = driver.find_element(By.XPATH, "/html/body/div/div/ol[1]")
    ol2 = driver.find_element(By.XPATH, "http://ol[1]")
    ol3 = driver.find_element(By.XPATH, "http://ol[@id='vegetables']")
    print(ol == ol2) # True
    print(ol == ol3) # True
    onions = driver.find_element(By.XPATH, "http://ol[1]/li[2]")
    print(onions.text)

交互
5種基本命令:

  • click(任意元素)
  • send keys(僅用于文本塊和內(nèi)容可編輯元素)
  • clear(同上)
  • submit (form 元素)
  • select (選擇列表元素)

獲取元素信息

image.png

總結(jié)

本次分享介紹了Selenium使用場景,簡單原理和一些的基礎(chǔ)用法铛楣。并列舉了一個小例子近迁。掌握以上內(nèi)容,你已經(jīng)可以實現(xiàn)基本的UI自動化測試了蛉艾。另外可以做一些爬蟲和自動化操縱瀏覽器的工具需求就需要根據(jù)個人場景化定制了钳踊,只要你有“懶”的天性,相信一定會找到挺多有意思場景使用去使用它勿侯。

參考

https://www.selenium.dev/
https://www.browserstack.com/guide/selenium-rc-tutorial

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拓瞪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子助琐,更是在濱河造成了極大的恐慌祭埂,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兵钮,死亡現(xiàn)場離奇詭異蛆橡,居然都是意外死亡,警方通過查閱死者的電腦和手機掘譬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門泰演,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人葱轩,你說我怎么就攤上這事睦焕。” “怎么了靴拱?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵垃喊,是天一觀的道長。 經(jīng)常有香客問我袜炕,道長本谜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任偎窘,我火速辦了婚禮乌助,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘评架。我一直安慰自己眷茁,他們只是感情好,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布纵诞。 她就那樣靜靜地躺著上祈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪浙芙。 梳的紋絲不亂的頭發(fā)上登刺,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機與錄音嗡呼,去河邊找鬼。 笑死揍很,一個胖子當著我的面吹牛窒悔,可吹牛的內(nèi)容都是我干的呜袁。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼阶界,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了聋庵?” 一聲冷哼從身側(cè)響起膘融,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤氧映,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后疗绣,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體铺韧,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年湾盗,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帐萎。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖澈段,靈堂內(nèi)的尸體忽然破棺而出李剖,到底是詐尸還是另有隱情,我是刑警寧澤充择,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站观挎,受9級特大地震影響显熏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一橙弱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦奴艾、人聲如沸像啼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間怖侦,已是汗流浹背谜叹。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工女仰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留一罩,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓找蜜,卻偏偏與公主長得像洗做,于是被迫代替她去往敵國和親裕菠。 傳聞我的和親對象是個殘疾皇子闭专,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容