使用Python學習selenium測試工具

發表於2016-03-15

 

快速入門

Selenium是一個簡便的Web應用軟體測試框架。Selenium的元件Selenium IDE支援錄製/回放。它還支援Python,Java,C#,javascript等語言。支援Windows,Linux和Macintosh。它是 開源軟體,根據Apache2.0許可證釋出的,並可以下載並無償使用。

 

歷史

Selenium來源於由傑森·哈金斯 (Jason Huggins)在2004年在ThoughtWorks的開發內部工具,後面有ThoughtWorks的其他程式設計師和測試人員在 ThoughtWorks加入。後來Paul Hammant加入開發了’Selenium Remote Control’ (RC)並開源。

2005年Dan Fabulich和Nelson Sproul在Pat Lightbody的幫助下給Selenium-RC做了一些補丁。同時ThoughtWorks在Huggins和Hammant代表的情況下組建了Selenium委員會。

2007 年哈金斯和Jennifer Bevan等加盟谷歌。他繼續Selenium RC的開發和穩定。與此同時,西蒙·斯圖爾特(Simon Stewart)在ThoughtWorks開發出了卓越的瀏覽器自動化工具webdriver。2009年在谷歌測試自動化大會上決定合併兩個專案,新 專案叫Selenium WebDriver,即Selenium 2.0。

2008年,ThoughtWorks的Philippe Hanrigou開發了’Selenium Grid’,支援同時在任意數量的本地或遠端系統執行多個Selenium測試,從而減少測試執行時間。Selenium Grid提供類似谷歌內部Selenium RC雲專案的功能,但是它是開源的。Pat Lightbody也開發了一個類似的私有云:’HostedQA’,並賣給了Gomez公司。

當時有個類似的軟體叫Mercury,及汞,哈金斯就取名為硒,可以通過服用硒補充劑治癒汞中毒。

 

元件

支援瀏覽器: Firefox、Internet        Explorer、Google Chrome、Safari和Opera。

支援作業系統:Linux, Windows和Mac OS X。

  • Selenium IDE

Selenium IDE是Selenium測試完整的整合開發環境(IDE)。它是Firefox外掛,並允許錄製,編輯和除錯。這是以前被稱為Selenium Recorder,最初是由Shinya Kasatani開發並於2006年捐贈給Selenium。

指令碼會自動錄製,可以事後編輯,編輯時可以自動完成並快速移動命令。指令碼記錄在Selenese的(Selenium特殊的測試指令碼語言)。Selenese可以在瀏覽器中執行操作命令(如點選連結,選擇選項),並從網頁中檢索資料。

  • Selenium client API

目前支援Python, Java,C#,Ruby。

  • Selenium Remote Control(webdriver已經棄用)

Selenium Remote Control (RC)是Java編寫的服務,通過HTTP接收瀏覽器的命令(類似代理伺服器)。RC支援多種程式語言對Web應用進行測試,方便整合進語言的單元測試 框架。支援PHP,Python和Ruby,.NET,Perl和Java客戶端驅動程式。java驅動通過Rhino engine支援JavaScript。一個埠只支援一個例項,但是Java/PHP中一個埠可以支援多個例項。RC來源於Paul Hammant和Jason。

Selenium Remote Control來源於Paul Hammant的Driven Selenium或Selenium B。最初的版本直接在程式語言中啟動程式和瀏覽器互動,Selenese在各種語言中實現。Dan Fabulich和Nelson Sproul在Pat Lightbody的幫助下改進後,測試指令碼和和瀏覽器之間增加了守護程式,這樣就可以驅動遠端瀏覽器,並只需要維護一套Selenese語言。2006 年RC完全替代Driven Selenium。RC和Driven Selenium瀏覽器模式是響應/請求,即Comet。

Selenium 2釋出時,已經建議用webdriver替代RC。

  • Selenium WebDriver:

