1. 程式人生 > >Selenium自動化測試-入門

Selenium自動化測試-入門

一、什麼是Selenium

Selenium 是一個瀏覽器自動化測試框架,它主要用於web應用程式的自動化測試,其主要特點如下:開源、免費;多平臺、瀏覽器、多語言支援;對web頁面有良好的支援;API簡單靈活易於使用;支援分散式測試用例執行。
Selenium經歷了兩個版本,Selenium1.0和2.0,Selenium1.0主要由以下幾部分構成:

  • Selenium IDE:是一個嵌入到Firefox中的外掛,可以實現瀏覽器的錄製於回放功能。
  • Selenium Grid:自動化測試輔助工具,可以很方便地同時在多臺機器上並行執行多個測試事例。
  • Selenium RC:是Selenium的核心工具,支援多種不同的語言編寫的測試指令碼,通過Selenium RC的伺服器作為代理伺服器去訪問應用從而達到測試的目的。主要分為以下兩部分:

    1. Client:用來編寫測試指令碼來控制Selenium server的庫。
    2. Server:負責控制瀏覽器的行為,包含三部分:Launcher;HttpProxy;Core。

    明白了Selenium1.0的家族關係,Selenium2.0可以簡單的認為是將WebDriver加入到了Selenium RC這一部分中去。那麼Selenium RC和WebDriver有什麼區別呢? RC和 WebDriver 類似,都可以看做是一套操作web頁面的規範。當然,他們的工作原理不一樣。

  • Selenium RC 在瀏覽器中執行 JavaScript 應用,使用瀏覽器內建的 JavaScript 翻譯器來翻譯和執行selenese 命令(Selenium 命令集合) 。
  • WebDriver 通過原生瀏覽器支援或者瀏覽器擴充套件直接控制瀏覽器。WebDriver 針對各個瀏覽器而開發,取代了嵌入到被測 Web 應用中的 JavaScript。與瀏覽器的緊密整合支援建立更高階的測試,避免了JavaScript 安全模型導致的限制。除了來自瀏覽器廠商的支援,WebDriver 還利用作業系統級的呼叫模擬使用者輸入。

以後我們基本都用Selenium2.0來進行學習和指令碼編寫,並且選定Python語言作為編寫指令碼的語言,其實各種語言編寫指令碼都大同小異。

二、Selenium環境搭建

1. 安裝Python

這裡暫時只說windows下的。訪問Python官網:

https://www.Python.org/選擇下載Python2或者3系列,直接點選安裝,注意勾選將其自動新增至系統環境變數中,並且勾選自動安裝pip,便於我們直接從cmd中使用。具體步驟不再多說,網上教程很多。

2. 安裝Selenium

安裝好了Python環境之後,我們直接用pip install Selenium命令來安裝Selenium。

3. 安裝瀏覽器驅動

這裡我們需要知道的是Firefox的驅動已經整合在了Selenium WebDriver包中了,不用我們自己安裝了。下面看一個簡單了例子:

#coding=utf-8
from Selenium import webdriver

#瀏覽器驅動
driver=webdriver.Firefox()
driver.get("https://www.baidu.com")

driver.find_element_by_id("kw").send_keys("Selenium2")
driver.find_element_by_id("su").click()
driver.quit()

這個簡單的例子做的事是:開啟Firefox,訪問百度首頁,輸入Selenium2關鍵字進行搜尋,退出。執行它,我們可以看見以下頁面:

Selenium2-Firefox

如果我們想要使用其他的瀏覽器呢?首先必須要下載響應瀏覽器的驅動,我們可以訪問http://docs.Seleniumhq.org/download/來下載相關的驅動,並將其放在系統路徑中。比如我們這裡把Firefox改為Chrome,再執行程式可以看見:

Selenium2-Chrome

4. 其他工具安裝

這裡我們主要使用Firefox來進行演示,還需要安裝一些外掛來方便我們後面的控制元件抓取。可以直接訪問https://addons.mozilla.org/zh-CN/firefox/來搜尋和安裝一些外掛,比如常用的XPath和Firebug等。

環境搭建完成以後我們要做的就是開始學習編寫指令碼的API了。

三、WebDriver API

本節的內容是,在Python語言中,如何通過Selenium WebDriver提供的各種方法來實現web自動化測試。我們會學習一下各種操作web頁面的API。這裡推薦一個特別好的寫示例Demo用的網站http://sahitest.com/demo/index.htm,它裡面基本可以找到我們需要的所有場景。

