1. 程式人生 > >Selenium自動化測試Python二:WebDriver基礎

Selenium自動化測試Python二:WebDriver基礎

WebDriver基礎

歡迎閱讀WebDriver基礎講義。本篇講義將會重點介紹Selenium WebDriver的環境搭建和基本使用方法。

WebDriver環境搭建

Selenium WebDriver 又稱為 Selenium2。

Selenium 1 + WebDriver = Selenium 2

WebDriver是主流Web應用自動化測試框架,具有清晰面向物件 API,能以最佳的方式與瀏覽器進行互動。

支援的瀏覽器:

  • Mozilla Firefox
  • Google Chrome
  • Microsoft Internet Explorer
  • Opera
  • Safari
  • Apple iPhone
  • Android browsers

環境搭建步驟

在上一篇中,我們已經確認使用Python來進行WebDriver的編碼和操作。事實上Python+Selenium WebDriver環境的搭建分為兩個部分:

  1. 安裝python
  2. 安裝Selenium

標準的安裝步驟

  1. 選擇Python的版本。

    Python主流的有兩個大的版本,2.7和3.5(請注意,從Python的3.5版本開始,不再支援Windows XP作業系統,Windows XP使用者請安裝3.4版本)。我們的例子將會選用面向未來的3.5版本。

  2. 安裝Python。

    在Python的官網下載最新的安裝包,進行介面安裝。https://www.python.org/

    安裝的時候,推薦選擇“Add exe to path”,將會自動新增Python的程式到環境變數中。然後可以在命令列輸入python -V檢測安裝的Python版本。

    當前的版本安裝中將會預設已經安裝了setuptoolspip這兩個Python的基本工具。如果使用了比較舊的Python版本的話,需要自行安裝這兩個工具。

    • setuptools:Python的基礎工具包,用來構建、安裝解除安裝Python程式
    • pip:Python軟體包的安裝和管理工具。通過pip可以簡單的安裝Python的任意類庫
  3. 安裝Selenium2.0版本。

    在Windows安裝Selenium2.0,有兩種途徑。使用pip命令列或者原始碼安裝。以下兩種方法,使用任何一個均可。推薦pip的方式。

    1. 方法一:pip命令列安裝,執行 | cmd,開啟命令列,-U其實就是--upgrade,升級安裝。

      pip install -U selenium
    2. 方法二:原始碼解壓安裝,前往https://pypi.python.org/pypi/selenium下載最新版的PyPI版本的Selenium,解壓後執行

      python setup.py install

Ubuntu下的環境搭建

在Ubuntu下的Python的直譯器一般情況下已經存在了。我們需要開啟終端,輸入python -V命令進行驗證。如果沒有安裝Python,那麼需要去Python官網上下載指定版本的原始檔,進行原始碼安裝。安裝完了以後並進行環境變數的設定。

安裝Selenium WebDriver的方法與上述在Windows環境下安裝部署的方法一致。依舊推薦使用pip命令列進行安裝。

使用IDE編寫Python

在上述環境搭建好以後,我們便可使用Python來編寫自動化指令碼程式,執行Selenium自動化測試。在此之前,我們依舊需要解決一個問題,那就是IDE的選擇。

IDE,Integrated Development Environment,整合開發環境。一個好的編輯器或者好的IDE將會極大的提高生產力,幫我們做很多事情,使得編碼工作更加簡單,編碼的體驗更加容易。一般情況下,我們有以下幾種工具可以選擇:

  • IDLE:Python自帶的IDE,功能簡單,使用方便
  • Notepad++:一個強大的開源編輯器
  • Vim:Linux系統中最好用的編輯器之一
  • Sublime Text:一個非常輕便好用的現代化的編輯器,推薦。
  • PyCharm:JetBrains公司提供的現代化的跨平臺的Python IDE。

