selenium自動(dòng)化測試基礎(chǔ)

selenium自動(dòng)化測試基礎(chǔ)

原文閱讀對象是針對測試人員碰缔,測試人員普遍開發(fā)能力偏弱萤彩,所以講的比較瑣碎膘掰,這里做了一定的刪減和改寫摹芙,主要針對測試主管或有一定經(jīng)驗(yàn)的開發(fā)人員或負(fù)責(zé)人嵌莉,快速了解及考慮使用selenium自動(dòng)化測試方案苛茂。

自動(dòng)化測試并不屬于新鮮的事物,或者說自動(dòng)化測試的各種方法論已經(jīng)層出不窮族操,但是苛坚,能夠在項(xiàng)目中持之以恒的實(shí)踐自動(dòng)化測試的團(tuán)隊(duì),卻依舊不是非常多色难。有的團(tuán)隊(duì)知道怎么做泼舱,做的還不夠好;有的團(tuán)隊(duì)還正在探索和摸索怎么做枷莉,甚至還有一些多方面的技術(shù)上和非技術(shù)上的舊系統(tǒng)需要重構(gòu)……

本文從使用實(shí)踐兩個(gè)視角娇昙,嘗試對基于Web UI自動(dòng)化測試做細(xì)致的分析和解讀,給各位去思考和實(shí)踐做一點(diǎn)引路依沮,以便各團(tuán)隊(duì)能找到更好的方式涯贞。

1. 使用測試工具

在開始具體的自動(dòng)化測試之前,我們需要做好更多的準(zhǔn)備危喉,包括以下幾個(gè)方面:

  • 認(rèn)識自動(dòng)化測試
  • 準(zhǔn)備自動(dòng)化測試工具
  • 使用有效的方式
  • 針對具體的測試對象

1.1 自動(dòng)化測試?yán)碚摻榻B

自動(dòng)化測試不再是一個(gè)陌生的話題宋渔,作為測試實(shí)踐活動(dòng)的一部分,我們首先分析一下自動(dòng)化測試的方方面面辜限。

自動(dòng)化測試的4W1H

  • WHAT - 什么是自動(dòng)化測試

    《軟件測試藝術(shù)》一書中皇拣,給出了測試的定義:

    “程序測試是為了發(fā)現(xiàn)錯(cuò)誤而執(zhí)行的過程。”

    自動(dòng)化測試:以人為驅(qū)動(dòng)的測試行為轉(zhuǎn)化為機(jī)器執(zhí)行的一種過程

    自動(dòng)化測試氧急,就是把手工進(jìn)行的測試過程颗胡,轉(zhuǎn)變成機(jī)器自動(dòng)執(zhí)行的測試過程。該過程吩坝,依舊是為了發(fā)現(xiàn)錯(cuò)誤而執(zhí)行毒姨。因此自動(dòng)化測試的關(guān)鍵在于“自動(dòng)化”三個(gè)字。自動(dòng)化測試的內(nèi)容钉寝,也就相應(yīng)的轉(zhuǎn)變成如何“自動(dòng)化”去實(shí)現(xiàn)原本手工進(jìn)行的測試的過程弧呐。

    通過程序,可以把手工測試嵌纲,轉(zhuǎn)變成自動(dòng)化測試俘枫。

  • WHEN - 在什么時(shí)候開展自動(dòng)化測試

    自動(dòng)化測試的開展,依賴于“程序”逮走。那么程序鸠蚪,其實(shí)就是由“源代碼”構(gòu)建而來的。那么原則上师溅,只要能做出自動(dòng)化測試所需要的“程序”的時(shí)候茅信,就可以進(jìn)行自動(dòng)化測試。但往往险胰,并不是所有的“時(shí)候”都是好的“時(shí)機(jī)”汹押。從這個(gè)W開始矿筝,我們將會(huì)加入對于成本的顧慮起便,也正是因?yàn)椤俺杀尽钡拇嬖冢攀沟孟旅娴挠懻摻盐兊糜幸饬x榆综。

    所有的開銷,都是有成本的铸史。構(gòu)建成“程序”的源代碼鼻疮,也是由工程師寫出來的。那么需要考慮這個(gè)過程中的成本琳轿∨泄担基于這個(gè)考慮,在能夠比較穩(wěn)定的構(gòu)建“程序”的時(shí)候崭篡,不需要花費(fèi)太多開銷在“源代碼”的時(shí)候挪哄,就是開展自動(dòng)化測試的好時(shí)機(jī)。這個(gè)開銷包括編寫修改源代碼琉闪,而源代碼指的是構(gòu)建出用來做自動(dòng)化測試的程序的源代碼迹炼。

  • WHERE - 在什么地方進(jìn)行自動(dòng)化測試

    自動(dòng)化測試的執(zhí)行,依靠的是機(jī)器。那么自動(dòng)化測試必將在“機(jī)器”上進(jìn)行斯入。一般來說砂碉,這個(gè)機(jī)器包括桌面電腦和服務(wù)器。通過將寫好的源代碼部署在機(jī)器上刻两,構(gòu)建出用來做自動(dòng)化測試的"程序"增蹭,并且運(yùn)行該程序,實(shí)現(xiàn)自動(dòng)化測試磅摹。

  • WHICH - 對什么目標(biāo)進(jìn)行自動(dòng)化測試

    自動(dòng)化測試的目標(biāo)沪铭,是被測試的軟件。拋開人工智能的成分偏瓤,手工測試必將在“人工智能”足夠普及和足夠“智能”之前杀怠,替代一大部分不需要“人類智能”的手工測試;以及自動(dòng)化測試會(huì)做一些手工測試無法實(shí)施的厅克,或者手工測試無法覆蓋的測試赔退。

- 不需要“人類智能”的普通手工測試 
    - 界面的普通操作
    - 通過固定輸入和固定操作而進(jìn)行的流程化測試
    - 重復(fù)的普通測試
