Day 4 測試腳本講義
經(jīng)過了前面三天的課程內(nèi)容母赵,我們應該初步基本的掌握了手工測試。接下來我們來面對另一個高度的挑戰(zhàn)悠砚,就是自動化測試。自動化測試是近期的一個熱門概念堂飞,在一線城市的軟件測試招聘中灌旧,經(jīng)常會出現(xiàn)自動化測試的要求,而且在面試的過程中绰筛,企業(yè)和面試官也是會涉及到自動化測試相關的內(nèi)容枢泰。接下來我們用兩張圖來說明自動化測試的內(nèi)容。
首先我們來看看手工測試铝噩。
再來看自動化測試衡蚂。
本次講義,主要解決的問題如下:
- 自動化測試的本質(zhì)是什么骏庸?
- Web UI 自動化測試的對象怎么理解毛甲?
- Selenium 是一個什么樣的工具?
注意:本講義探討的自動化測試是 Web UI 自動化測試具被。
0 主要內(nèi)容
- 1 T5_自動化測試分析
- 2 T6_自動化測試環(huán)境準備
- 3 T7_自動化測試腳本編寫
1 T5_自動化測試分析
1.1 自動化測試的出發(fā)點
還記得上一屆內(nèi)容中對“回歸測試”的描述么玻募?在敏捷開發(fā)的實踐中,每一次新版本的發(fā)布一姿,都會要求對過往版本已經(jīng)測試過的功能進行回歸測試补箍。一般會挑選重要的測試用例,加入到回歸測試的用例集合中啸蜜,然后在每一次的新版本中坑雅,重新執(zhí)行。
這樣的要求衬横,如果單純依靠手工測試裹粤,那么工作量會相當大,而且也會增加測試人員的疲倦情緒,于是遥诉,自動化測試就閃亮登場了拇泣。目前自動化測試其實主要解決的就是回歸測試的問題,而不能夠做到完全替代手工測試矮锈。
1.2 自動化測試的對象分析
本次講義的內(nèi)容霉翔,我們重點分析的就是 Web UI(瀏覽器界面)的自動化測試,并且我們已知“自動化測試就是人類讓電腦替自己做測試執(zhí)行”的過程苞笨,那么我們首先要分析一下债朵,瀏覽器界面的執(zhí)行因素。
如果你還不明白講義在這里指代的內(nèi)容是什么瀑凝,那么我們用瀏覽器自帶的開發(fā)者工具查看瀏覽器渲染的 html 源碼序芦。
瀏覽器渲染的內(nèi)容是由一個個tag
組成的。我們平時通過手工測試點擊瀏覽器粤咪,實際上就是選擇了瀏覽器渲染出來的 html 標簽谚中,并且對其進行操作的。
1.3 自動化測試的工具要求
自動化測試就需要做到下面的事情寥枝,即可宪塔。
- 讓電腦明白去找哪個瀏覽器的哪個標簽
- 找到標簽后做什么樣具體的操作
- 操作以后,檢查操作是否成功
2 T6_自動化測試環(huán)境準備
2.1 選擇并安裝編程語言
從上面一節(jié)囊拜,我們知道蝌麸,讓電腦替我們做事情,并且要讓電腦給出檢查結(jié)果艾疟,這是需要通過編程語言來實現(xiàn)的。因為“電腦不懂人話”……
現(xiàn)在主流的可以選擇的編程語言進行測試敢辩,主要集中在 Python 和 Java 上蔽莱。部分工具也會選擇 C#。我們這里選擇 Python戚长。
Python 語言的選擇盗冷,便捷
- 測試人員的編程能力普遍不是很強,而Python作為一種腳本語言同廉,不僅功能強大仪糖,而且語法優(yōu)美,支持多種自動化測試工具迫肖,而且學習上手比較容易锅劝。
- Python的社區(qū)發(fā)展比較好,有著非常多的文檔和支持庫蟆湖,另外Python也可以在Web開發(fā)故爵、數(shù)據(jù)處理、科學計算等縱多領域有著非常好的應用前景隅津。
- 對于有一定編程基礎的人員诬垂,使用Python作為自動化測試的語言可以非常順暢的轉(zhuǎn)換劲室,幾乎沒有學習成本。同時Python是標準的面向?qū)ο蟮木幊陶Z言结窘,對于C#很洋、Java等面向?qū)ο蟮恼Z言有著非常好的示例作用,通過Python的示例可以非常輕松的觸類旁通隧枫,使用其他語言進行Selenium2.0的WebDriver的使用喉磁。
- 讀音:
/'pa?θ?n/
- Python的創(chuàng)始人為Guido Van Rossum。1989年圣誕節(jié)期間悠垛,在阿姆斯特丹线定,Guido為了打發(fā)圣誕節(jié)的無趣,決心開發(fā)一個新的腳本解釋程序确买,做為ABC 語言的一種繼承斤讥。之所以選中Python(大蟒蛇的意思)作為程序的名字,是因為他是一個叫Monty Python的喜劇團體的愛好者湾趾。
- Python 語言除了在自動化測試領域有出色的表現(xiàn)外芭商,在系統(tǒng)編程,網(wǎng)絡編程搀缠,web 開發(fā)铛楣,GUI開發(fā),科學計算艺普,游戲開發(fā)等多個領域應用非常廣泛簸州,而且具有非常良好的社區(qū)支持。也就是說學習和掌握python 編程歧譬,其實是為你打開了一道更廣闊的大門岸浑。
安裝 Python 語言
Python的官方網(wǎng)站:http://www.python.org
Python 目前并行了兩套版本,2.x 和 3.x瑰步。如果你之前沒有 Python 的使用經(jīng)驗矢洲,建議使用 Python 3.x 版本。兩套版本互相不兼容缩焦,并且 Python 從 3.5(含)開始读虏,不再支持 Windows XP 系統(tǒng),請注意袁滥。
-
選擇安裝目錄
- 3.4或者3.4以下的版本盖桥,都是
C:\python34
- 3.5以上的目錄,默認裝個人文件夾题翻,建議用類似上面的目錄葱轩,比如
C:\python35
- 3.4或者3.4以下的版本盖桥,都是
-
勾選添加環(huán)境變量
勾選
Add Python.exe to PATH
安裝過程中不要關閉彈出來的命令行窗口
-
關于 Python 的安裝,也可以選擇一些第三方的Python 安裝包,典型的有
Anaconda3
靴拱,這樣的包有豐富的第三方庫垃喊,在使用 Python 的過程中會更加方便。Anaconda 的官網(wǎng):https://www.continuum.io/anaconda-overview
2.2 設置測試工具與驅(qū)動
Selenium 是開源的自動化測試工具袜炕,它主要是用于Web 應用程序的自動化測試本谜,不只局限于此,同時支持所有基于web 的管理任務自動化偎窘。
-
Selenium
官網(wǎng)的介紹Selenium is a suite of tools to automate web browsers across many platforms.
- runs in many browsers and operating systems
- can be controlled by many programming languages and testing frameworks.
- Selenium 官網(wǎng):http://seleniumhq.org/
- Selenium Github 主頁:https://github.com/SeleniumHQ/selenium
Selenium 是用于測試 Web 應用程序用戶界面 (UI) 的常用框架乌助。它是一款用于運行端到端功能測試的超強工具。您可以使用多個編程語言編寫測試陌知,并且 Selenium 能夠在一個或多個瀏覽器中執(zhí)行這些測試他托。
Selenium 誕生于 2004 年,當在
ThoughtWorks
工作的 Jason Huggins 在測試一個內(nèi)部應用時仆葡。作為一個聰明的家伙赏参,他意識到相對于每次改動都需要手工進行測試,他的時間應該用得更有價值沿盅。他開發(fā)了一個可以驅(qū)動頁面進行交互的 Javascript 庫把篓,能讓多瀏覽器自動返回測試結(jié)果。那個庫最終變成了 Selenium 的核心腰涧,它是 Selenium RC(遠程控制)和 Selenium IDE 所有功能的基礎韧掩。Selenium RC 是開拓性的,因為沒有其他產(chǎn)品能讓你使用自己喜歡的語言來控制瀏覽器窖铡。這就是 Selenium 1疗锐。在 2006 年,一名 Google 的工程師费彼, Simon Stewart 開始基于這個項目進行開發(fā)滑臊,這個項目被命名為 WebDriver。此時敌买,Google 早已是 Selenium 的重度用戶,但是測試工程師們不得不繞過它的限制進行工具阶界。Simon 需要一款能通過瀏覽器和操作系統(tǒng)的本地方法直接和瀏覽器進行通話的測試工具虹钮,來解決Javascript 環(huán)境沙箱的問題。WebDriver 項目的目標就是要解決 Selenium 的痛點膘融。
到了 2008 年芙粱,Selenium 和 WebDriver 兩個項目合并。Selenium 有著豐富的社區(qū)和商業(yè)支持氧映,但 WebDriver 顯然代表著未來的趨勢春畔。兩者的合并為所有用戶提供了一組通用功能,并且借鑒了一些測試自動化領域最閃光的思想。這就是 Selenium 2律姨。
2016 年振峻,Selenium 3 誕生。移除了不再使用的 Selenium 1 中的 Selenium RC择份,并且官方重寫了所有的瀏覽器驅(qū)動扣孟。
-
安裝 Selenium 工具包
由于 安裝好的 Python 默認有
pip
Python 包管理工具,可以通過pip
非常方便的安裝 Selenium荣赶。啟動命令行工具:Win+R | 輸入 cmd | 回車
-
輸入命令:
pip install selenium
該命令的執(zhí)行需要有互聯(lián)網(wǎng)聯(lián)網(wǎng)環(huán)境凤价。此外該命令有以下幾種選項可以使用
-
安裝指定的版本,例如安裝指定的 Selenium 3.4.3
pip install selenium==3.4.3
?
-
安裝最新版的 Selenium
pip install -U selenium # -U 也可以用 --upgrade pip install --upgrade selenium
?
-
卸載安裝當前的 Selenium
pip uninstall selenium
-
-
當然拔创,如果您的機器處于非接入互聯(lián)網(wǎng)的環(huán)境利诺,您可以事先下載 Selenium 的 Python 安裝包,再進行手動安裝剩燥。
上述地址會下載最新版的 Selenium慢逾,目前最先版的是 3.4.3,您也可以根據(jù)以下路徑下載指定的 3.4.3
Selenium 3.4.3 下載地址:https://pypi.python.org/pypi/selenium/3.4.3#downloads
下載后躏吊,解壓該壓縮包
-
然后用命令行進入該壓縮包的根目錄氛改,輸入命令進行安裝
python setup.py install
?
-
-
配置 瀏覽器 和 驅(qū)動
Selenium 2 可以默認支持Firefox 46.0或者更低版本,對于其他瀏覽器需要額外安裝驅(qū)動比伏。
-
Selenium 3 對于所有的瀏覽器都需要安裝驅(qū)動胜卤,本文以 Chrome 和 Firefox、IE為例設置瀏覽器和驅(qū)動赁项。
ChromeDriver下載地址:http://chromedriver.storage.googleapis.com/index.html
-
ChromeDriver 與 Chrome 對應關系表:
ChromeDriver版本 支持的Chrome版本 v2.43 v69 v2.42 v68 v2.31 v58-60 v2.30 v58-60 v2.29 v56-58 v2.28 v55-57 v2.27 v54-56 v2.26 v53-55 v2.25 v53-55 v2.24 v52-54 v2.23 v51-53 v2.22 v49-52 v2.21 v46-50 v2.20 v43-48 GeckoDriver下載地址:https://github.com/mozilla/geckodriver/releases
-
GeckoDriver 與 Firefox 的對應關系表:
GeckoDriver版本 支持的Firefox版本 v0.18.0 v56 v0.17.0 v55 v0.16.0 v54葛躏,需要Selenium 3.4或者以上 v0.15.0 v53,需要Selenium 3.3或者以上 IEDriverServer下載地址:http://selenium-release.storage.googleapis.com/index.html
IEDriverServer 的版本需要與 Selenium 保持嚴格一致悠菜。
-
瀏覽器驅(qū)動的配置
- 首先舰攒,將下載好的對應版本的瀏覽器安裝。
- 其次悔醋,在 Python 的根目錄中摩窃,放入瀏覽器驅(qū)動。
- 最好再重啟電腦芬骄,一般情況下不重啟也可以的猾愿。
2.3 使用 IDE 進行腳本編寫
- JetBrains PyCharm 的介紹
PyCharm 是 JetBrains 公司針對Python推出的IDE(Integrated Development Environment,集成開發(fā)環(huán)境)账阻。是目前最好的Python IDE之一蒂秘。目前包含了兩個版本:
- 社區(qū)版,Community Edition
- 專業(yè)版淘太,Professional Edition
- 付費
- 比社區(qū)版主要多了Web開發(fā)框架
我們推薦使用免費的社區(qū)版本姻僧,進行Python腳本的編寫和自動化測試執(zhí)行规丽。
PyCharm可以在官網(wǎng)下載,http://www.jetbrains.com
PyCharm 安裝后撇贺,如果也安裝過 Python 環(huán)境赌莺,可以直接進行操作。否則請在 1.2.3 中安裝好 Python显熏,再使用 PyCharm雄嚣。
-
安裝按照默認的步驟安裝
-
使用方式
-
Create New Project:
創(chuàng)建新的項目,選擇項目創(chuàng)建的位置喘蟆,選擇Python的解釋器
- 設置location缓升,項目的路徑和名稱
- 名稱必須以英文字母開頭
- 名稱不可以有空格
- 位置不可以在
C:\Pytho34
中,應該放到普通的目錄中
- 設置interpreter
- 一個電腦可以裝多個 Python
- 這里選擇一個你需要的 Pythpn
新建Python文件
在創(chuàng)建的文件中編寫第一個Python語句
print("hello Python!")
右鍵該文件蕴轨,選擇
Run hello
港谊,運行該語句,在下面的運行框中會顯示運行結(jié)果C:\Python35\python.exe D:/Git/WeekendSelenium/untitled/hello.py hello python! Process finished with exit code 0
如圖
- 設置location缓升,項目的路徑和名稱
-
Open
打開已經(jīng)存在的項目橙弱,比如別人發(fā)給你的項目歧寺,或者已經(jīng)創(chuàng)建過的項目
-
-
-
安裝后進行設置如下:
-
設置行號的顯示
永久設置主儡。
File
-->Settings
-->Editor
-->Appearance
, 之后勾選Show Line Numbers
竭鞍。?
-
設置字體
選擇 Settings | Editor | Colors & Fonts | Fonts
Save AS 主題
選擇 Source Code Pro(建議選擇,等寬字體)
-
編寫第一個腳本
通過上一節(jié)的環(huán)境安裝成功以后邓夕,我們可以進行第一個對Selenium 的使用蛀缝,就是最簡腳本編寫顷链。腳本如下:
# 聲明一個司機,司機是個Chrome類的對象
driver = webdriver.Chrome()
# 讓司機加載一個網(wǎng)頁
driver.get("http://demo.ranzhi.org")
# 給司機3秒鐘去打開
sleep(3)
# 開始登錄
# 1. 讓司機找用戶名的輸入框
we_account = driver.find_element_by_css_selector('#account')
we_account.clear()
we_account.send_keys("demo")
# 2. 讓司機找密碼的輸入框
we_password = driver.find_element_by_css_selector('#password')
we_password.clear()
we_password.send_keys("demo")
# 3. 讓司機找 登錄按鈕 并 單擊
driver.find_element_by_css_selector('#submit').click()
sleep(3)
實際上一段20行的代碼屈梁,也不能算太少了嗤练。但是這段代碼的使用,確實體現(xiàn)了 Selenium 的最簡單的使用在讶。我們在下面內(nèi)容進行闡述煞抬。
-
關于面向?qū)ο缶幊?/p>
通過前面的介紹,我們知道 Selenium 支持多種語言构哺,并且推薦使用面向?qū)ο蟮姆绞竭M行編程革答。接下來我們將著重介紹如何使用面向?qū)ο蟮姆绞竭M行編程。
我們利用 Python 進行面向?qū)ο缶幊淌锴浚枰紫攘私庖粋€概念:類
-
類
類是任何面向?qū)ο缶幊痰恼Z言的基本組成残拐,描述了使用的基本方法。我們可能在目前旗扑,還不是特別明白類的含義蹦骑,但是我們可以通過類的使用慈省,來進一步了解臀防。
-
類的使用
類眠菇,通過實例化進行使用。比如有一個類:
Driver
袱衷,該類有一個方法:head(road)
那么關于這個類的使用捎废,只需要兩個步驟:
- 實例化該類:
d = Driver()
- 調(diào)用類的方法:
d.head("中山路")
- 實例化該類:
了解上述例子和使用以后,我們來看具體的 Selenium 的使用致燥。
?
-
-
具體的對象的使用
在面向?qū)ο蟮睦砟羁磥淼橇疲魏蔚木幋a,都是由對象而來的嫌蚤,這里也不例外辐益。和之前介紹 WebDriver 時候的描述對應,我們需要用到兩種主要的類脱吱,并將其實例化智政。
- WebDriver 類:主要靠直接實例化該類為對象,然后用其對象直接調(diào)用該類的方法和屬性
- WebElement 類:主要通過 WebDriver 類實例化的對象箱蝠,通過對頁面元素的查找续捂,得到 WebElement 類的對象,然后調(diào)用該類的方法和屬性宦搬。
上述代碼中牙瓢,使用了一個 WebDriver 類 的對象,即第2行间校,聲明了該類的對象矾克,并賦值給變量 driver,接著變量 driver 作為 WebDriver 類的對象撇簿,使用了多個 WebDriver 類的方法聂渊。
注意:Chrome 是 WebDriver 的子類,是 WebDriver 類的一種
- get(url): 第5行四瘫,打開網(wǎng)址
- find_element_by_css_selector(selector): 第12汉嗽、17、22行都使用了該方法找蜜,同時通過對該方法的調(diào)用饼暑,分別各產(chǎn)生了一個 WebElement類的對象,
we_account
洗做,we_password
和最后一個匿名的對象弓叛,并通過產(chǎn)生的三個對象,調(diào)用 WebElement 類的方法- clear():清理頁面元素中的文字
- send_keys(text):給頁面元素中诚纸,輸入新的文字
- click():鼠標左鍵點擊頁面元素
正是通過這樣的面向?qū)ο蟮姆绞阶辏a(chǎn)生 Web司機(WebDriver類的對象),并且通過 Web司機不懈的努力畦徘,尋找到各種 Web元素(WebElement類的對象)進行操作毕籽,這樣便實現(xiàn)了 Selenium WebDriver 作為一款出色的瀏覽器測試工具抬闯,進行瀏覽器UI界面的自動化測試的代碼編寫和用例執(zhí)行。
3 T7_自動化測試腳本編寫
3.1 WebDriver 類的使用
通過上述最簡腳本的使用关筒,我們可以來進一步了解 Selenium 的使用溶握。事實上,上一節(jié)用的蒸播,便是 Selenium 的 WebDriver API睡榆。API(Application Programming Interface,應用程序編程接口袍榆,即通過編程語言胀屿,操作 WebDriver 的方法集合)
Selenium WebDriver API 官方參考:http://seleniumhq.github.io/selenium/docs/api/py/
具體API文檔地址:https://seleniumhq.github.io/selenium/docs/api/py/api.html
- API 使用: 用現(xiàn)成的類(大部分情況)的方法進行編程
- WebDriver
- WebElement
- API 文檔
- 編程使用說明
- 介紹了每個方法的使用
- 方法的作用
- 方法的參數(shù)
- 方法的返回值
3.1.1 控制瀏覽器
瀏覽器的控制也是自動化測試的一個基本組成部分,我們可以將瀏覽器最大化包雀,設置瀏覽器的高度和寬度以及對瀏覽器進行導航操作等碉纳。
# 瀏覽器打開網(wǎng)址
driver.get("https://www.baidu.com")
# 瀏覽器最大化
driver.maximize_window()
# 設置瀏覽器的高度為800像素,寬度為480像素
driver.set_window_size(480, 800)
# 瀏覽器后退
driver.back()
# 瀏覽器前進
driver.forward()
# 瀏覽器關閉
driver.close()
# 瀏覽器退出
driver.quit()
3.1.2 元素定位操作
WebDriver提供了一系列的定位符以便使用元素定位方法馏艾。常見的定位符有以下幾種:
- id
- name
- class name
- tag
- link text
- partial link text
- xpath
- css selector
那么我們以下的操作將會基于上述的定位符進行定位操作劳曹。
對于元素的定位,WebDriver API可以通過定位簡單的元素和一組元素來操作琅摩。在這里铁孵,我們需要告訴Selenium如何去找元素,以至于他可以充分的模擬用戶行為房资,或者通過查看元素的屬性和狀態(tài)蜕劝,以便我們執(zhí)行一系列的檢查。
在Selenium2中轰异,WebDriver提供了多種多樣的find_element_by
方法在一個網(wǎng)頁里面查找元素岖沛。這些方法通過提供過濾標準來定位元素。當然WebDriver也提供了同樣多種多樣的find_elements_by
的方式去定位多個元素搭独。
盡管上述的方式婴削,可以進行元素定位,實際上我們也是更多的用組合的方式進行元素定位牙肝。
依據(jù)ID查找
請查看如下HTML的代碼唉俗,以便實現(xiàn)通過ID的屬性值去定義一個查找文本框的查找:
<input id="search" type="text" name="q" value=""
class="input-text" maxlength="128" autocomplete="off"/>
根據(jù)上述代碼,這里我們使用find_element_by_id()
的方法去查找搜索框并且檢查它的最大長度maxlength
屬性配椭。我們通過傳遞ID的屬性值作為參數(shù)去查找虫溜,參考如下的代碼示例:
def test_search_text_field_max_length(self):
# get the search textbox
search_field = self.driver.find_element_by_id("search")
# check maxlength attribute is set to 128
self.assertEqual("128", search_field.get_attribute("maxlength"))
如果使用find_elements_by_id()
方法,將會返回所有的具有相同ID屬性值的一系列元素股缸。
依據(jù)名稱name查找
這里還是根據(jù)上述ID查找的HTML代碼衡楞,使用find_element_by_name
的方法進行查找。參考如下的代碼示例:
# get the search textbox
self.search_field = self.driver.find_element_by_name("q")
同樣敦姻,如果使用find_elements_by_name()
方法瘾境,將會返回所有的具有相同name屬性值的一系列元素坎背。
依據(jù)class name查找
除了上述的ID和name的方式查找,我們還可以使用class name的方式進行查找和定位寄雀。
事實上,通過ID陨献,name或者類名class name查找元素是最提倡推薦的和最快的方式盒犹。當然Selenium2 WebDriver也提供了一些其他的方式,在上述三類方式條件不足眨业,查找無效的時候急膀,可以通過這些其他方式來查找。這些方式將會在后續(xù)的內(nèi)容中講述龄捡。
請查看如下的HTML代碼卓嫂,通過改代碼進行練習和理解.
<button type="submit" title="Search" class="button">
<span><span>Search</span></span>
</button>
根據(jù)上述代碼,使用find_element_by_class_name()
方法去定位元素聘殖。
def test_search_button_enabled(self):
# get Search button
search_button = self.driver.find_element_by_class_name("button")
# check Search button is enabled
self.assertTrue(search_button.is_enabled())
同樣的如果使用find_elements_by_class_name()
方法去定位元素晨雳,將會返回所有的具有相同name屬性值的一系列元素。
依據(jù)標簽名tag name查找
利用標簽的方法類似于利用類名等方法進行查找奸腺。我們可以輕松的查找出一系列的具有相同標簽名的元素餐禁。例如我們可以通過查找表中的<tr>
來獲取行數(shù)。
下面有一個HTML的示例突照,這里在無序列表中使用了<img>
標簽帮非。
<ul class="promos">
<li>
<a >
<img src="/media/wysiwyg/homepage-three-column-promo-
01B.png" alt="Physical & Virtual Gift Cards">
</a>
</li>
<li>
<a >
<img src="/media/wysiwyg/homepage-three-column-promo-
02.png" alt="Shop Private Sales - Members Only">
</a>
</li>
<li>
<a href="http://demo.magentocommerce.com/accessories/
bags-luggage.html">
<img src="/media/wysiwyg/homepage-three-columnpromo-
03.png" alt="Travel Gear for Every Occasion">
</a>
</li>
</ul>
這里面我們使用find_elements_by_tag_name()
的方式去獲取全部的圖片,在此之前讹蘑,我們將會使用find_element_by_class_name()
去獲取到指定的<ul>
末盔。
具體代碼如下:
def test_count_of_promo_banners_images(self):
# get promo banner list
banner_list = self.driver.find_element_by_class_name("promos")
# get images from the banner_list
banners = banner_list.find_elements_by_tag_name("img")
# check there are 20 tags displayed on the page
self.assertEqual(20, len(banners))
依據(jù)鏈接文字link查找
鏈接文字查找通常比較簡單。使用find_element_by_link_text
請查看以下示例
<a href="#header-account" class="skip-link skip-account">
<span class="icon"></span>
<span class="label">ACCOUNT Description</span>
</a>
測試代碼如下:
def test_my_account_link_is_displayed(self):
# get the Account link
account_link =
self.driver.find_element_by_link_text("ACCOUNT Description")
# check My Account link is displayed/visible in
# the Home page footer
self.assertTrue(account_link.is_displayed())
依據(jù)部分鏈接文字partial text查找
這里依舊使用上述的列子進行代碼編寫:
def test_account_links(self):
# get the all the links with Account text in it
account_links = self.driver.\
find_elements_by_partial_link_text("ACCOUNT")
# check Account and My Account link is
# displayed/visible in the Home page footer
self.assertTrue(2, len(account_links))
依據(jù)XPath進行查找
XPath是一種在XML文檔中搜索和定位節(jié)點node的一種查詢語言座慰。所有的主流Web瀏覽器都支持XPath陨舱。Selenium2可以用強大的XPath在頁面中查找元素。
常用的XPath的方法有starts-with()
版仔,contains()
和ends-with()
等
若想要了解更多關于XPath的內(nèi)容隅忿,請查看http://www.w3schools.com/XPath/
如下有一段HTML代碼,其中里面的<img>
沒有使用ID邦尊,name或者類屬性背桐,所以我們無法使用之前的方法。亞這里我們可以通過<img>
的alt
屬性蝉揍,定位到指定的tag链峭。
<ul class="promos">
<li>
<a >
<img src="/media/wysiwyg/homepage-three-column-promo-
01B.png" alt="Physical & Virtual Gift Cards">
</a>
</li>
<li>
<a >
<img src="/media/wysiwyg/homepage-three-column-promo-
02.png" alt="Shop Private Sales - Members Only">
</a>
</li>
<li>
<a href="http://demo.magentocommerce.com/accessories/
bags-luggage.html">
<img src="/media/wysiwyg/homepage-three-columnpromo-
03.png" alt="Travel Gear for Every Occasion">
</a>
</li>
</ul>
具體代碼如下:
def test_vip_promo(self):
# get vip promo image
vip_promo = self.driver.\
find_element_by_xpath("http://img[@alt='Shop Private Sales - Members Only']")
# check vip promo logo is displayed on home page
self.assertTrue(vip_promo.is_displayed())
# click on vip promo images to open the page
vip_promo.click()
# check page title
self.assertEqual("VIP", self.driver.title)
當然,如果使用find_elements_by_xpath()
的方法又沾,將會返回所有匹配了XPath查詢的元素弊仪。
依據(jù)CSS選擇器進行查找
CSS是一種設計師用來描繪HTML文檔的視覺的層疊樣式表熙卡。一般來說CSS用來定位多種多樣的風格,同時可以用來是同樣的標簽使用同樣的風格等励饵。類似于XPath驳癌,Selenium2也可以使用CSS選擇器來定位元素。
請查看如下的HTML文檔役听。
<div class="minicart-wrapper">
<p class="block-subtitle">Recently added item(s)
<a class="close skip-link-close" href="#" title="Close">×</a>
</p>
<p class="empty">You have no items in your shopping cart.
</p>
</div>
我們來創(chuàng)建一個測試颓鲜,驗證這些消息是否正確。
def test_shopping_cart_status(self):
# check content of My Shopping Cart block on Home page
# get the Shopping cart icon and click to open the
# Shopping Cart section
shopping_cart_icon = self.driver.find_element_by_css_selector("div.header-minicart\
span.icon")
shopping_cart_icon.click()
# get the shopping cart status
shopping_cart_status = self.driver.find_element_by_css_selector("p.empty").text
self.assertEqual("You have no items in your shopping cart.", shopping_cart_status)
# close the shopping cart section
close_button = self.driver.find_element_by_css_selector("div.minicart-wrapper a.close")
close_button.click()
特殊 iframe 操作
iframe 元素會創(chuàng)建包含另外一個文檔的內(nèi)聯(lián)框架(即行內(nèi)框架)典予。
iframe: 紫禁城
在一個<html>中甜滨,包含了另一個<html>
示例
<html>
<head>
<title>iframe示例</title>
</head>
<body>
<h1>
這里是H1,標記了標題
</h1>
<p>
這里是段落瘤袖,標記一個段落衣摩,屬于外層
</p>
<div>
<iframe id="iframe-1">
<html>
<body>
<p>
這里是個段落,屬于內(nèi)層捂敌,內(nèi)聯(lián)框架中的
</p>
<div id="div-1">
<p class="hahahp">
這里是div中的段落艾扮,需要被定位
</p>
</div>
</body>
</html>
</iframe>
</div>
</body>
</html>
需要定位上面示例中的<p>
:這里是div中的段落,需要被定位
如下是selenium WebDiriver的代碼
## 查找并定位 iframe
element_frame = driver.find_element_by_css_selector('#iframe-1')
## 切換到剛剛查找到的 iframe
driver.switch_to.frame(element_frame)
## 定位 <p>
driver.find_element_by_css_selector('#div-1 > p')
## TODO....
## 退出剛剛切換進去的 iframe
driver.switch_to.default_content()
特殊 Select 操作
<select>
是選擇列表Select 是個selenium的類
selenium.webdriver.support.select.Select
Select 類的路徑:
C:\Python35\Lib\site-packages\selenium\webdriver\support\select.py
<select id="brand">
<option value ="volvo">Volvo</option>
<option value ="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
</select>
示例占婉,選擇 Audi
## 查找并定位到 select
element_select = driver.find_element_by_css_selector('#brand')
## 用Select類的構(gòu)造方法栏渺,實例化一個對象 object_select
object_select = Select(element_select)
## 操作 object_select
object_select.select_by_index(3)
## 也可以這樣
object_select.select_by_value('audi')
## 還可以這樣
object_select.select_by_visible_text('Audi')
組合操作
自動化經(jīng)驗的積累,需要100%按照手工的步驟進行操作锐涯。
比如步驟如下:
- 點擊一個
<a id="customer_chosen">
- 自動產(chǎn)生了一個
<ul id="customer_list">
- 點擊
<ul>
的第五個<li>
代碼示例
driver.find_element_by_css_selector('#customer_chosen').click()
sleep(1)
driver.find_element_by_css_selector('#customer_list > li:nth-child(5)')
3.1.3 鼠標事件操作
Web測試中磕诊,有關鼠標的操作,不只是單擊纹腌,有時候還要做右擊霎终、雙擊、拖動等操作升薯。這些操作包含在ActionChains類中莱褒。
常用的鼠標方法:
- context_click() # 右擊
- double_click() # 雙擊
- drag_and_drop() # 拖拽
- move_to_element() # 鼠標停在一個元素上
- click_and_hold() # 按下鼠標左鍵在一個元素上
例子:
# 方法模擬鼠標右鍵,參考代碼如下:
# 引入ActionChains 類
from selenium.webdriver.common.action_chains import ActionChains
...
# 定位到要右擊的元素
right =driver.find_element_by_xpath("xx")
# 對定位到的元素執(zhí)行鼠標右鍵操作
ActionChains(driver).context_click(right).perform()
...
# 定位到要雙擊的元素
double = driver.find_element_by_xpath("xxx")
# 對定位到的元素執(zhí)行鼠標雙擊操作
ActionChains(driver).double_click(double).perform()
3.1.4 鍵盤事件操作
鍵盤操作經(jīng)常處理的如下:
代碼 | 描述 |
---|---|
send_keys(Keys.BACKSPACE) |
刪除鍵(BackSpace) |
send_keys(Keys.SPACE) |
空格鍵(Space) |
send_keys(Keys.TAB) |
制表鍵(Tab) |
send_keys(Keys.ESCAPE) |
回退鍵(Esc) |
send_keys(Keys.ENTER) |
回車鍵(Enter) |
send_keys(Keys.CONTROL,'a') |
全選(Ctrl+A) |
send_keys(Keys.CONTROL,'c') |
復制(Ctrl+C) |
代碼如下
from selenium import webdriver
# 引入Keys 類包
from selenium.webdriver.common.keys import Keys
import time
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
# 輸入框輸入內(nèi)容
driver.find_element_by_id("kw").send_keys("selenium")
time.sleep(3)
# 刪除多輸入的一個m
driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE)
time.sleep(3)
# 輸入空格鍵+“教程”
driver.find_element_by_id("kw").send_keys(Keys.SPACE)
driver.find_element_by_id("kw").send_keys("教程")
time.sleep(3)
# ctrl+a 全選輸入框內(nèi)容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'a')
3.1.5 截圖操作
截圖的方法:save_screenshot(file)
3.2 單元測試框架的引入
在上一節(jié)涎劈,我們對 Selenium WebDriver 的使用广凸,僅僅停留在讓網(wǎng)頁自動的進行操作的階段,并沒有對任何一個步驟進行“檢查”蛛枚。當然谅海,這樣沒有“檢查”的操作,實際上是沒有測試意義的蹦浦。那么第一項扭吁,我們需要解決的便是“檢查”的問題。
所謂“檢查”,實際上就是斷言侥袜。對需要檢查的步驟操作蝌诡,通過對預先設置的期望值,和執(zhí)行結(jié)果的實際值之間的對比枫吧,得到測試的結(jié)果浦旱。在這里,我們并不需要單獨的寫 if
語句進行各種判定九杂,而是可以使用編程語言中對應的單元測試框架颁湖,即可解決好此類問題。
目前 Java 語言主流的單元測試框架有 JUnit 和 TestNG尼酿。Python 語言主流的單元測試框架有 unittest 。本小節(jié)的內(nèi)容植影,主要介紹 unittest 的使用裳擎,探討單元測試框架如何幫助自動化測試。
接下來我們將會使用 Python 語言的unittest
框架展開“檢查”思币。unittest
框架的原本的名字是PyUnit鹿响。是從JUnit 這樣一個被廣泛使用的 經(jīng)典的Java應用開發(fā)的單元測試框架創(chuàng)造而來。類似的框架還有NUnit(.Net開發(fā)的單元測試框架)等谷饿。我們可以使用unittest框架為任意Python項目編寫可理解的單元測試集合』涛遥現(xiàn)在這個unittest已經(jīng)作為Python的標準庫模塊發(fā)布。我們安裝完Python以后博投,便可以直接使用unittest绸贡。
使用unittest需要以下簡單的三步:
- 引入unittest模組
- 繼承unittest.TestCase基類
- 測試方法以
test
開頭
unittest 并未使用 Java 語言常見的注解方式,依舊停留在 比較早期的 Java 版本中依靠方法名稱進行識別的方式毅哗。主要有以下兩個固定名字的方法:
- setUp():在每個測試方法運行前听怕,執(zhí)行。是測試前置條件虑绵。
- tearDown():在每個測試方法運行后執(zhí)行尿瞭,是測試清理操作。
具體的代碼如下:
## 引入unittest模組
import unittest
## 定義測試類翅睛,名字為DemoTests
## 該類必須繼承unittest.TestCase基類
class DemoTests(unittest.TestCase):
## 使用'@'修飾符声搁,注明該方法是類的方法
## setUpClass方法是在執(zhí)行測試之前需要先調(diào)用的方法
## 是開始測試前的初始化工作
@classmethod
def setUpClass(cls):
print("call setUpClass()")
## 每一個測試開始前的預置條件
def setUp(self):
print("call setUp()")
## 每一個測試結(jié)束以后的清理工作
def tearDown(self):
print("call tearDown()")
## 測試一(務必以test開頭)
def test_01(self):
print("call test_01()")
pass
## 測試三(務必以test開頭)
def test_02(self):
print("call test_02()")
pass
## 測試三(務必以test開頭)
def test_03(self):
print("call test_03()")
pass
## tearDownClass方法是執(zhí)行完所有測試后調(diào)用的方法
## 是測試結(jié)束后的清除工作
@classmethod
def tearDownClass(cls):
print("call tearDownClass()")
# 執(zhí)行測試主函數(shù)
if __name__ == '__main__':
## 執(zhí)行main全局方法,將會執(zhí)行上述所有以test開頭的測試方法
unittest.main(verbosity=2)
需要注意步驟:
- 引入 unittest 模組
- 繼承 unittest.TestCase 類
- 做測試用例的方法捕发,方法以 test_ 開頭
- 附加 setUp(), tearDown(), 在每個 test_ 方法執(zhí)行前后 進行執(zhí)行
- 附加 setUpClass(), tearDownClass()
需要在 類實例化的對象疏旨,運行的開頭和結(jié)尾進行執(zhí)行。
加了星號(*)的步驟扎酷,可以不用充石。
- 附加 setUpClass(), tearDownClass()
上述代碼運行結(jié)果如下:
call setUpClass()
call setUp()
call test_01()
call tearDown()
call setUp()
call test_02()
call tearDown()
call setUp()
call test_06()
call tearDown()
call tearDownClass()
-
unittest 的斷言配置使用
unittest 的斷言,屬于
TestCase
類,只要繼承了該類骤铃,均可以通過 self調(diào)用斷言方法 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可選巩掺,用來解釋失敗的原因
3.3 測試用例類的編寫
這里,我們需要結(jié)合 unittest 與 WebDriver 來一起編寫 測試用例的類页畦。
- WebDriver 的實例化放到 setUp() 里面實現(xiàn)
- WebDriver 實例化的對象的退出胖替,放到 tearDown() 里面實現(xiàn)
- 測試的步驟與斷言,放到 test_ 開頭的方法里
參考一個例子豫缨。
from time import sleep
from selenium import webdriver
import unittest
class RanzhiTest(unittest.TestCase):
"""
用例 [rzat01] 系統(tǒng)登錄模塊能接受不同的語言和不同類型的用戶在有效和無效范圍內(nèi)登錄独令。
"""
base_url = None
main_page = None
def set_up(self):
"""
測試前置條件
:param **kwargs:
:return:
"""
self.base_driver = webdriver.Chrome()
self.base_url = "http://localhost/ranzhi/www/"
def tear_down(self):
"""
測試清理條件
:return:
"""
self.base_driver.quit()
def test_01(self):
"""
測試有效和無效用戶登錄
:return:
"""
account = "admin"
password = "123456"
self.base_driver.get(self.base_url)
sleep(2)
we_account = self.base_driver.find_element_by_id("account")
we_account.clear()
we_account.send_keys(account)
we_password = self.base_driver.find_element_by_id("password")
we_account.clear()
we_account.send_keys(password)
self.base_driver.find_element_by_id("submit").click()
sleep(2)
expected_url = self.base_url + "sys/index.html"
actual_url = self.base_driver.get_url()
self.assertEqual(expected_url, actual_url, "有效登錄用戶[%s]登錄失敗或者登錄后跳轉(zhuǎn)錯誤!" % account)
- 相關學習
立師兄Linty:六天入門軟件測試①——測試執(zhí)行講義