1. 定位元素

通過firebug等工具我們可以看見頁面上的各種元素,如下圖:

firebug百度首頁

每個元素都有不同的標籤名和屬性名等,Selenium可以通過這些來定位元素。在WebDriver中有以下定位元素的方法:

  • id
  • name
  • class name
  • tag name
  • link text
  • partial link text
  • XPath
  • css selector

    對應的在Python中定位的方法如下:
    find_element _by_id()
    find_element _by_name()

    等等八種方式(僅僅更換了關鍵字)。

上面這些定位方式除了最後兩種外,我們只需要看它的名字就很明顯可以知道,它到底是怎麼定位的。但是有個問題是?我們怎麼得到這些屬性,可以看見即使通過firebug或檢視原始碼去觀察元素時,也是比較麻煩和不直觀的。這裡我們就要用到最後這兩種強大的工具了。

XPath定位:

在前面我們說到了安裝XPath工具,如果安裝成功了之後,在一個網頁的任意位置,單擊右鍵可以看到以下頁面:

Firefox-xpath

通過firebug可以看出來一些元素的屬性等資訊,如以下片段是搜尋框和按鈕的資訊:

<span class="bg s_ipt_wr quickdelete-wrap">
<span class="soutu-btn"></span>
<input id="kw" class="s_ipt" name="wd" value="" maxlength="255" autocomplete="off">
<a id="quickdelete" class="quickdelete" href="javascript:;" title="清空" style="top: 0px; right: 0px; display: none;"></a>
</span>
<span class="bg s_btn_wr">
<input id="su" class="bg s_btn" value="百度一下" type="submit">
</span>

圖中我們是在百度搜索的搜尋框中點選了右鍵,選中XPaths之後,可以看到顯示出了很多種定位此元素的方法,從中我們也可以得到此元素的各種資訊。這時在相應的方法上單擊右鍵或左鍵就可以將其複製下來。

使用絕對路徑定位 很顯然我們要定位一個元素的話,可以從第一層一直往下找,最終一定會找到這個元素的:

firebug-百度kw

可以從上圖看到,如果想定位到搜尋框的話,採用絕對路徑定位的話,其層級有十層之多,太煩人類了!

使用元素屬性定位 我們來分析一下這種格式,比如//input[@id='kw'],如果要在指令碼中使用的話,應該是find_element_by_xpath("//input[@id='kw']"),這裡的//表示當前頁面的某個目錄下,input表示定位元素的標籤名,[@id=’kw’]表示這個元素的id屬性值為kw。同理我們還可以用其他的屬性值來定位,如name、class,元素的任意屬性值都可以用,只要它可以標識唯一的一個元素。
如果屬性有重複的話,可以使用邏輯運算子來連線多個屬性從而區別其他屬性。比如:find_element_by_xpath("//input[@id='kw' and @name='wd']")

CSS選擇器定位

css選擇器

根據以上語法,我們可以使用

driver.find_element_by_css_selector("#kw")
driver.find_element_by_css_selector(".s_ipt")
driver.find_element_by_css_selector("map>area")

等等方式來定位元素。可以使用如下方式得到CSS層級:

CSS選擇器

複製之後,粘貼出來可以看到如下字串:

html body div#wrapper div#head div.head_wrapper div.s_form div.s_form_wrapper.soutu-env-nomac.soutu-env-index div#lg map area