- 手工測試無法實(shí)施或者覆蓋的 
    - 大量的數(shù)據(jù)的輸入
    - 大量的步驟的操作
    - 源代碼基本的測試
    - 系統(tǒng)模塊間接口的調(diào)用測試
    - ……
  • HOW - 如何開展自動(dòng)化測試

    • 準(zhǔn)備測試用例
    • 找到合適的自動(dòng)化測試工具
    • 用準(zhǔn)確的編程形成測試腳本
    • 在測試腳本中對目標(biāo)進(jìn)行“檢查”,即做斷言
    • 記錄測試日志证舟,生成測試結(jié)果

和所有的其他測試一樣硕旗,自動(dòng)化測試的流程也是由“用例”執(zhí)行和“缺陷”驗(yàn)證組成。差別是需要找到合適的“工具”來替代“人手”女责。不同目標(biāo)的自動(dòng)化測試有不同的測試工具漆枚,但是任何工具都無不例外的需要“編程”的過程,實(shí)現(xiàn)“源代碼”抵知,也可以稱之為測試腳本墙基。

于是開展自動(dòng)化測試的方式基本上如下:

自動(dòng)化測試的典型金字塔原理

談到自動(dòng)化測試,就不得不提的一個(gè)人和概念就是:Martin Fowler和他的金字塔原理刷喜。首先請看金字塔原理的圖示如下:

該圖說明了三個(gè)問題:

  • 自動(dòng)化測試包括三個(gè)方面:UI前端界面残制,Service服務(wù)契約和Unit底層單元
  • 越是底層的測試,運(yùn)行速度越快掖疮,時(shí)間開銷越少初茶,金錢開銷越少
  • 越是頂層的測試,運(yùn)行速度越慢浊闪,時(shí)間開銷越多恼布,金錢開銷越多

這是理想中的金字塔原理。

在實(shí)際的項(xiàng)目中搁宾,尤其是結(jié)合國內(nèi)的項(xiàng)目實(shí)踐折汞,其實(shí)還隱藏了另一個(gè)問題:越是頂層的測試,效果越明顯猛铅。有句話說“貴的東西字支,除了貴,其他都是好的!”能夠很清晰的闡述這個(gè)觀點(diǎn)堕伪。

金字塔原理在國內(nèi)的適應(yīng)性也有一定的問題

  • 自動(dòng)化測試的起步不是特別早
  • 甚至軟件測試很長一段時(shí)間都在進(jìn)行基于業(yè)務(wù)的手工測試揖庄,測試人員的代碼能力相對較弱
  • 開發(fā)人員在代碼中不太習(xí)慣寫單元測試
  • 近些年基于服務(wù)契約的API測試也在興起

相對來說,在基于UI前端界面的自動(dòng)化測試反倒是開展和實(shí)施的不是特別多欠雌。盡管基于界面的測試帶來的效果還是能夠立竿見影的蹄梢。對于產(chǎn)品的質(zhì)量提升,還是比較容易有保證富俄。

自動(dòng)化測試的適用范圍

自動(dòng)化測試可以涉及和試用的范圍主要在以下方面:

  • 基于Web UI的瀏覽器應(yīng)用的界面測試
  • 基于WebService或者WebAPI的服務(wù)契約測試
  • 基于WCF禁炒、.net remotingSpring等框架的服務(wù)的集成測試
  • 基于APP UI的移動(dòng)應(yīng)用界面測試
  • 基于Java霍比、C#等編程文件進(jìn)行的單元測試

本文集中討論第一條:基于Web UI的瀏覽器應(yīng)用的界面測試幕袱。界面的改動(dòng)對于測試來說,具有較大的成本風(fēng)險(xiǎn)悠瞬。主要考慮以下方面:

  • 任務(wù)測試明確们豌,不會(huì)頻繁變動(dòng)
  • 每日構(gòu)建后的測試驗(yàn)證
  • 比較頻繁的回歸測試
  • 軟件系統(tǒng)界面穩(wěn)定,變動(dòng)少
  • 需要在多平臺上運(yùn)行的相同測試案例浅妆、組合遍歷型的測試望迎、大量的重復(fù)任務(wù)
  • 軟件維護(hù)周期長
  • 項(xiàng)目進(jìn)度壓力不太大
  • 被測軟件系統(tǒng)開發(fā)比較規(guī)范,能夠保證系統(tǒng)的可測試性
  • 具備大量的自動(dòng)化測試平臺
  • 測試人員具備較強(qiáng)的編程能力
  • 自動(dòng)化測試的流程

自動(dòng)化測試和普通的手工測試遵循的測試流程凌外,與項(xiàng)目的具體實(shí)踐相關(guān)辩尊。一般來說,也是需要從測試計(jì)劃開始涉及自動(dòng)化測試的康辑。

  • 測試計(jì)劃:劃定自動(dòng)化測試的范圍包含哪些需求摄欲,涉及到哪些測試過程
  • 測試策略:確定自動(dòng)化測試的工具、編程方案晾捏、代碼管理蒿涎、測試重點(diǎn)
  • 測試設(shè)計(jì):使用測試設(shè)計(jì)方法對被測試的需求進(jìn)行設(shè)計(jì)哀托,得出測試的測試點(diǎn)惦辛、用例思維導(dǎo)圖等
  • 測試實(shí)施:根據(jù)測試設(shè)計(jì)進(jìn)行用例編寫,并且將測試用例用編程的方式實(shí)現(xiàn)測試腳本
  • 測試執(zhí)行:執(zhí)行測試用例仓手,運(yùn)行測試腳本胖齐,生成測試結(jié)果

1.2 自動(dòng)化測試工具