Selenium WebDriver是RC的替代。它接受命令(Selenese或者API),併傳送給瀏覽器。呼叫特定瀏覽器的驅動,傳送命令到瀏覽器,並獲取結果。多 數瀏覽器驅動啟動和訪問瀏覽器應用程式(如Firefox或Internet Explorer);另外還有瀏覽器的HtmlUnit驅動程式,它用模擬使用瀏覽器。

Selenium WebDrive不需要特殊的伺服器來執行測試。webdriver直接啟動瀏覽器例項並控制它。Selenium Grid可以用於的webdriver執行遠端測試。

2012 年初,Simon Stewart(webdriver的發明者,當時在google工作,現在在Facebook)和Mozilla的David Burns與W3C協商將WebDriver作為網際網路標準。2013年初草案發布,Selenium-Webdriver為參考實現。目前 Selenium-WebDriver在Python和Ruby,Java和C#有完整的支援。

  • Selenium Grid(Selenium standalone server)

Selenium Grid是允許在遠端機器上執行的Web瀏覽器例項的服務。Selenium Grid允許執行測試在多臺計算機上並行,以及管理的不同版本的瀏覽器和瀏覽器配置。甚至支援移動作業系統:Android和Apple iOS。

 

快速入門

Selenium WebDriver python client可以訪問Selenium WebDriver和Selenium standalone server,開發人員:David        Burns,        Adam Goucher, Maik Röder,Jason        Huggins, Luke        Semerau, Miki Tebeka和Eric Allenin。支援python版本2.6, 2.7, 3.2和3.3。

安裝:

需要選擇一個合適IDE,要求如下:

  • 程式碼完成和智慧提示的圖形化程式碼編輯器
  • 函式和類的程式碼瀏覽器
  • 語法高亮
  • 專案管理
  • 程式碼模板
  • 單元測試和除錯
  • 原始碼控制支援

推薦:WingIDE,PyCharm,PyDev Eclipse plugin,PyScripter。相關下載地址如下:

例項1:在網站python自動化測試上面尋找webdriver相關的頁面,並輸出相關的網址:

注意:本例項因為http://automationtesting.vipsinaapp.com及http://automationtesting.sinaapp.com已經因為新浪收費原因關閉匿名使用者查詢,已經不能執行。

selenium.webdriver實現了瀏覽器驅動類,涉及 Firefox, Chrome, Internet Explorer,        Safari等瀏覽器及用於測試遠端機器的類RemoteWebDriver。

driver.implicitly_wait(30)表示最多等待頁面開啟的時間為30秒。

執行結果:

例項2開啟網址,搜尋產品,並列出產品名。例項的網站為:magentocommerce,程式碼下載地址:learnsewithpython

注意:上面演示的網址可能需要梯子

執行結果:

 

跨瀏覽器支援

 

IE

selenium下載頁面地址。為了在Internet Explorer上面執行,需要下載配置InternetExplorerDriver服務,它是測試指令碼和Internet Explorer之間的膠水。

在上述下載頁面搜尋InternetExplorerDriver,下載32位或者64位版本,並解壓到合適的目錄。在IE7以上的版本,選擇Tools 選單下面的Internet Options,在彈出視窗選擇Security標籤,把每個zone的Protected Mode設定為關或者開啟的情況都設定為中。另外要特別注意IE的縮放要選擇為100%才正確地進行座標對應。

例項1:

例項2:

執行結果和火狐的類似。

參考資料:

 

Chrome

ChromeDriver由Chromium開發,安裝方法和IE的類似,但是不需要設定Protected Mode。 例項1:

例項2:

參考資料:

 

 

 

在unittest中使用

 

unittest可以為webdriver增加setup、teardown、檢查應用狀態、報告測試結果、資料驅動等功能。主要內容如下:

  • 什麼是unittest?
  • 使用unittest來編寫webDriver測試
  • 基於TestCase類實現測試
  • 理解各種型別的assert方法
  • 建立一組測試為TestSuite
  • 使用unittest擴充套件生成HTML格式的測試報告

 