可以得到規律:層級之間用空格分隔,元素定位的方式會展示出來。(如,使用標籤名的html、使用class的div.s_form、使用id的div#lg等等)所以我們上面可以使用map>area(父標籤>子標籤)來定位百度首頁那張圖片的位置。

關於更多CSS選擇器的用法不做更多的解釋了,可以檢視官方文件等方式來檢視使用方法!我們可以熟練的使用XPath或CSS選擇器中的一種,就可以解決大部分定位的問題了。

2. 控制瀏覽器

控制瀏覽器視窗大小:

driver=webdriver.Firefox()
#設定視窗大小為x,y
driver.set_window_size(x,y) 
#最大化視窗
driver.maxmize_window()

控制瀏覽器前進後退:
類似於點選前進後退按鈕,實現頁面切換。要注意的是,我們開啟的頁面是不是新建了一個標籤頁,是不是有上級頁面可以返回。

driver=webdriver.Firefox()
driver.get("https://www.baidu.com")
driver.find_element_by_css_selector("div#u1>a.mnav").click()
driver.back()
driver.forward()

3. 元素操作

當我們獲取了元素之後,還要對其進行操作,如點選按鈕、輸入文字、提交表單等。大多數頁面互動的方法通過WebElement介面提供,常用的有:

clear() 清除文字框中的文字
send_keys(*value) 模擬按鍵輸入
click() 單擊元素

這幾個方法很簡單,很方便使用。

submit() 用於提交表單,例如搜尋框中的提交按鈕。比如我們可以用如下程式碼直接輸入搜尋的關鍵字後用submit()提交,而不用獲取搜尋按鈕再點選。

driver.find_element_by_css_selector("#kw").send_keys("selenium2").submit()

還有幾個常用的方法:

size() 獲取元素的大小尺寸
text()獲取元素的文字
is_displayed()元素是否可見

4. 滑鼠、鍵盤事件

模擬滑鼠右鍵、雙擊、懸停、拖拽等操作,會用到ActionChains類。selenium.webdriver.common.action_chains.ActionChains(driver)當呼叫ActionChains的方法時,不會立即執行,而是會將所有的操作按順序存放在一個佇列裡,當你呼叫perform()方法時,佇列中的時間會依次執行。

ActionChains方法列表:

click(on_element=None) ——單擊滑鼠左鍵
click_and_hold(on_element=None) ——點選滑鼠左鍵,不鬆開
context_click(on_element=None) ——點選滑鼠右鍵
double_click(on_element=None) ——雙擊滑鼠左鍵
drag_and_drop(source, target) ——拖拽到某個元素然後鬆開
drag_and_drop_by_offset(source, xoffset, yoffset) ——拖拽到某個座標然後鬆開
key_down(value, element=None) ——按下某個鍵盤上的鍵
key_up(value, element=None) ——鬆開某個鍵
move_by_offset(xoffset, yoffset) ——滑鼠從當前位置移動到某個座標
move_to_element(to_element) ——滑鼠移動到某個元素
move_to_element_with_offset(to_element, xoffset, yoffset) ——移到距某個元素(左上角)多少距離的位置
perform() ——執行鏈中的所有動作
release(on_element=None) ——在某個元素位置鬆開滑鼠左鍵
send_keys(*keys_to_send) ——傳送某個鍵到當前焦點的元素
send_keys_to_element(element, *keys_to_send) ——傳送某個鍵到指定元素 

這些滑鼠鍵盤事件相對來說用的並不是很多,我們只需要熟練使用最常用的那些,剩下的都差不多。

5. 獲取驗證資訊

我們在編寫功能測試用例時,一般會有預期結果,在自動化用例執行完成之後,我們可以從頁面上獲取一些資訊來驗證用例是執行失敗還是成功。最常用的幾種如下:

driver.title -獲取當前頁的title
driver.current_url -獲取當前頁面URL
driver.find_element_by_...(...).text -獲取當前控制元件的text資訊

6.設定等待時間

顯示等待: - 主要使用的類和方法:WebDriverWait、uitil\until_not、Expected Conditions。
請看以下簡單示例:

# coding=utf-8
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver=webdriver.Firefox()
driver.get("http://www.qq.com/")

element=WebDriverWait(driver,5,0.5).until(EC.title_is(U"騰訊首頁"))

print(element)

這裡呼叫WebDriverWait來實現,在預設的一段時間內,每隔一段時間檢測一次當前的頁面指定元素是存在。

WebDriver wait

WebDriverWait()

如圖所示,WebDriverWait有四個引數,WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None),分別是:driver;超時時間,檢測間隔;超時後的異常資訊。

until()和until_not()

WebDriverWait()一般和until()或until_not()配合使用,until(method,message=’ ‘) 呼叫該方法提供的驅動程式作為一個引數,直到返回值為true,同理可知道until_not(method,message=’ ‘),呼叫該方法提供的驅動程式作為一個引數,直到返回值應該為false。

其中的引數method,應該使用什麼方法呢?這裡就要用到另一個常用的類了:

expected_conditions

注意,在上面的code中我們用as將其重新命名為了EC,這個類有很多種方法可以選用:

1

2

可以看到裡面有很多的方法可以用來判斷是否存在相應的元素。當然這裡的method我們也可以用其他的方法,比如:WebDriverWait(driver,5,0.5).until(lambda driver: driver.find_element_by_xpath("//a[@bosszone='news_n']")),用這樣的方式來判斷是否顯示出了響應的元素。