基于Web UI的自動(dòng)化測試工具主要有兩大類:付費(fèi)的商業(yè)版工具和免費(fèi)使用的開源版工具。典型的有兩種:

  • UFT嗽冒,QTP被惠普收購以后的新名稱呀伙。
    • 通過程序的錄制,可以實(shí)現(xiàn)測試的編輯
    • 錄制的測試腳本是 VBScript 語法
    • 成熟版的商業(yè)付費(fèi)工具
    • 工具比較龐大添坊,對具體的項(xiàng)目定制測試有難度
  • SELENIUM剿另,本次選擇的開源工具
    • 本身不是測試工具,只是模擬瀏覽器操作的工具
    • 背后有 Google 維護(hù)源代碼
    • 支持全部主流的瀏覽器
    • 支持主流的編程語言,包括:Java雨女、Python谚攒、C#、PHP氛堕、Ruby馏臭、JavaScript等
    • 工具很小,可以實(shí)現(xiàn)對測試項(xiàng)目的定制測試方案
    • 基于標(biāo)準(zhǔn)的 WebDriver 語法規(guī)范

Selenium 基本介紹

Selenium`是開源的自動(dòng)化測試工具讼稚,它主要是用于Web 應(yīng)用程序的自動(dòng)化測試括儒,不只局限于此,同時(shí)支持所有基于web 的管理任務(wù)自動(dòng)化锐想。

  • 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 是用于測試 Web 應(yīng)用程序用戶界面 (UI) 的常用框架帮寻。它是一款用于運(yùn)行端到端功能測試的超強(qiáng)工具。您可以使用多個(gè)編程語言編寫測試赠摇,并且 Selenium 能夠在一個(gè)或多個(gè)瀏覽器中執(zhí)行這些測試规婆。

Selenium 工具集

  • Selenium IDE

    Selenium IDE (集成開發(fā)環(huán)境) 是一個(gè)創(chuàng)建測試腳本的原型工具。它是一個(gè) Firefox 插件蝉稳,實(shí)現(xiàn)簡單的瀏覽器操作的錄制與回放功能抒蚜,提供創(chuàng)建自動(dòng)化測試的建議接口。Selenium IDE 有一個(gè)記錄功能耘戚,能記錄用戶的操作嗡髓,并且能選擇多種語言把它們導(dǎo)出到一個(gè)可重用的腳本中用于后續(xù)執(zhí)行。

  • Selenium RC

    Selenium RC 是selenium 家族的核心工具收津,Selenium RC 支持多種不同的語言編寫自動(dòng)化測試腳本饿这,通過selenium RC 的服務(wù)器作為代理服務(wù)器去訪問應(yīng)用從而達(dá)到測試的目的。

    selenium RC 使用分Client Libraries 和Selenium Server撞秋。

- Client Libraries 庫主要主要用于編寫測試腳本长捧,用來控制selenium Server 的庫。
- Selenium Server 負(fù)責(zé)控制瀏覽器行為吻贿,總的來說串结,Selenium Server 主要包括3 個(gè)部分:Launcher、Http Proxy舅列、Core肌割。
  • Selenium Grid

    Selenium Grid 使得 Selenium RC 解決方案能提升針對大型的測試套件或者哪些需要運(yùn)行在多環(huán)境的測試套件的處理能力。Selenium Grid 能讓你并行的運(yùn)行你的測試帐要,也就是說把敞,不同的測試可以同時(shí)跑在不同的遠(yuǎn)程機(jī)器上。這樣做有兩個(gè)優(yōu)勢榨惠,首先奋早,如果你有一個(gè)大型的測試套件盛霎,或者一個(gè)跑的很慢的測試套件,你可以使用 Selenium Grid 將你的測試套件劃分成幾份同時(shí)在幾個(gè)不同的機(jī)器上運(yùn)行耽装,這樣能顯著的提升它的性能摩渺。同時(shí),如果你必須在多環(huán)境中運(yùn)行你的測試套件剂邮,你可以獲得多個(gè)遠(yuǎn)程機(jī)器的支持摇幻,它們將同時(shí)運(yùn)行你的測試套件。在每種情況下挥萌,Selenium Grid 都能通過并行處理顯著地縮短你的測試套件的處理時(shí)間绰姻。

  • Selenium WebDriver

    WebDriver 是 Selenium 2 主推的工具,事實(shí)上WebDriver是Selenium RC的替代品引瀑,因?yàn)镾elenium需要保留向下兼容性的原因狂芋,在 Selenium 2 中, Selenium RC才沒有被徹底的拋棄憨栽,如果使用Selenium開發(fā)一個(gè)新的自動(dòng)化測試項(xiàng)目帜矾,那么我們強(qiáng)烈推薦使用Selenium2 的 WebDriver進(jìn)行編碼。另外屑柔, 在Selenium 3 中屡萤,Selenium RC 被移除了。

自動(dòng)化編程語言Python選擇

  • 測試人員的編程能力普遍不是很強(qiáng)掸宛,而Python作為一種腳本語言死陆,不僅功能強(qiáng)大,而且語法優(yōu)美唧瘾,支持多種自動(dòng)化測試工具措译,而且學(xué)習(xí)上手比較容易。
  • 對于有一定編程基礎(chǔ)的人員饰序,使用Python作為自動(dòng)化測試的語言可以非常順暢的轉(zhuǎn)換领虹,幾乎沒有學(xué)習(xí)成本。同時(shí)Python是標(biāo)準(zhǔn)的面向?qū)ο蟮木幊陶Z言求豫,對于C#塌衰、Java等面向?qū)ο蟮恼Z言有著非常好的示例作用,通過Python的示例可以非常輕松的觸類旁通注祖,使用其他語言進(jìn)行Selenium2.0的WebDriver的使用猾蒂。

使用的工具集

  • IDE: Jetbrains PyCharm
  • 語言: Python
  • 工具: Selenium WebDriver
  • 源代碼管理: SVN/Git

JetBrains PyCharm 使用

  • JetBrains PyCharm 的介紹

PyCharm 是 JetBrains 公司針對Python推出的IDE(Integrated Development Environment,集成開發(fā)環(huán)境)是晨。是目前最好的Python IDE之一。目前包含了兩個(gè)版本:

  • 社區(qū)版舔箭,Community Edition
  • 專業(yè)版罩缴,Professional Edition
    • 付費(fèi)
    • 比社區(qū)版主要多了Web開發(fā)框架

我們推薦使用免費(fèi)的社區(qū)版本蚊逢,進(jìn)行Python腳本的編寫和自動(dòng)化測試執(zhí)行。

PyCharm可以在官網(wǎng)下載箫章,http://www.jetbrains.com

Selenium 的環(huán)境搭建

在 Windows 搭建和部署 Selenium 工具

先安裝python

  • 安裝 Selenium 工具包

    由于 安裝好的 Python 默認(rèn)有 pip Python 包管理工具烙荷,可以通過 pip 非常方便的安裝 Selenium。

```
pip install selenium
```

```
pip install -U selenium
```
    

當(dāng)然檬寂,可以事先下載 Selenium 的 Python 安裝包终抽,再進(jìn)行手動(dòng)安裝。
    
官方下載地址:https://pypi.python.org/pypi/selenium

```
python setup.py install
```                                

?

  • 配置瀏覽器和驅(qū)動(dòng)

    Selenium 3 對于所有的瀏覽器都需要安裝驅(qū)動(dòng)桶至,本文以 Chrome 和 Firefox昼伴、IE為例設(shè)置瀏覽器和驅(qū)動(dòng)。

ChromeDriver下載地址:http://chromedriver.storage.googleapis.com/index.html

ChromeDriver 與 Chrome 對應(yīng)關(guān)系表:
        
ChromeDriver版本 | 支持的Chrome版本 |
-|-|
v2.31| v58-60 |
v2.30 |v58-60 |
v2.29 |v56-58 |

GeckoDriver下載地址:https://github.com/mozilla/geckodriver/releases

GeckoDriver 與 Firefox 的對應(yīng)關(guān)系表:
        
GeckoDriver版本 |支持的Firefox版本 |
-|-|
v0.18.0| v56 |
v0.17.0 |v55 |


IEDriverServer下載地址:http://selenium-release.storage.googleapis.com/index.html

IEDriverServer 的版本需要與 Selenium 保持嚴(yán)格一致镣屹。

**瀏覽器驅(qū)動(dòng)的配置**
        
- 首先圃郊,將下載好的對應(yīng)版本的瀏覽器安裝。
- 其次女蜈,在 Python 的根目錄中持舆,放入瀏覽器驅(qū)動(dòng)。
- 最好再重啟電腦伪窖,一般情況下不重啟也可以的逸寓。

?

1.3 Selenium 的最簡腳本

通過上一節(jié)的環(huán)境安裝成功以后,我們可以進(jìn)行第一個(gè)對Selenium 的使用覆山,就是最簡腳本編寫席覆。腳本如下:

# 聲明一個(gè)司機(jī),司機(jī)是個(gè)Chrome類的對象
driver = webdriver.Chrome()

# 讓司機(jī)加載一個(gè)網(wǎng)頁
driver.get("http://demo.xxx.com")

# 給司機(jī)3秒鐘去打開
sleep(3)

# 開始登錄
# 1. 讓司機(jī)找用戶名的輸入框
we_account = driver.find_element_by_css_selector('#account')
we_account.clear()
we_account.send_keys("demo")

# 2. 讓司機(jī)找密碼的輸入框
we_password = driver.find_element_by_css_selector('#password')
we_password.clear()
we_password.send_keys("demo")

# 3. 讓司機(jī)找 登錄按鈕 并 單擊
driver.find_element_by_css_selector('#submit').click()
sleep(3)

實(shí)際上一段20行的代碼汹买,也不能算太少了佩伤。但是這段代碼的使用,確實(shí)體現(xiàn)了 Selenium 的最簡單的使用晦毙。這些代碼有開發(fā)基礎(chǔ)的同學(xué)生巡,一看都懂。

注意:Chrome 是 WebDriver 的子類见妒,是 WebDriver 類的一種

1.4 Selenium WebDriver API 的使用

通過上述最簡腳本的使用孤荣,我們可以來進(jìn)一步了解 Selenium 的使用。事實(shí)上须揣,上一節(jié)用的盐股,便是 Selenium 的 WebDriver API帽馋。

Selenium WebDriver API 官方參考:http://seleniumhq.github.io/selenium/docs/api/py/

具體API文檔地址:https://seleniumhq.github.io/selenium/docs/api/py/api.html

控制瀏覽器

瀏覽器的控制也是自動(dòng)化測試的一個(gè)基本組成部分拘泞,我們可以將瀏覽器最大化,設(shè)置瀏覽器的高度和寬度以及對瀏覽器進(jìn)行導(dǎo)航操作等地来。


# 瀏覽器打開網(wǎng)址
driver.get("https://www.baidu.com")

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

# 設(shè)置瀏覽器的高度為800像素卵酪,寬度為480像素
driver.set_window_size(480, 800)

# 瀏覽器后退
driver.back()

# 瀏覽器前進(jìn)
driver.forward()

# 瀏覽器關(guān)閉
driver.close()

# 瀏覽器退出
driver.quit()

元素定位操作

WebDriver提供了一系列的定位符以便使用元素定位方法幌蚊。常見的定位符有以下幾種:

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

那么我們以下的操作將會(huì)基于上述的定位符進(jìn)行定位操作谤碳。

對于元素的定位,WebDriver API可以通過定位簡單的元素和一組元素來操作溢豆。在這里蜒简,我們需要告訴Selenium如何去找元素,以至于他可以充分的模擬用戶行為漩仙,或者通過查看元素的屬性和狀態(tài)搓茬,以便我們執(zhí)行一系列的檢查。

在Selenium2中队他,WebDriver提供了多種多樣的find_element_by方法在一個(gè)網(wǎng)頁里面查找元素卷仑。這些方法通過提供過濾標(biāo)準(zhǔn)來定位元素。當(dāng)然WebDriver也提供了同樣多種多樣的find_elements_by的方式去定位多個(gè)元素漱挎。

盡管上述的方式系枪,可以進(jìn)行元素定位,實(shí)際上我們也是更多的用組合的方式進(jìn)行元素定位磕谅。

方法Method 描述Description 參數(shù)Argument 示例Example
id 該方法通過ID的屬性值去定位查找單個(gè)元素 id: 需要被查找的元素的ID find_element_by_id('search')
name 該方法通過name的屬性值去定位查找單個(gè)元素 name: 需要被查找的元素的名稱 find_element_by_name('q')
class name 該方法通過class的名稱值去定位查找單個(gè)元素 class_name: 需要被查找的元素的類名 find_element_by_class_name('input-text')
tag_name 該方法通過tag的名稱值去定位查找單個(gè)元素 tag: 需要被查找的元素的標(biāo)簽名稱 find_element_by_tag_name('input')
link_text 該方法通過鏈接文字去定位查找單個(gè)元素 link_text: 需要被查找的元素的鏈接文字 find_element_by_link_text('Log In')
partial_link_text 該方法通過部分鏈接文字去定位查找單個(gè)元素 link_text: 需要被查找的元素的部分鏈接文字 find_element_by_partial_link_text('Long')
xpath 該方法通過XPath的值去定位查找單個(gè)元素 xpath: 需要被查找的元素的xpath find_element_by_xpath('//*[@id="xx"]/a')
css_selector 該方法通過CSS選擇器去定位查找單個(gè)元素 css_selector: 需要被查找的元素的ID find_element_by_css_selector('#search')

find_elements_by的方法依據(jù)匹配的具體標(biāo)準(zhǔn)返回一系列的元素私爷。

下面代碼通過ID的屬性值去定義一個(gè)查找文本框的查找:


<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()方法,將會(huì)返回所有的具有相同ID屬性值的一系列元素放刨。

這里還是根據(jù)上述ID查找的HTML代碼工秩,使用find_element_by_name的方法進(jìn)行查找。參考如下的代碼示例:


# get the search textbox
self.search_field = self.driver.find_element_by_name("q")

同樣进统,如果使用find_elements_by_name()方法助币,將會(huì)返回所有的具有相同name屬性值的一系列元素。

依據(jù)class name查找

除了上述的ID和name的方式查找螟碎,我們還可以使用class name的方式進(jìn)行查找和定位眉菱。

事實(shí)上,通過ID掉分,name或者類名class name查找元素是最提倡推薦的和最快的方式俭缓。

<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())


其他方式都可以參考jquery或一些爬蟲關(guān)于html節(jié)點(diǎn)查找的方法华坦。

依據(jù)XPath進(jìn)行查找

XPath是一種在XML文檔中搜索和定位節(jié)點(diǎn)node的一種查詢語言。所有的主流Web瀏覽器都支持XPath不从。

常用的XPath的方法有starts-with()惜姐,contains()ends-with()

若想要了解更多關(guān)于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 &amp; 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://www.9999.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)

當(dāng)然倡勇,如果使用find_elements_by_xpath()的方法逞刷,將會(huì)返回所有匹配了XPath查詢的元素。

依據(jù)CSS選擇器進(jìn)行查找

CSS是一種設(shè)計(jì)師用來描繪HTML文檔的視覺的層疊樣式表妻熊。一般來說CSS用來定位多種多樣的風(fēng)格夸浅,同時(shí)可以用來是同樣的標(biāo)簽使用同樣的風(fēng)格等。

<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)建一個(gè)測試扔役,驗(yàn)證這些消息是否正確帆喇。


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 元素會(huì)創(chuàng)建包含另外一個(gè)文檔的內(nèi)聯(lián)框架(即行內(nèi)框架)。

在一個(gè)<html>中亿胸,包含了另一個(gè)<html>

示例

<html>
  <head>
    <title>iframe示例</title>
  </head>
  <body>
    <h1>
      這里是H1坯钦,標(biāo)記了標(biāo)題
    </h1>
    <p>
      這里是段落,標(biāo)記一個(gè)段落侈玄,屬于外層
    </p>
    <div>
      <iframe id="iframe-1">
        <html>
          <body>
            <p>
              這里是個(gè)段落婉刀,屬于內(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中的段落突颊,需要被定位</p>

如下是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....
## 退出剛剛切換進(jìn)去的 iframe
driver.switch_to.default_content()

特殊 Select 操作

<select> 是選擇列表

Select 是個(gè)selenium的類selenium.webdriver.support.select.Select


<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)造方法潘悼,實(shí)例化一個(gè)對象 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')


組合操作

自動(dòng)化經(jīng)驗(yàn)的積累律秃,需要100%按照手工的步驟進(jìn)行操作。

比如步驟如下:

  1. 點(diǎn)擊一個(gè) <a id="customer_chosen">
  2. 自動(dòng)產(chǎn)生了一個(gè) <ul id="customer_list">
  3. 點(diǎn)擊<ul>的第五個(gè)<li>

代碼示例

driver.find_element_by_css_selector('#customer_chosen').click()
sleep(1)
driver.find_element_by_css_selector('#customer_list > li:nth-child(5)').click()

鼠標(biāo)事件操作

Web測試中治唤,有關(guān)鼠標(biāo)的操作棒动,不只是單擊,有時(shí)候還要做右擊肝劲、雙擊迁客、拖動(dòng)等操作。這些操作包含在ActionChains類中辞槐。

常用的鼠標(biāo)方法:

  • context_click() # 右擊
  • double_click() # 雙擊
  • drag_and_drop() # 拖拽
  • move_to_element() # 鼠標(biāo)停在一個(gè)元素上
  • click_and_hold() # 按下鼠標(biāo)左鍵在一個(gè)元素上

例子:

# 方法模擬鼠標(biāo)右鍵掷漱,參考代碼如下:
# 引入ActionChains 類
from selenium.webdriver.common.action_chains import ActionChains
...
# 定位到要右擊的元素
right =driver.find_element_by_xpath("xx")
# 對定位到的元素執(zhí)行鼠標(biāo)右鍵操作
ActionChains(driver).context_click(right).perform()
...
# 定位到要雙擊的元素
double = driver.find_element_by_xpath("xxx")
# 對定位到的元素執(zhí)行鼠標(biāo)雙擊操作
ActionChains(driver).double_click(double).perform()

鍵盤事件操作

鍵盤操作經(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') 復(fù)制(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)

# 刪除多輸入的一個(gè)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')

截圖操作

截圖的方法:save_screenshot(file)

1.5 unittest 單元測試框架

在上一節(jié),我們對 Selenium WebDriver 的使用榄檬,僅僅停留在讓網(wǎng)頁自動(dòng)的進(jìn)行操作的階段卜范,并沒有對任何一個(gè)步驟進(jìn)行“檢查”。當(dāng)然鹿榜,這樣沒有“檢查”的操作海雪,實(shí)際上是沒有測試意義的锦爵。那么第一項(xiàng),我們需要解決的便是“檢查”的問題奥裸。

所謂“檢查”险掀,實(shí)際上就是斷言。對需要檢查的步驟操作湾宙,通過對預(yù)先設(shè)置的期望值樟氢,和執(zhí)行結(jié)果的實(shí)際值之間的對比,得到測試的結(jié)果侠鳄。在這里埠啃,我們并不需要單獨(dú)的寫 if 語句進(jìn)行各種判定,而是可以使用編程語言中對應(yīng)的單元測試框架伟恶,即可解決好此類問題碴开。

目前 Java 語言主流的單元測試框架有 JUnit 和 TestNG。Python 語言主流的單元測試框架有 unittest 博秫。本小節(jié)的內(nèi)容潦牛,主要介紹 unittest 的使用,探討單元測試框架如何幫助自動(dòng)化測試台盯。

接下來我們將會(huì)使用 Python 語言的unittest框架展開“檢查”罢绽。unittest框架的原本的名字是PyUnit。是從JUnit 這樣一個(gè)被廣泛使用的經(jīng)典的Java應(yīng)用開發(fā)的單元測試框架創(chuàng)造而來静盅。類似的框架還有NUnit(.Net開發(fā)的單元測試框架)等良价。我們可以使用unittest框架為任意Python項(xiàng)目編寫可理解的單元測試集合。現(xiàn)在這個(gè)unittest已經(jīng)作為Python的標(biāo)準(zhǔn)庫模塊發(fā)布蒿叠。我們安裝完P(guān)ython以后明垢,便可以直接使用unittest。

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

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

unittest 并未使用 Java 語言常見的注解方式市咽,依舊停留在 比較早期的 Java 版本中依靠方法名稱進(jìn)行識別的方式痊银。主要有以下兩個(gè)固定名字的方法:

  • setUp():在每個(gè)測試方法運(yùn)行前,執(zhí)行施绎。是測試前置條件溯革。
  • tearDown():在每個(gè)測試方法運(yùn)行后執(zhí)行,是測試清理操作谷醉。

具體的代碼如下:

## 引入unittest模組
import unittest

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

    ## 使用'@'修飾符,注明該方法是類的方法
    ## setUpClass方法是在執(zhí)行測試之前需要先調(diào)用的方法
    ## 是開始測試前的初始化工作
    @classmethod
    def setUpClass(cls):
        print("call setUpClass()")
    
    ## 每一個(gè)測試開始前的預(yù)置條件
    def setUp(self):
        print("call setUp()")
        
    ## 每一個(gè)測試結(jié)束以后的清理工作
    def tearDown(self):
        print("call tearDown()")

    ## 測試一(務(wù)必以test開頭)
    def test_01(self):
        print("call test_01()")
        pass

    ## 測試三(務(wù)必以test開頭)
    def test_02(self):
        print("call test_02()")
        pass

    ## 測試三(務(wù)必以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全局方法俱尼,將會(huì)執(zhí)行上述所有以test開頭的測試方法
    unittest.main(verbosity=2)

需要注意步驟:

  1. 引入 unittest 模組
  2. 繼承 unittest.TestCase 類
  3. 做測試用例的方法抖单,方法以 test_ 開頭
  • 附加 setUp(), tearDown(), 在每個(gè) test_ 方法執(zhí)行前后 進(jìn)行執(zhí)行
  • 附加 setUpClass(), tearDownClass()
    需要在 類實(shí)例化的對象,運(yùn)行的開頭和結(jié)尾進(jìn)行執(zhí)行。
    加了星號(*)的步驟矛绘,可以不用耍休。

上述代碼運(yùn)行結(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

  • 清晰的單元測試框架,提供 TestCase, TestSuite, TextTestRunner 等基本類

  • unittest 是 原生 Python 的一部分

  • unittest 有第三方可用的 HTML 庫货矮,可以輕松的生成 測試報(bào)告

  • 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可選,用來解釋失敗的原因

1.6 為什么需要封裝 Selenium

  • 什么是封裝

    封裝是一個(gè)面向?qū)ο缶幊痰母拍钊妇茫敲嫦驅(qū)ο缶幊痰暮诵膶傩运尴。ㄟ^將代碼內(nèi)部實(shí)現(xiàn)進(jìn)行密封和包裝,從而簡化編程赖捌。對Selenium進(jìn)行封裝的好處主要有如下三個(gè)方面:

  • 使用成本低
    1. 不需要要求所有的測試工程師會(huì)熟練使用Selenium祝沸,而只需要會(huì)使用封裝以后的代碼
    2. 不需要對所有的測試工程師進(jìn)行完整培訓(xùn)。也避免工作交接的成本越庇。
    3. 測試人員使用統(tǒng)一的代碼庫
  • 維護(hù)成本低
    1. 通過封裝罩锐,在代碼發(fā)生大范圍變化和遷移的時(shí)候,不需要維護(hù)所有代碼卤唉,只需要變更封裝的部分即可
    2. 維護(hù)代碼不需要有大量的工程師涩惑,只需要有核心的工程師進(jìn)行封裝的維護(hù)即可
  • 代碼安全性
    1. 對作為第三方的Selenium進(jìn)行封裝,是代碼安全的基礎(chǔ)桑驱。
    2. 對于任何的代碼的安全隱患竭恬,必須由封裝來解決,使得風(fēng)險(xiǎn)可控熬的。
    3. 使用者并不知道封裝內(nèi)部的代碼結(jié)構(gòu)痊硕。

1.7 如何封裝

這里面向的用戶是開發(fā)者,有一定基礎(chǔ)的悦析,特別是面向?qū)ο箝_發(fā)基礎(chǔ)的開發(fā)者寿桨。封裝,最簡單直接就是函數(shù)、方法亭螟、類挡鞍。這里不再復(fù)述。

1.8 Page-Object設(shè)計(jì)模式介紹

  • Page-Object設(shè)計(jì)模式的本質(zhì)

    Page Object設(shè)計(jì)模式是Selenium自動(dòng)化測試項(xiàng)目的最佳設(shè)計(jì)模式之一预烙,強(qiáng)調(diào)測試墨微、邏輯、數(shù)據(jù)和驅(qū)動(dòng)相互分離扁掸。

    Page Object模式是Selenium中的一種測試設(shè)計(jì)模式翘县,主要是將每一個(gè)頁面設(shè)計(jì)為一個(gè)Class,其中包含頁面中需要測試的元素(按鈕谴分,輸入框锈麸,標(biāo)題等),這樣在Selenium測試頁面中可以通過調(diào)用頁面類來獲取頁面元素牺蹄,這樣巧妙的避免了當(dāng)頁面元素id或者位置變化時(shí)忘伞,需要改測試頁面代碼的情況。當(dāng)頁面元素id變化時(shí)沙兰,只需要更改測試頁Class中頁面的屬性即可氓奈。

    它的好處如下:

  • 集中管理元素對象,便于應(yīng)對元素的變化
  • 集中管理一個(gè)page內(nèi)的公共方法鼎天,便于測試用例的編寫
  • 后期維護(hù)方便舀奶,不需要重復(fù)的復(fù)制和修改代碼

具體的做法如下:

  1. 創(chuàng)建一個(gè)頁面的類
  2. 在類的構(gòu)造方法中,傳遞 WebDriver 參數(shù)斋射。
  3. 在測試用例的類中育勺,實(shí)例化頁面的類,并且傳遞在測試用例中已經(jīng)實(shí)例化的WebDriver對象绩鸣。
  4. 在頁面的類中怀大,編寫該頁面的所有操作的方法
  5. 在測試用例的類中,調(diào)用這些方法
  • Page 如何劃分

    一般通過繼承的方式呀闻,進(jìn)行按照實(shí)際Web頁面進(jìn)行劃分

  • Page-Object 類如何實(shí)現(xiàn)

    實(shí)現(xiàn)的示例

    • Page 基類

      • 設(shè)計(jì)了一個(gè)基本的 Page類化借,以便所有的頁面進(jìn)行繼承,該類標(biāo)明了一個(gè)sub page類的基本功能和公共的功能捡多。
      • 全局變量: self.base_driver蓖康,讓所有的子類都使用的。
      # 基類的變量垒手,所有繼承的類蒜焊,都可以使用
      base_driver = None
                          
      
      • 構(gòu)造方法:

      • 傳遞 driver的構(gòu)造方法

      # 方法
      def __init__(self, driver: BoxDriver):
          """
          構(gòu)造方法
          :param driver: ":BoxDriver" 規(guī)定了 driver 參數(shù)類型
          """
          self.base_driver = driver
      
      
      • 私有的常量:存放元素的定位符
    ```python
    LOGIN_ACCOUNT_SELECTOR = "s, #account"
    LOGIN_PASSWORD_SELECTOR = "s, #password"
    LOGIN_KEEP_SELECTOR = "s, #keepLoginon"
    LOGIN_SUBMIT_SELECTOR = "s, #submit"
    LOGIN_LANGUAGE_BUTTON_SELECTOR = "s, #langs > button"
    LOGIN_LANGUAGE_MENU_SELECTOR = "s, #langs > ul > li:nth-child(%d) > a"
    LOGIN_FAIL_MESSAGE_SELECTOR = "s, body > div.bootbox.modal.fade.bootbox-alert.in > div > div > div.modal-body"
    
    ```
    - 成員方法:                    
    - 每個(gè)子類都需要的系統(tǒng)功能:

        - open

            ```pypthon
            def open(self, url):
                """
                打開頁面
                :param url:
                :return:
                """
                self.base_driver.navigate(url)
                self.base_driver.maximize_window()
                sleep(2)
            
            ```

    - 所有子類(頁面)都具有的業(yè)務(wù)功能                            
        - select\_app
        - logout
- Sub Pages(s)子類
        
    - 具體的頁面的類,定義了某個(gè)具體的頁面的功能
    - 必須繼承基類
        
        ```
        class MainPage(BasePage):            
        ```            
    - 特定頁面的業(yè)務(wù)
    - 使用基類的 `self.base_driver` 成員變量
- Tests 類

    - 這部分描述的是具體的測試用例科贬。
    - 聲明全局變量            
        ```
        base_driver = None
        base_url = None
        main_page = None
        
        ```

    - 調(diào)用各種頁面(pages)
        
        
        - 實(shí)例化Page
                
            ```python
            self.main_page = MainPage(self.base_driver)
            
            ```
            
        - 使用page的對象泳梆,調(diào)用成員方法                    
        
            ```python
            self.main_page.open(self.base_url)
            self.main_page.change_language(lang)
            
            ```

2. 構(gòu)建測試方案

2.1 數(shù)據(jù)驅(qū)動(dòng)在自動(dòng)化測試中的應(yīng)用

  • 什么是數(shù)據(jù)驅(qū)動(dòng)

    主要的數(shù)據(jù)驅(qū)動(dòng)方式有兩種:

  • 通過 文本文件或者 Excel 文件存儲(chǔ)數(shù)據(jù)鳖悠,并通過程序讀取數(shù)據(jù),遍歷所有的行
  • 通過數(shù)據(jù)庫存儲(chǔ)數(shù)據(jù)优妙,并通過程序和 SQL 腳本讀取數(shù)據(jù)乘综,遍歷所有的行

通過 CSV 文件 或者 MySQL 數(shù)據(jù)庫,是主流的數(shù)據(jù)驅(qū)動(dòng)方式套硼。當(dāng)然數(shù)據(jù)驅(qū)動(dòng)也可以結(jié)合單元測試框架的參數(shù)化測試進(jìn)行編寫(此部分本文不做具體描述)卡辰。

無論使用了 哪一種(CSV 或者 MySQL),讀取數(shù)據(jù)后都要進(jìn)行遍歷操作邪意。

  • 使用 csv
```python
import csv