使用Sublime Text 3搭建Python環境

  1. **通過快捷鍵Ctrl + 或者View > Show Console開啟控制檯,輸入以下程式碼並回車

    import urllib.request,os; pf = 'Package Control.sublime-package'; 
    ipp = sublime.installed_packages_path(); 
    urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); 
    open(os.path.join(ipp, pf), 'wb').write(urllib.request.urlopen( 'http://sublime.wbond.net/' + pf.replace(' ','%20')).read())
  2. 安裝完以後,重啟Sublime Text 3

  3. 如果在Perferences->package settings中看到package control這一項,則安裝成功

  4. 按下Ctrl+Shift+P調出命令面板

  5. 輸入install package選項並回車

  6. 輸入i,匹配到以後,按回車,安裝。Anaconda是一個終極的Python外掛。安裝完了以後便可用Sublime Text 3編寫Python程式碼,並且使用Ctrl + B來編譯執行。

一般來說,一個好的IDE提供一下功能,使你的編碼開發工作變得更有效率:

  1. 一個圖形化的智慧程式碼提示和補全功能
  2. 可以輕鬆檢視方法和類
  3. 語法高亮
  4. 提供單元測試和除錯的工具
  5. 原始碼版本管理工具的支援

我們可以嘗試用上述的編輯器或者IDE來進行Python程式碼編寫工作。

開始使用WebDriver

接下來我們嘗試幾個簡單的例子來體會一下Selenium WebDriver的使用。

示例1

## 引入WebDriver的包
from selenium import webdriver

## 建立瀏覽器物件
browser = webdriver.Firefox()

## 開啟百度網站
browser.get('https://www.baidu.com/')

示例2

## 引入WebDriver包
from selenium import webdriver

## 引入WebDriver Keys包
from selenium.webdriver.common.keys import Keys

## 建立瀏覽器物件
browser = webdriver.Firefox()

## 導航到百度主頁
browser.get('https://www.baidu.com')

## 檢查標題是否為‘百度一下,你就知道’
assert '百度一下,你就知道' in browser.title

## 找到名字為wd的元素,賦值給elem
elem = browser.find_element_by_name('wd')  # 找到搜尋框
elem.send_keys('seleniumhq' + Keys.RETURN)  # 搜尋seleniumhq

## 關閉瀏覽器
browser.quit()

Selenium 3.0.1 出現的問題以及解決

3.0.1 更新以後,需要做兩個操作:

  1. Geckodriver executable needs to be in PATH。Geckodirver的下載地址:https://github.com/mozilla/geckodriver/releases
    報錯內容:
    WebDriverException:Message:'geckodriver'executable needs to be in Path
    geckodriver是一原生態的第三方瀏覽器,對於selenium3.x版本都會使用geckodriver來驅動firefox,所以需要下載geckodriver.exe。放置在Path 環境變數可以訪問到的地方。例如 C:\python34
  2. 需要將火狐的安裝路徑放到path,然後重啟(必須重啟電腦)
    報錯內容:
    selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executable needs to be in PATH.
    參考地址:http://stackoverflow.com/questions/40208051/selenium-using-python-geckodriver-executable-needs-to-be-in-path/40208762

XAMPP的安裝部署和環境搭建

XAMPP的安裝,在Windows作業系統中比較簡單,可以直接執行安裝檔案,預設全部下一步,即可完成軟體的安裝。

請注意:Windows XP系統只能可以 XAMPP 1.8.2版本;Windows 7以及以上的系統可以安裝最新版的XAMPP。XAMPP不分32位和64位作業系統。

XAMPP的部署

XAMPP = OS + Apache + MySQL + PHP + Perl

我們一般部署的網站,符合XAMPP環境的話,只需要啟動Apache和MySQL兩個應用。

部署步驟

  1. 啟動Apache

  2. 啟動MySQL

  3. 解壓網站原始檔,例如解壓然之:ranzhi.2.5.zip,請把壓縮包裡面的ranzhi這個資料夾解壓出來;禪道也類似,需要把壓縮包中的zentaopms資料夾解壓出來

  4. 部署原始檔,請將解壓以後的原始檔放到xampp\htdocs資料夾中

  5. 通過瀏覽器訪問部署好的網站原始檔,進行嚮導安裝。http://localhost/ranzhi/www

    PS:這裡我們主要支援的是PHP+MySQL開發的網站部署。