隱式等待: - implicitly_wait

隱式等待相對於顯式等待就要簡單多了,driver.implicitly_wait(n),n代表等待的秒數, 隱式等待相當於設定全域性的等待,在定位元素時,對所有元素設定超時時間,超出了設定時間則丟擲異常,預設是0。如果元素定位不到,則以輪詢的方式不斷定位,直到超時時間到達。

強制等待-sleep休眠方法: - Python的time模組提供,sleep(n),n為秒數。程式執行到這裡的時候,強制暫停所設定的時長。

7. 定位一組元素

在前面我們說到了8種定位方法,是對單元素定位的。WebDriver還提供了與之對應的8種定位方法用於定位一組元素。區別在於element後面加了一個s,如下:

find_elements_by_id()
find_elements_by_name()
...

一般用於以下場景:

  • 批量操作物件:如將所有的複選框選中\取消選中
  • 先獲取一組物件,然後在這組物件中過濾出具體定位的物件

8. 多表單、多視窗切換

多表單頁面:如圖所示我們如果直接操作,去點選Link Test(frame中的元素),是不可以的,因為我們首先需要切換到這個frame裡面才可以進行操作。

iframe

通過firebug工具可以得到此頁面的原始碼,便於我們定位元素:

iframe原始碼

switch_to_frame(引數)方法,引數可以是iframe的id、name,如果沒有的話,也可以傳入locator;switch_to_default_content()方法,用來返回上一層表單,預設與據它最近的switch_to_frame方法對應。

#coding=utf-8
from selenium import webdriver

driver=webdriver.Firefox()
driver.get("http://sahitest.com/demo/iframesTest.htm")
#切換到frame裡面去
driver.switch_to_frame(driver.find_element_by_xpath("/html/body/iframe"))
#進行操作
driver.find_element_by_link_text("Link Test").click()
#退出至上一層表單
driver.switch_to_default_content()

多視窗切換:如果我們打開了多個視窗,然後想切換到其中的一個視窗呢?那就要用到switch_to_window這個方法了,請看如下程式碼片段:

driver=webdriver.Firefox()
driver.get("http://www.qq.com/")

#獲取qq首頁視窗控制代碼
first_windows=driver.current_window_handle

driver.find_element_by_xpath("//a[@bosszone='news_n']").click()

#當前所有開啟的視窗控制代碼
all_handles=driver.window_handles

#進入到首頁視窗
for handle in all_handles:
    if handle==first_windows:
        driver.switch_to_window(handle)
        print("In first_windows")

#從首頁開啟"圖片"頁
driver.find_element_by_xpath("//a[@bosszone='photo_n']").click()

9. 警告框處理

在WebDriver中處理js生成的alert、confirm、prompt是很簡單的,即用switch_to_alert()方法定位到彈出框,再使用text/accept/dismiss/send_keys進行操作。看如下程式碼片段:

# coding=utf-8
from selenium import webdriver
import time

driver=webdriver.Firefox()
driver.get("https://www.baidu.com/")

#點選設定
driver.find_element_by_css_selector("div#u1 a.pf").click()
#點選編輯設定
driver.find_element_by_class_name("setpref").click()
time.sleep(1)
#儲存設定
driver.find_element_by_css_selector("div#gxszButton>a.prefpanelgo").click()
time.sleep(1)
#接收彈窗
driver.switch_to_alert().accept()

10. 操作滾動條&截圖

操作滾動條:

可以使用js指令碼,拖動到指定地方,用
driver.execute_script("arguments[0].scrollIntoView();", target),這個方法來拖動滾動條到指定的地方。其實元素沒在一屏,也可以直接定位並點選的。

# coding=utf-8
from selenium import webdriver

driver=webdriver.Firefox()
driver.get("http://www.qq.com/")

#定位到“體育社群”
target = driver.find_element_by_xpath("//a[@href='http://sports.qq.com/fans/']")
#滾動到“體育社群”
driver.execute_script("arguments[0].scrollIntoView();", target)

截圖:

截圖操作也很簡單,使用driver.get_screenshot_as_file(path)即可完成截圖,之後 可以藉助PIL模組來進行各種處理。

11. 其他操作

還有其他一些操作如:上傳下載檔案、操作cookie、驗證碼的處理等等操作還沒有用到過,這些用的場景較少並且有的還比較複雜,用到的時候再去學習就好了。
熟練使用以上的各部分,可以寫出各種常用的指令碼,我們算是入門Selenium了。:)