unittest庫

主要組成如下:

  • Test Fixture:準備及清理工作。
  • Test Case: 通常是使用assert方法檢查動作和輸入的響應,一般是基於TestCase類擴充。
  • Test Suite:多個測試的集合。
  • Test Runner:測試執行。
  • Test        Report:測試報告。

測試通常由3A組成:

  • Arrange:預置條件、相關配置和依賴等。
  • Act:實際功能。
  • Assert:斷言。

其他框架有Pytest和Nose等。

 

TestCase類

測試方法以test_開頭

執行結果:

 

基於類的setUp()和tearDown()方法

上面每個用例都會初始化和清理一次,有時這不一定是必要的。@classmethod支援在一個類中只進行一次初始化和清理。

 

斷言

斷言有3種型別:相等、邏輯比較、異常。如果斷言不通過,當前測試用例會停止,並報錯。詳細的斷言參見unittest

另外fail()可以無條件讓用例失敗。

 

測試用例集(Test suites)

通過TestSuite, TestLoader和TestRunner可以有效地組織測試用例集。

先新增檔案homepagetests.py,演示上面部分斷言。

再組合起來,見smoketests.py:

執行結果:

 

生成HTML測試報告

外掛 HTMLTestRunner可以幫助生成HTML報告。見 smoketests_with_html_report.py:

 

web通常包含了Hyper Text Markup Language (HTML)、Cascading Style Sheets (CSS)和JavaScript。本節主要內容如下:

  • 瞭解更多Selenium webDriver查詢元素的知識
  • 使用各種瀏覽器提供的開發工具找到和定位元素
  • 多種發現元素的方法:ID、Name、類屬性值、XPath、CSS選擇器
  • Selenium webDriver中的各種find_element_by方法。

一般的瀏覽器都有檢視原始碼的功能。

 

元素查詢

 

使用開發工具發現定位器

Firefox的外掛Firebug是個好幫手,可以F12或者右鍵點選元素選擇“Inspect Element with Firebug”開啟。Firefox的搜素框還可以對XPath或CSS進行查詢。

Chrome中可以F12或者右鍵點選元素選擇“Inspect Element”的方式檢視程式碼。查詢功能也和Firefox類似。Internet Explorer也有類似功能,不再贅述。

 

元素查詢

find_element_by*系列方法在找到元素的時候返回WebElement例項,否則產生NoSuchElementException異常。另外find_elements_by*系列方法可以一次返回多個元素。