csv_file = open("xxx.csv", "r", encoding="utf8")
csv_data = csv.reader(csv_file)
for row in csv_data:
    # 進(jìn)行測試
    # 使用字典類型
    data_to_test = {
    "key1": row[0],
    "key2": row[1]
    }

csv_file.close()

```
  • 使用 MySQL
```python
import pymysql

connect = pymysql.connect(host="xx", port=3306, user="root", passwd="xxx", db="xx")
cur = connect.cursor()
cur.execute("SELECT...")
mysql_data = cur.fetchall()
for row in mysql_data:
    # 進(jìn)行測試
    # 使用字典類型
    data_to_test = {
    "key1": row[0],
    "key2": row[1]
    }
    
cur.close()
connect.close()

```
  • 需要掌握的知識點(diǎn):

    1. python的字典類型 dict 類型
    2. python的讀寫文件
    3. python的讀寫數(shù)據(jù)庫
    4. for循環(huán)
    5. 注意資源的釋放
      1. 關(guān)閉數(shù)據(jù)庫游標(biāo)和連接
      2. 關(guān)閉文件

2.2 測試方案的編碼實(shí)現(xiàn)

  • main.py 測試入口
  • runner.py 測試運(yùn)行器
  • cases 測試用例
  • pages 測試頁面
  • base 底層封裝與驅(qū)動(dòng)

2.3 測試報(bào)告的生成

  • 如何生成測試報(bào)告

  • 測試報(bào)告的種類

  • HTML 測試報(bào)告的生成

    HTML測試報(bào)告需要引入HTMLTestRunner

    HTMLTestRunner是基于Python2.7的九妈,我們的課程講義基于Python3.x,那么需要對這個(gè)文件做一定的修改雾鬼。

    測試的示例代碼如下

```python
# 聲明一個(gè)測試套件
suite = unittest.TestSuite()
# 添加測試用例到測試套件
suite.addTest(RanzhiTests("test_ranzhi_login"))