XAMPP的問題解決

  • 無法啟動Apache:請認真檢視日誌,判斷80和443埠被什麼樣的程式佔用,需要關閉對應程式,或者修改Apache的埠。

    1. IIS:控制面板 | 管理工具 | Internet資訊服務 | 預設網站 | 關閉
    2. VisualSVN Server: 控制面板 | 管理工具 | VisualSVN Server | 關閉
    3. VMware Workstation: 開始 | VMware Workstation | 編輯 | 首選項 | 共享虛擬機器 | 禁用共享
    4. HP LoadRunner: 右側工作列 | 右鍵 | 關閉
    5. 修改XAMPP Apache 埠:Config | httpd.conf修改Linsten 80 | Httpd-ssl.conf修改 Listen 443
  • 無法啟動MySQL:請認真檢視錯誤日誌,找到已經啟動的MySQL的程式程序,殺掉該程序。

使用unittest編寫測試指令碼

通過上面的例子,我們可以簡單的寫出Selenium WebDriver的指令碼,但是對於測試工作來說,上述的指令碼還遠遠不夠。因為上述的指令碼沒有“檢查”。

接下來我們將會使用Python語言的unittest框架展開“檢查”。

unittest基礎

unittest框架的原本的名字是PyUnit。是從JUnit這樣一個被廣泛使用的Java應用開發的單元測試框架創造而來。類似的框架還有NUnit(.Net開發的單元測試框架)等。

我們可以使用unittest框架為任意Python專案編寫可理解的單元測試集合。現在這個unittest已經作為Python的標準庫模組釋出。我們安裝完Python以後,便可以直接使用unittest。

unittest框架提供了編寫test casestest suitestest fixtures的基本功能。我們首先關注 Test cases的編寫與執行。

使用unittest需要以下簡單的三步:

  • 引入unittest模組
  • 繼承unittest.TestCase基類
  • 測試方法以test開頭

unittest示例

## 引入unittest模組
import unittest

## 定義測試類,名字為DemoTests
## 該類必須繼承unittest.TestCase基類
class DemoTests(unittest.TestCase):

    ## 使用'@'修飾符,註明該方法是類的方法
    ## setUpClass方法是在執行測試之前需要先呼叫的方法
    ## 是開始測試前的初始化工作
    @classmethod
    def setUpClass(cls):
        pass

    ## 測試一(務必以test開頭)
    def test_01(self):
        pass

    ## 測試三(務必以test開頭)
    def test_02(self):
        pass

    ## 測試三(務必以test開頭)
    def test_03(self):
        pass

    ## tearDownClass方法是執行完所有測試後呼叫的方法
    ## 是測試結束後的清除工作
    @classmethod
    def tearDownClass(cls):
        pass

# 執行測試主函式
if __name__ == '__main__':
    ## 執行main全域性方法,將會執行上述所有以test開頭的測試方法
    unittest.main(verbosity=2)

Python知識的補充:

  1. Python檔案的字尾名是.py
  2. .py檔案可以用來直接執行。也可以被用來作為模組匯入。在cmd命令列中執行的命令為python demo.py
  3. 在Python中匯入模組(模組)一般使用的是import

使用unittest框架編寫Selenium WebDriver測試

接下來我們檢視一個完整的Selenium WebDriver自動化測試例項

例項

import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

class SearchTests(unittest.TestCase):

    def setUp(self):
        # 建立一個新的瀏覽器物件
        self.driver = webdriver.Firefox()
        self.driver.implicitly_wait(30)
        self.driver.maximize_window()
        # 導航到京東主頁
        self.driver.get("https://www.jd.com/")

    def test_search_by_category(self):
        # 獲取到搜尋框
        self.search_field = self.driver.find_element_by_id("key")
        self.search_field.clear()
        # 輸入iphone 6s plus並按下回車進行搜尋
        self.search_field.send_keys("iphone 6s plus"  + Keys.RETURN)
        # 獲取所有的查詢結果
        products = self.driver.find_elements_by_css_selector("li[class='gl-item']")
        # 斷言:檢查查詢出來的個數是否為24個
        self.assertEqual(24, len(products))

    def tearDown(self):
        # 關閉瀏覽器物件
        self.driver.quit()

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