driver.find_element_by_css_selector(‘#search’)

Method Description Argument Example
find_element_by_id(id) This        method        finds        an        element by        the        ID attribute value id:        The        ID        of        the        element        to        be found driver.find_element_by_id(‘search’)
find_element_by_name(name) This method finds an element by        the        name attribute value name: The name of the element to be        found driver.find_element_by_name(‘q’)
find_element_by_class_name(name) This        method        finds an element by        the        class attribute        value name:        The        class name of the element to be        found driver.find_element_by_class_name(‘input-text’)
find_element_by_tag_name(name) This method finds        an element by        its        tag name name: The tag name of the element        to        be        found driver.find_element_by_tag_name(‘input’)
find_element_by_xpath(xpath) This        method        finds        an        element using        XPath xpath:        The        xpath        of        the        element to        be        found driver.find_element_by_xpath(‘form[0]/div[0]/input[0]’)
find_element_by_css_selector(css_selector) This        method        finds        an        element by the CSS selector css_selector: The CSS selector of the element        to be found
find_element_by_link_text(link_text) This        method        finds        an        element by        the        link        text link_text:        The        text        of        the element        to        be        found driver.find_element_by_link_text(‘Log        In’)
find_element_by_partial_link_text(link_text) This        method        finds        an        element by        a       partial        match        of        its        link text link_text:        The        text to        match part        of        the        text        of        the        element driver.find_element_by_partial_link_text(‘Log’)

通過id、name、類屬性是最建議,也是最快速的查詢方法,尤其是id和name。其次使用tag和連結文字,萬不得已才使用xpath和css。

XPath即為XML路徑語言(XML Path Language),它是一種用來確定XML文件中某部分位置的語言。參考:XPath維基百科介紹 以及 w3schools的Xpath介紹zvon的XPath 1.0介紹。參考書籍:Selenium Testing Tools        Cookbook。注意XPath的速度會比CSS還慢,不過支援向前向後定義和相對路徑。

層疊樣式表(英語:Cascading Style Sheets,簡寫CSS),又稱串樣式列表、層次結構式樣式表檔案,一種用來為結構化文件(如HTML文件或XML應用)新增樣式(字型、間距和顏色等)的計算機語言。參考CSS維基百科介紹w3schools之CSS介紹

 

例項

執行結果:

 

元素互動

本節主要內容如下:

  • 瞭解更多關於WebDriver和WebElement類的知識
  • 使用webdriver和WebElement類方法和屬性實現測試與應用互動
  • 使用Select類自動化下拉選單和列表的操作
  • 自動化的JavaScript彈窗和瀏覽器操作。

 

HTML表單的元素

 

webDriver類

webDriver類主要用於和瀏覽器互動,完整的屬性和方法參見:selenium.webdriver.remote.webelement

屬性列表:

Property/attribute Description Example
current_url This gets the        URL        of the current page        displayed in the browser driver.current_url
current_window_handle This gets the handle of        the        current        window driver.current_window_handle
name This        gets the name of the underlying        browser        for        this instance driver.name
orientation This gets        the        current        orientation        of the device driver.orientation
page_source This gets        the        source of the current page driver.page_source
title This gets the title        of the current page driver.title
window_handles This gets the        handles        of all windows within the current session driver.window_handles

方法列表:

Method Description Argument Example
back() This goes one step        backward in the        browser        history        in the        current session. driver.back()
close() This closes the current browser window. driver.close()
forward() This goes one step forward in the browser history in the current session. driver.forward()
get(url) This        navigates and loads        a web page in the current browser session. url is the address of the website or web page to        navigate driver.get(“http://www.google.com”)
maximize_window() This maximizes the current browser window. driver.maximize_window()
quit() This quits        the driver and closes all the associated windows. driver.quit()
refresh() This refreshes the current page        displayed in the browser. driver.refresh()
switch_to.active_element() This returns the element with focus or        the        body if        nothing        else has focus. driver.switch_to_active_element()
Switch.to_alert() This switches the focus        to an alert        on        the        page. driver.switch_to_alert()
switch_to.default_content() This switches        the        focus to the default frame. driver.switch_to_default_content()
switch_to.frame(frame_reference) This switches the focus to the specified        frame, by index, name, or web element. This        method also        works on IFRAMES. frame_reference: This is the name of the window to switch        to,        an integer representing        the        index, or a        web        element that is        a frame        to switch to driver.switch_to_frame(‘frame_name’)
switch_to.window(window_name) This switches focus        to the specified window. window_name is the name or window handle of        the window to switch to. driver.switch_to_window(‘main’)
implicitly_wait(time_to_wait) This sets a        sticky timeout to implicitly wait for an element to        be found, or a command to complete.        This method        only needs to be called        one        time        per        session. To         set        the        timeout        for        calls to execute_async_script,        see        set_script_timeout. time_to_wait is        the        amount of time to wait(in seconds).
set_page_load_timeout(time_to_wait) This        sets the amount        of time to        wait for a page        load to        complete. time_to_wait is the amount of time to wait(in seconds) driver.set_page_load_timeout(30)
set_script_timeout(time_to_wait) This sets the amount of time that the script        should        wait during       an execute_async_script        call before        throwing an error. time_to_wait is the amount of time to wait(in seconds) driver.set_script_timeout(30)

 

WebElement類

WebElement類主要用於和元素互動,完整的屬性和方法參見:elenium.webdriver.remote.webelement

屬性列表:

Property/attribute Description Example
size This        gets the size of the element element.size
tag_name This        gets this element’ s HTML tag name element.tag_name
text This        gets the text of the element element.text

方法列表:

Method Description Argument Example
clear() This clears the content of the textbox or text area element. element.clear()
click() This clicks the element. element.click()
get_attribute(name) This gets the        attribute value        from the element. name is the name of the attribute. element.get_attribute(“value”) Or element.get_attribute(“maxlength”)
is_displayed() This checks whether the element is        visible        to the user. element.is_displayed()
is_enabled() This        checks        whether        the element is enabled. element.is_enabled()
is_selected() This checks        whether       the element is selected. This method is        used to check the selection of        a radio        button or checkbox. element.is_selected()
send_keys(*value) This simulates typing into the element. Value is a string for typing or setting        form fields. element.send_keys(“foo”)
submit() This        submits        a form.        If you call        this method        on an element, it will submit the parent form. element.submit()
value_of_css_property(property_name) This        gets the value of a        CSS        property. property_name is the name of the CSS property. element.value_of_css_property(“backgroundcolor”)

 

處理form、textbox、checkbox和radio

下面的homepagetests建立一個使用者,演示了form、textbox、checkbox和radio等操作。

register_new_user.py

執行結果:

 

處理dropdown和list

屬性列表:

Property/attribute Description Example
all_selected_options This        gets a list        of all the selected        options        belonging to the dropdown or list select_element.all_selected_options
first_selected_option This gets the first        selected/currently selected        option from        the        dropdown or        list select_element.first_selected_option
options This gets        a list of all options from the dropdown        or list select_element.options

方法列表:

Method Description Argument Example
deselect_() This clears all the selected entries from        a multiselect dropdown or list select_element.deselect_()
deselect_by_index(index) This        deselects the option at        the        given index        from the dropdown or list index is the index of the option        to        be deselected deselect_element.deselect_by_index(1)
deselect_by_value(value) This deselects all options that have a value matching the argument from the dropdown        or list value is the        value attribute        of the option to be deselected select_element.deselect_by_value(“foo”)
deselect_by_visible_text(text) This deselects all        the options that display text matching the argument from the dropdown or list text is the text value of        the        option to be        deselected select_element.deselect_by_visible_text(“bar”)
select_by_index(index) This selects an option        at the given index from        the        dropdown or list index is the index of the option to        be selected select_element.select_by_index(1)
select_by_value(value) This selects all the options that have a value matching the argument from the dropdown        or list value is        the        value attribute        of the option to be        selected select_element.select_by_value(“foo”)
select_by_visible_text(text) This         selects        all        the        options        that display the text matching the argument        from the dropdown or list text is the text value of the option to be        selected select_element.select_by_visible_text(“bar”)

程式碼檔案:homepagetests.py。

 

處理告警和彈出視窗

完整的參考地址:selenium.webdriver.common.alert

屬性列表:

Property/attribute Description Example
text This        gets text from the alert window alert.text

方法列表:

Method Description Argument Example
accept() This        will accept        the        JavaScript? alert.box that is click on the OK button alert.accept()
dismiss() This will dismiss the JavaScript? alert.box that is click        on the Cancel button alert.dismiss()
send_keys(*value) This simulates typing into the element value is        a string for typing        or setting form        fields alert.send_keys(“foo”)

例項中先加入商品,然後清空商品,此時會有彈出告警。注意此處的程式碼在網速較慢時,彈出視窗可能無法識別,解決方法參見下一章。

 

 

自動化瀏覽器瀏覽

Method Description Argument Example
back() This goes one step        backward in        the        browser        history        in        the        current session. None driver.back()
forward() This goes one step forward in the browser history in the current session. None driver.forward()
refresh() This refreshes the current page        displayed in the browser. None driver.refresh()

例項: navigation_test.py

上面用例,因為google被和諧,通常無法執行,僅供參考。

 

 

同步

webdriver支援顯式和隱式的同步。本節主要內容如下:

  • 顯式和隱式等待
  • 何時使用顯式和隱式的等待
  • 使用預期條件
  • 建立自定義的等待狀態

 

使用隱式等待

隱式等待提供了通用的方法同步測試和步驟。適用於網路響應時間不一致或者使用Ajax呼叫渲染元素的時候。

隱式等待的預設超時時間是0,對整個webdriver生效。這個功能我們在第2章就有使用,現在我們把當時例項的隱式等待時間從30秒改成10秒。

針對具體案例,顯式案例通常隱式案例要好。

explicit_wait_tests.py

 

expected_conditions類

完整的屬性和方法參見:selenium.webdriver.support.expected_conditions

該類的常見方法如下:

Method Description Argument Example
element_to_be_clickable(locator) This will wait for an element to be located and be visible and enabled so that it can be clicked. This method returns the element that is located back to the test. locator: This is a tuple of (by, locator). WebDriverWait?(self.driver, 10).until(expected_conditions.element_to_be_clickable((By.NAME,“is_subscribed”)))
element_to_be_selected(element) This will wait until a specified element is selected. element: This is the WebElement?. subscription = self.driver.find_element_by_name(“is_subscribed”) WebDriverWait?(self.driver, 10).until(expected_conditions.element_to_be_selected(subscription))
invisibility_of_element_located(locator) This will wait for an element that is either invisible or is not present on the DOM. locator: This is a tuple of (by, locator). WebDriverWait?(self.driver, 10).until(expected_conditions.invisibility_of_element_located((By.ID,“loading_banner”)))
presence_of_all_elements_located(locator) This will wait until at least one element for the matching locator is present on the web page. This method returns the list of WebElements? once they are located. locator: This is a tuple of (by, locator). WebDriverWait?(self.driver,10).until(expected_conditions.presence_of_all_elements_located((By.CLASS_NAME,“input-text”)))
presence_of_element_located(locator) This will wait until an element for the matching locator is present on a web page or available on the DOM. This method returns an element once it is located. locator: This is a tuple of (by, locator). WebDriverWait?(self.driver, 10).until(expected_conditions.presence_of_element_located((By.ID,“search”)))
text_to_be_present_in_element(locator, text_) This will wait until an element is located and has the given text. locator: This is a tuple of (by, locator). text: This is the text to be checked. WebDriverWait?(self.driver,10).until(expected_conditions.text_to_be_present_in_element((By.ID,“sele language”),“English”))
title_contains(title) This will wait for the page tile to contain a casesensitive substring.This method returns true if the tile matches, false otherwise。 title: This is the substring of the        title        to check. WebDriverWait?(self.driver, 10).until(expected_conditions.title_contains(“Create New Customer Account”))
title_is(title) This will wait for the page tile to be equal to the expected title. This method returns true if the tile matches, false otherwise. title: This is the title of the page. WebDriverWait?(self.driver, 10).until(expected_conditions.title_is(“Create New Customer Account -Magento Commerce Demo Store”))
visibility_of(element) This will wait until an element is present in DOM, is visible, and its width and height are greater than zero. This method returns the (same) WebElement? once it becomes visible. element: This is the WebElement?. first_name = self.driver.find_element_by_id(“firstname”) WebDriverWait?(self.driver,10).until(expected_conditions.visibility_of(first_name))
visibility_of_element_located(locator) This will wait until an element to be located is present in DOM, is visible, and its width and height are greater than zero. This method returns the WebElement? once it becomes visible. locator: This is a tuple of (by, locator). WebDriverWait?(self.driver,10).until(expected_conditions.visibility_of_element_located((By.ID,“firstname”)))

前一章的彈出視窗處理得不夠好,現在我們修改下:comparetests.py

 

參考資料

相關文章