# 創(chuàng)建一個(gè)新的測試結(jié)果文件
buf = open("./result.html", "wb")

# 聲明測試運(yùn)行的對象
runner = HTMLTestRunner.HTMLTestRunner(stream=buf,
                                        title="Ranzhi Test Result",
                                        description="Test Case Run Result")
# 運(yùn)行測試萌朱,并且將結(jié)果生成為HTML
runner.run(suite)

# 關(guān)閉文件輸出
buf.close()
```  

From:測試/selenium自動(dòng)化測試基礎(chǔ)-www.9ong.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市呆贿,隨后出現(xiàn)的幾起案子嚷兔,更是在濱河造成了極大的恐慌,老刑警劉巖做入,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異同衣,居然都是意外死亡竟块,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門耐齐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浪秘,“玉大人,你說我怎么就攤上這事埠况∷市” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵辕翰,是天一觀的道長夺衍。 經(jīng)常有香客問我,道長喜命,這世上最難降的妖魔是什么沟沙? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮壁榕,結(jié)果婚禮上矛紫,老公的妹妹穿的比我還像新娘。我一直安慰自己牌里,他們只是感情好颊咬,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般喳篇。 火紅的嫁衣襯著肌膚如雪缓呛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天杭隙,我揣著相機(jī)與錄音哟绊,去河邊找鬼。 笑死痰憎,一個(gè)胖子當(dāng)著我的面吹牛票髓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播铣耘,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼洽沟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蜗细?” 一聲冷哼從身側(cè)響起裆操,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎炉媒,沒想到半個(gè)月后踪区,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吊骤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年缎岗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片白粉。...
    茶點(diǎn)故事閱讀 38,569評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡传泊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鸭巴,到底是詐尸還是另有隱情眷细,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布鹃祖,位于F島的核電站溪椎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏惯豆。R本人自食惡果不足惜池磁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望楷兽。 院中可真熱鬧地熄,春花似錦、人聲如沸芯杀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至却特,卻和暖如春扶供,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背裂明。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工椿浓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人闽晦。 一個(gè)月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓扳碍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親仙蛉。 傳聞我的和親對象是個(gè)殘疾皇子笋敞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評論 2 348