理解unittest框架提供的各種斷言方法

方法 Method 檢查條件
assertEqual(a, b [, msg]) a == b,msg可選,用來解釋失敗的原因
assertNotEqual(a, b [, msg] a != b,msg可選,用來解釋失敗的原因
assertTrue(x [, msg]) x 是真,msg可選,用來解釋失敗的原因
assertFalse(x [, msg]) x 是假,msg可選,用來解釋失敗的原因
assertIsNot(a, b [, msg]) a 不是 b,msg可選,用來解釋失敗的原因

 

 

 

 

WebDriver API 基本操作

這裡我們將會開始WebDriver API的基本操作,從元素定位以及瀏覽器的基本操作開始。

定位符

元素的定位和操作是自動化測試的核心部分,其操作是建立在定位的基礎上的。因此我們首選要開始定位元素。

在html裡面,元素具有各種各樣的屬性。我們可以通過這樣唯一區別其他元素的屬性來定位到這個元素。WebDriver提供了一系列的元素定位方法。常見的有以下幾種:

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

查詢簡單元素

我們從簡單的一個元素開始定位。最基本的方法是idname。大多數元素有這兩個屬性,在對控制元件的idname命名是一般也會使其有意義,而取不同的名字。

例如我們看下面這段html

<input id="search" type="text" name="q" value="" class="input-text" maxlength="128" />

我們可以使用對應的方法來定位這個input

find_element_by_id('search')
find_element_by_name('q')
find_element_by_class_name('input-text')

這裡我們開始用最簡單的方式來嘗試定位

檢視下面一個例子

self.driver.get('http://pro.demo.zentao.net')
# 用name定位使用者文字輸入框
self.account_field = self.driver.find_element_by_name('account')
# 用name定位密碼文字輸入框
self.password_field = self.driver.find_element_by_name('password')
self.account_field.clear()
self.password_field.clear()
self.driver.implicitly_wait(30)

# 輸入使用者名稱demo
self.account_field.send_keys('demo')
# 輸入密碼123456
self.password_field.send_keys('123456')
self.driver.find_element_by_id('submit').click()
self.driver.implicitly_wait(30)

companyname = self.driver.find_element_by_id('companyname')
self.assertEqual('demo專案管理系統', companyname.text)

示例2

self.driver.find_element_by_id('menuproduct').click()
self.driver.implicitly_wait(30)

self.driver.find_element_by_id('menuproject').click()
self.driver.implicitly_wait(30)

self.driver.find_element_by_id('menuqa').click()
self.driver.implicitly_wait(30)

self.driver.find_element_by_id('menudoc').click()
self.driver.implicitly_wait(30)

self.driver.find_element_by_id('menureport').click()
self.driver.implicitly_wait(30)

self.driver.find_element_by_id('menucompany').click()
self.driver.implicitly_wait(30)

self.driver.find_element_by_link_text('退出').click()
self.driver.implicitly_wait(30)

此外XPath定位和CSS Selector定位,和定位一組元素這樣的內容案例,將在後續的講義繼續探討和講解。

控制瀏覽器

瀏覽器的控制也是自動化測試的一個基本組成部分,我們可以將瀏覽器最大化,設定瀏覽器的高度和寬度以及對瀏覽器進行導航操作等。

## 瀏覽器最大化
driver.maximize_window()

## 設定瀏覽器的高度為800畫素,寬度為480畫素
driver.set_window_size(480, 800)

## 瀏覽器後退
driver.back()

## 瀏覽器前進
driver.forward()

這裡我們做一個綜合性的練習例項

# coding=utf-8
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
# import sys
# reload(sys)
# sys.setdefaultencoding('utf8')


class WebDriverTests(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        # create a new Firefox session
        cls.driver = webdriver.Firefox()
        cls.driver.get('about:blank')
        cls.driver.implicitly_wait(30)
        print(" -- set up finished -- ")
        print()

    def test_01_navigate(self):
        pass
        url_baidu = 'https://www.baidu.com/'
        url_zentao = 'http://pro.demo.zentao.net/user-login-Lw==.html'
        # 導航到百度
        self.driver.get(url_baidu)
        self.driver.maximize_window()
        self.driver.implicitly_wait(30)

        # 導航到禪道
        self.driver.get(url_zentao)
        self.driver.maximize_window()
        self.driver.implicitly_wait(30)

        # 後退
        self.driver.back()
        self.assertEqual(url_baidu, self.driver.current_url)
        self.driver.implicitly_wait(30)

        # 前進
        self.driver.forward()
        self.assertEqual(url_zentao, self.driver.current_url)
        self.driver.implicitly_wait(30)

        print("-- test 01 finished -- ")
        print()

    def test_02_element_interaction(self):
        self.driver.get('http://pro.demo.zentao.net')
        ## 找到使用者名稱和密碼的輸入框
        self.account_field = self.driver.find_element_by_name('account')
        self.password_field = self.driver.find_element_by_name('password')
        ## 清除當前的輸入
        self.account_field.clear()
        self.password_field.clear()
        self.driver.implicitly_wait(30)

        ## 輸入使用者名稱和密碼,進行登入
        self.account_field.send_keys('demo')
        self.password_field.send_keys('123456')
        self.driver.find_element_by_id('submit').click()
        self.driver.implicitly_wait(30)

        companyname = self.driver.find_element_by_id('companyname')
        self.assertEqual('demo專案管理系統', companyname.text)
        print(companyname.get_attribute('type'))
        print()
        self.driver.implicitly_wait(30)

        print('-- test 02 finished -- ')
        print()

    def test_03_element_interation2(self):
        ## 這裡執行了一段JavaScript程式碼
        js = 'selectTheme("green")'
        self.driver.execute_script(js)
        self.driver.implicitly_wait(30)

        js = 'selectTheme("red")'
        self.driver.execute_script(js)
        self.driver.implicitly_wait(30)

        js = 'selectTheme("lightblue")'
        self.driver.execute_script(js)
        self.driver.implicitly_wait(30)

        js = 'selectTheme("blackberry")'
        self.driver.execute_script(js)
        self.driver.implicitly_wait(30)

        self.driver.find_element_by_id('menuproduct').click()
        self.driver.implicitly_wait(30)

        self.driver.find_element_by_id('menuproject').click()
        self.driver.implicitly_wait(30)

        self.driver.find_element_by_id('menuqa').click()
        self.driver.implicitly_wait(30)

        self.driver.find_element_by_id('menudoc').click()
        self.driver.implicitly_wait(30)

        self.driver.find_element_by_id('menureport').click()
        self.driver.implicitly_wait(30)

        self.driver.find_element_by_id('menucompany').click()
        self.driver.implicitly_wait(30)

        self.driver.find_element_by_link_text('退出').click()
        self.driver.implicitly_wait(30)

        WebDriverWait(self.driver, 10).until(
            expected_conditions.element_to_be_clickable((By.ID, "submit")))

        self.driver.implicitly_wait(30)

        print('-- test 03 finished -- ')
        print()

    def test_04_cookies(self):

        self.driver.add_cookie(
            {'name': 'key-neeeeew', 'value': 'value-neeeewwwww'})

        # 遍歷cookies 中的name 和value 資訊列印,當然還有上面新增的資訊
        for cookie in self.driver.get_cookies():
            print("%s -> %s" % (cookie['name'], cookie['value']))
            print()

        self.driver.delete_all_cookies()

        cookies = self.driver.get_cookies()
        print(cookies)
        print()

        print('-- test 04 finished -- ')
        print()

    @classmethod
    def tearDownClass(cls):
        # close the browser window
        cls.driver.quit()
        pass
        print('-- tear down finished -- ')
        print()

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

轉載來源:http://www.jianshu.com/p/3ce95cbc65be