面試準備——(三)Selenium面試題總結

1、Selenium基本知識

1. 什麼是Selenium?

Selenium是瀏覽器自動化工具,主要用來Web的自動化測試,以及基於Web的任務管理自動化。它支持的語言有:python、Java、ruby、JavaScript等,而且幾乎能在主流的瀏覽器上運行。css

Selenium2.0、Selenium3.0主要由三大部分組成:SeleniumIDE、Selenium WebDriver、Selenoium Grid。html

  • Selenium IDE錄製和回放腳本,能夠模擬用戶對頁面的真實操做,區別於其餘工具:是經過攔截http請求
    • 通常只把錄製腳本看成一個輔助功能,由於一個UI節點的細微變化,均可能致使自動化測試工具沒法識別,當測試項目項目大時,定位、更新十分困難。
    • 其次,錄製的腳本有時候人工難以理解。
  • Selenium Grid實如今多臺機器上、和異構環境中並行執行測試用例。並行執行不只節省時間,並且能夠同時在不一樣的瀏覽器、平臺上運行自動化測試腳本。
  • Selenium Web Driver:針對各個瀏覽器而開發,經過原生瀏覽器支持或者擴展(Chrome webDrive、FireFox WebDriver)直接控制瀏覽器

    VS Selenium RC(Selenium1.0):在瀏覽器中運行javaScript,使用瀏覽器內置的JavaScript來翻譯和執行selensejava

Web Driver原理python

webDriver是按照client/server模式設計的。client是咱們的測試腳本,發送請求;server就是打開的瀏覽器,用來接收client的請求並做出響應。web

具體的工做流程:ajax

  1. webDriver打開瀏覽器並綁定到指定端口。啓動的瀏覽器做爲遠程服務器remote server
  2. client經過CommandExecuter發送http請求給遠程服務器的偵聽端口(the wire protocal)
  3. 遠程服務器根據原生的瀏覽器組件來轉化爲瀏覽器的本地(native)調用

web Driver用到的協議設計模式

  1. 打開瀏覽器時:HTTP協議
  2. client端發送http請求到遠程服務器的偵聽端口:the wire protocol

其中:瀏覽器

  • 有線協議:指的是從點到點獲取數據的方式,是應用層的協議。
  • HTTP協議:是用於從服務器傳輸超文本標記語言HTML到客戶端的通訊協議。是一個應用層協議,由請求/響應構成,是一個標準的客戶/服務器模式。是一個無狀態的協議。(無狀態:對事務沒有記憶能力,不會保存此次傳輸的信息——節約內存)

2. Selenium的特色有:

  • 支持錄製和回放(Selenium IDE)
  • 經過WebDriver,直接控制瀏覽器,而不是經過攔截HTTP請求,實現真正模仿了用戶的操做;同時使用WebDriver可以靈活的獲取頁面元素(WebDriver),而且提供執行JS的接口
  • 可以分佈式運行在不一樣機器和異構環境中(不一樣瀏覽器)

 

3. Selenium的內部運行機制?如何可以跨瀏覽器使用?——WebDriver原理(&RC原理)

1)RC原理安全

在Selenium1.0中,是經過Selenium RC服務器做爲代理服務器去訪問應用從而達到測試的目的。ruby

Selenium RC分爲三個部分,Launcher、HttpProxy、Core。

  • Launcher用於啓動瀏覽器,把Selenium Core加載到瀏覽器中,而且把瀏覽器的代理設置爲Selenium Server的Http Proxy。
  • Core是一堆JavaScript的集合,因此本質至關於運行這些JavaScript函數來實現對Html頁面的操做。——這也是爲何能夠運行在幾乎全部主流的瀏覽器上。

然而直接運行JavaScript會有極大的安全漏洞,因此會受到「同源限制」,在這個基礎上,Selenium2.0引入了WebDriver。

2)Web Driver原理

webDriver是按照client/server模式設計的。client是咱們的測試腳本,發送請求;server就是打開的瀏覽器,用來接收client的請求並做出響應。

具體的工做流程:

  1. webDriver打開瀏覽器並綁定到指定端口。啓動的瀏覽器做爲遠程服務器remote server
  2. client經過CommandExecuter發送http請求給遠程服務器的偵聽端口(the wire protocal)
  3. 遠程服務器根據原生的瀏覽器組件來轉化爲瀏覽器的本地(native)調用

因此web Driver用到的協議

  1. 打開瀏覽器時:HTTP協議
  2. client端發送http請求到遠程服務器的偵聽端口:the wire protocol

其中:

  • 有線協議:指的是從點到點獲取數據的方式,是應用層的協議。
  • HTTP協議:是用於從服務器傳輸超文本標記語言HTML到客戶端的通訊協議。是一個應用層協議,由請求/響應構成,是一個標準的客戶/服務器模式。是一個無狀態的協議。(無狀態:對事務沒有記憶能力,不會保存此次傳輸的信息——節約內存)

4. 如何提升selenium腳本的執行速度?

1)優化測試用例。

  • 儘量不用sleep、減小使用implicityWait,而使用WebDriverWait/FluentWait,這樣能夠優化等待時間
  • 減小沒必要要的操做步驟。

2)使用Selenium grid,經過testNG實現併發執行。 

說到這裏,在編寫測試用例的時候,必定要實現鬆耦合,而後再服務器容許的狀況下,儘可能設置多線程實現併發運行。

3)設置等待時間、中斷頁面加載。若是頁面加載內容太多,咱們能夠查看一下加載緩慢的緣由,在不影響測試的狀況下,能夠設置超時時間,中斷頁面加載。

 

5. 提升自動化腳本穩定性——減小誤報

1. 誤報問題。咱們一旦測試用例沒有經過,則沒法完成每日自動構建,可是其實這些測試用例是正確,也不存在BUG。

2. 主要的緣由頁面尚未加載完成,咱們就開始進行元素定位。

3. 解決方法重試機制。利用遞歸封裝了一個等待元素的方法。其中,設置最大等待時間爲1s,輪詢時間爲50ms,這個方法會不斷輪詢,直到方法執行成功或者超過設置的最大等待時間。在咱們最好的一次實踐中,咱們把一個測試用例的誤報率從10%下降到0,而且執行時間從原先的45秒下降到33秒。

 

6. 如何設計高質量自動化腳本

1. 使用四層結構實現業務邏輯、腳本、數據分離。

2. 使用PO設計模式,將一個頁面用到的元素和操做步驟封裝在一個頁面類中。若是一個元素定位發生了改變,咱們只用修改這個頁面的元素屬性

3. 對於頁面類的方法,咱們儘可能從客戶的正向邏輯去分析,方法中是一個獨立場景,例如:登陸到退出,並且不要想着把全部的步驟都封裝在一個方法中。

4. 測試用例設計中,減小測試用例之間的耦合度。

 

7. 你以爲自動化測試最大的缺陷是什麼?

1. 一旦項目發生變化,測試用例就須要改進,工做量大。

2. 驗證的範圍有限,操做更加複雜,好比說簡單的一個驗證驗證碼,若是是人工識別很快就能夠輸入,可是自動化測試中會增添不少困難。那麼這個時候速度也不如人工。

3. 不穩定

4. 可靠性不強

5. 成本與收益

 

2、元素定位

1. ElementNotVisible

1. selenium中hidden或者是display = none的元素是否能夠定位到?——用Js修改display = block

1)區分:display= none VS hidden

共同點:都把網頁中的元素給隱藏起來了;在selenium中沒法直接定位

區別:none:不爲隱藏的對象保留其物理空間 看不見/摸不着

   hidden仍佔有空間 看不見/摸得着

1. 處理 display:none

頁面主要經過"dislay:none"來控制整個下拉框不見。若是直接操做:

from selenium.webdriver.support.ui import WebDriverWait
from selenium import webdriver
from selenium.webdriver.support.select import Select
import os

driver = webdriver.Firefox(executable_path="/Users/lesley/Downloads/geckodriver")
file_path = 'file:///' + os.path.abspath('test.html')
driver.get(file_path)

select = driver.find_elements('select')
Select(select).select_by_value('volvo')
WebDriverWait()

driver.quit()

報錯:ElementNotVisible

咱們能夠通過JavaScript來修改display的值

js = 'document.querySelectortAll('select')[0]'.style.display='block';'

select = driver.find_element_by_tag_name('select')
Select(select).select_by_value('Opel')

document.querySelectAll('select'):選擇全部的select;[0]表示第幾個

style.display='block':修改display=block,表示可見

 

2. NoSuchElementException

首先,判斷一個元素是否顯示:is_displayed()

1. Frame/IFrame緣由定位不到元素——switch_to_iframe

frame是指:頁面中嵌入另外一個頁面,而webdriver每次只能在一個頁面識別,所以須要先定位到相應的frame,對那個頁面裏的元素進行定位。

此時,有兩種方式:

1. iframe存在id 或者name。

首先用switch_to_frame('x-URS-iframe')定位到這個iframe,而後再定位這個iframe中的元素

driver=webdriver.Firefox()
driver.get(r'http://www.126.com/')
driver.switch_to_frame('x-URS-iframe')  #需先跳轉到iframe框架
username=driver.find_element_by_name('email')
username.clear()

2.  iframe不存在name/id。

先定位到iframe,再swith_to_frame

#先定位到iframe
elementIframe= driver.find_element_by_class_name('APP-editor-iframe')
#再將定位對象傳給switch_to_frame()方法
driver.switch_to_frame(elementIframe) 

若是完成操做後,能夠經過switch_to_parent_content()方法跳出當前iframe,或者還能夠經過switch_to_default_content()方法跳回最外層的頁面。

 

2. 頁面沒有加載出來,就對頁面中元素進行操做。

——設置等待時間直到元素出現(WebDriveWait(driver,10).until(lambda x:x.find_elemetn_by_id('someId').is_displayed)

獲取頁面加載狀態

document.readyState

例如:當Selenium點擊一個按鈕打開一個彈窗,彈窗尚未打開的時候,咱們就要使用彈窗上一個按鈕。

——>解決:設置等待最大等待時間

1)sleep():設置固定休眠時間

2)implicity_wait():是webDriver提供的一個超時等待,隱的等待一個元素被發現,或者一個命令完成

3)WebDriverWait():一樣也是WebDriver提供的方法。在設置時間內,默認每隔一段時間檢測一次當前頁面元素是否存在,若是超出指定時間檢測不到則拋出異常。

WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)

# driver:WebDriver的驅動程序
# timeout:最長超時時間,默認以秒爲單位
# poll_frequency:休眠時間的間隔時間
# ignore_exception():超時後的異常信息,默認狀況下拋出NoSuchElementException

一般與until()或者until_not()方法配合使用

until(method, message="")
# 調用該方法提供的驅動程序做爲一個參數,直到返回值不爲FALSE

until_not(method, message="")
# 調用該方法提供的驅動程序做爲一個參數,直到返回值爲FALSE

 舉例:

 1 from selenium.webdriver.support.ui import WebDriverWait
 2 
 3 from selenium import webdriver
 4 import time
 5 
 6 driver = webdriver.Firefox(executable_path="/Users/lesley/Downloads/geckodriver")
 7 driver.get("https://www.baidu.com/")
 8 
 9 # 添加WebDriverWait
10 element = WebDriverWait(driver, 10).until(lambda driver:driver.find_element_by_id("kw"))
11 is_disappeared = WebDriverWait(driver, 5).until_not(lambda x: x.find_element_by_id("someId").is_displayed())
12 element.send_keys("sbw")
13 
14 # 添加智能等待
15 driver.implicitly_wait(5)
16 driver.find_element_by_id("su").click()
17 
18 # 添加固定時間等待
19 time.sleep(5)
20 
21 driver.quit()

4)WaitFor:配合setTimeout,設置最大等待時間,而後輪詢查看是否在指定時間內找到該元素。

1 def waitfor(getter, timeout=3, interval=0.5, *args):
 2     starttime = datetime.datetime.now()
 3     while True:
 4         if getter(args):
 5             return
 6         else:
 7             runtime = datetime.datetime.now() - starttime
 8             print runtime
 9             if runtime.seconds >= timeout:
10                 raise Exception
11             time.sleep(interval)
12     
13 current_value = 1    
14 def testgetval(args):
15     wanted_value = args[0]
16     global current_value
17     current_value += 1
18     print '%d, %d' % (wanted_value, current_value)
19     return current_value > wanted_value    
20         
21 if __name__ == '__main__':
22     waitfor(testgetval, 1, 0.3, 2)
23     print '======================='
24     waitfor(testgetval, 1, 0.3, 8)

 

3. 動態ID沒法定位元素——1)直接使用Xpath相對路徑;2)根據部分元素定位

如何判斷是動態ID?

簡單,通常看到元素屬性裏有拼接一串數字的,就頗有多是動態的。想要分辨,刷新一下瀏覽器再看該元素,屬性值中的數字串改變了,便是動態屬性了。

<div id="btn-attention_2030295">...</div>

方式(一)根據相對路徑

http://blog.csdn.net/huilan_same/article/details/52541680

方式(二)根據部分元素屬性定位

driver.find_element_by_xpath("//div[contains(@id, 'btn-attention')]")
driver.find_element_by_xpath("//div[starts-with(@id, 'btn-attention')]")
driver.find_element_by_xpath("//div[ends-with(@id, 'btn-attention')]")  # 這個須要結尾是‘btn-attention’

 

4. 二次定位,如彈出登錄框

——層級定位

# 點擊打開菜單欄
driver.find_element_by_xpath("//*[@id='sidebar-collapse']/i").click();

# 點擊菜單塊
driver.find_element_by_xpath("//*[@id='sidebar']/div[1]/ul/li[2]/a").click();

# 點擊「待辦中心」
driver.find_element_by_linkText("待辦案件").click();

 

5. 有兩個屬性相同的元素,可是其中一個是不可見的。——找到符合這個屬性且style屬性中display=none的元素

driver.find_element_by_xpath("//span[contains(@id, 'sbw')] and not(contains[@style, 'display:none'])")

 

6. Xpath描述錯誤

1)經過屬性定位元素

find_element_by_xpath("//標籤名[@屬性='屬性值']")

例如:

# id屬性:
driver.find_element_by_xpath("//input[@id='kw']")

# class屬性:
driver.find_element_by_xpath("//input[@class='s_ipt']")

# name屬性:
driver.find_element_by_xpath("//input[@name='wd']")

# maxlength屬性:
driver.find_element_by_xpath("//input[@maxlength='255']")

2)經過標籤名

driver.find_elment_by_xpath('//input')

3)父子定位元素

查找有父親元素的標籤名爲span,它的全部標籤名叫input的子元素

driver.find_element_by_xpath("//span/input") 

4)經過元素內容

例如:

<p id="jgwab">
    <i class="c-icon-jgwablogo"></i>
    京公網安備11000002000001號
</p>

則咱們能夠定位:

# 根據text()
driver.find_elment_by_xpath('//p[contains(text(), '京公網')]')

# 根據class
driver.find_elment_By_xpath('//p[contains(@class, '京公網')]')

5. 組合定位元素

//父元素標籤名/標籤名的屬性值:指的是span下的input標籤下class屬性爲s_ipt的元素

driver.find_element_by_xpath("//span/input[@class='s_ipt']")

6. 多個屬性組合定位

指的是input標籤下id屬性爲kw且name屬性爲wd的元素

driver.find_element_by_xpath("//input[@class='s_ipt' and @name='wd']")

指的是p標籤下內容包含「京公網」且id屬性爲jgwab的元素

find_element_by_xpath("//p[contains(text(),'京公網') and @id='jgwab']") 

 

3、常見控件使用

1. link、button

element.click()

2. Textbox

element.send_keys('test')

3. Upload

element.send_keys('D\test.txt')

4. Mouse Event——ActionChains()

#雙擊
ActionChains(driver).double_click(element).perform()

#右擊
ActionChains(driver).context_click(element).perform()

#拖動
ActionChains(driver).drag_and_drop(element).perform()

#懸停
ActionChains(driver).move_to_element(element).perform()

5. DropDown:

1)<Select>標籤的下拉菜單

from selenium.webdriver.support.ui import Select

Select(driver.find_element_by_id('gender')).select_by_value('2')
Select(driver.find_element_by_id('gender')).select_by_index(1)
Select(driver.find_element_by_id('gender')).select_by_visible_text('Male')

2)非<select>標籤——層級定位

Dropdown1 = driver.find_element_by_id(‘id’) #先定位到dropdown

Dropdown1.find_element_by_id(「li2_input_2」) #再定位到dropdown中的值

 3)使用js實現:

 

6. Alert

driver.switch_to_alert().accept() # 接收彈窗
driver.switch_to_alert().dismiss() # 取消彈窗

# 獲取彈窗的文本消息
Message = driver.switch_to_alert().text

7. Window

driver.refresh() # 刷新

driver.back() # 後退

driver.forward() # 前進

driver.maximize_window() # 最大化

driver.set_window_size(100,200) # 設置窗口大小

driver.switch_to.window(searchwindow)

8. frame

driver.switch_to.frame(ReferenceFrame)

driver.switch_to.parent_frame()  # frame須要一級一級切

driver.switch_to.default_content() # 返回最外層

 

4、等待

1. 顯示等待——WebDriverWait()

:等到某個條件成立時繼續執行。每隔一段時間檢測,超出最大時間則拋出異常

is_disappeared = WebDriverWait(driver, 5).until_not(lambda x: x.find_element_by_id("someId").is_displayed())

 

2.  隱式等待——implicitly_wait()

隱式等待中的時間並不是一個固定的等待時間,它並不影響腳本的執行速度。好比進行某元素的定位時,若是元素能夠定位就繼續執行,若是目前定位不到就以輪詢的方式持續判斷該元素是否被定位到,若是超過規定的時間還沒定位到就拋出異常。

driver.implicitly_wait(20)

 

3. 強制等待——sleep()

from time import sleep
sleep(5)

 

 5、測試模型

 

3. selenium中如何保證操做元素的成功率?也就是說如何保證我點擊的元素必定是能夠點擊的?

  1. 首先經過封裝find方法,實現wait_for_element_ispresent,這樣在對元素進行操做以前保證元素被找到,進而提升成功率。(WebDriverWait)
  2. 在對頁面進行click以前,先滾動到該元素(經過Js封裝),避免在頁面未加在完成前或是在下拉以後才能顯示。

 

4. Selenium有幾種定位方式?你最偏心哪種,爲何?

Selenium有八種定位方式

  1. 與name有關的有三種:name、class_name、tag_name
  2. 與link相關的有兩種:link_text、partitial_link_text
  3. 與id有關:id
  4. 全能選手:xpath、css_selector

若是存在id,我必定使用Id,由於簡單方便,定位最快。其次是Xpath,由於不少狀況下html標籤的屬性不夠規範,沒法惟必定位。Xpath是經過相對位置定位

 

5. 如何去定位頁面上動態加載的元素?

首先觸發動態事件,而後再定位。若是是動態菜單,則須要層級定位。——JS實現(對動態事件封裝)

http://www.cnblogs.com/tobecrazy/p/4817946.html 

6. 如何去定位屬性動態變化的元素?

屬性動態變化也就是指該元素沒有固定的屬性值能夠經過:

  1. JS實現,
  2. 經過相對位置來定位,好比xpath的軸,paren/following-sibling/percent-sibling

http://www.cnblogs.com/zhaozhan/archive/2009/09/10/1564332.html

 

8. 點擊連接之後,selenium是否會自動等待該頁面加載完畢?

不會的。因此有的時候,當selenium並未加載完一個頁面時再請求頁面資源,則會誤報不存在此元素。因此首先咱們應該考慮判斷,selenium是否加載完此頁面。其次再經過函數查找該元素。

  

11. 如何在定位元素後高亮元素(以調試爲目的)?

 

12. 什麼是斷言?VS 驗證

1)斷言(assert):測試將會在檢查失敗時中止,並不運行後續的檢查

優勢:能夠直截了當的看到檢查是否經過

缺點:檢查失敗後,後續檢查不會執行,沒法收集那些檢查結果狀態

2)驗證(vertify):將不會終止測試

缺點:你必須作更多的工做來檢查測試結果:查看日誌——>耗時多,因此更偏向於斷言

# 斷言驗證:百度搜索的標題是否爲:百度搜索
# import unittest

try:
    self.assertEqual(u"百度搜素", driver.title)
except AssertionError as e:
    print("Cannot find this title")

3)Waitfor:用於等待某些條件變爲真。可用於AJAX應用程序的測試。

若是該條件爲真,他們將當即成功執行。若是該條件不爲真,則將失敗並暫停測試。直到超過當前所設定的超時時間。 通常跟setTimeout時間一塊兒用。

 

經常使用的斷言:

 1 assertLocation          # 判斷當前是在正確的頁面
 2 assertTitle             #檢查當前頁面的title是否正確
 3 assertValue             # 檢查input的值, checkbox或radio,有值爲」on」無爲」off」
 4 assertSelected          # 檢查select的下拉菜單中選中是否正確
 5 assertSelectedOptions   # 檢查下拉菜單中的選項的是否正確
 6 assertText              # 檢查指定元素的文本
 7 assertTextPresent       # 檢查在當前給用戶顯示的頁面上是否有出現指定的文本
 8 assertTextNotPresent    # 檢查在當前給用戶顯示的頁面上是否沒有出現指定的文本
 9 assertAttribute         # 檢查當前指定元素的屬性的值
10 assertTable             # 檢查table裏的某個cell中的值
11 assertEditable          # 檢查指定的input是否能夠編輯
12 assertNotEditable       # 檢查指定的input是否不能夠編輯
13 assertAlert             # 檢查是否有產生帶指定message的alert對話框
14 waitForElementPresent   # 等待檢驗某元素的存在。爲真時,則執行。

 

13. 若是有一個按鈕,點擊該按鈕後發出一個ajax call,而後獲得返回結果後內容顯示到新彈出的一個layer中。在寫腳本的時候,點擊這個按鈕動做是否能夠用clickAndWait命令?若是不行,怎麼解決?

不可以。Ajax是一種支持動態改變用戶界面元素的技術。在Ajax驅動的應用程序中,數據能夠從應用服務器檢索,而後顯示在頁面上,而不須要加載整個頁面,只有一小部分頁面或者元素自己被從新加載。

因此不可以使用ClickAndWait,由於Ajax call不會刷新整個頁面,clickAndWait命令會由於等待頁面從新加載而出現time out。

也就是說最大的麻煩是判斷Ajax調用是否結束。能夠用click + pause完成

使用JQuery進行輔助測試:http://www.cnblogs.com/nbkhic/archive/2011/10/23/2221729.html

 

 

其中,去哪兒網的題目以下:

1、 UI自動化測試

Qunar機票搜索場景

1) 訪問Qunar機票首頁http://flight.qunar.com,選擇「單程」,輸入出發、到達城市,選擇today+7往後的日期,點「搜索」,跳轉到機票單程搜索列表頁。

2) 在列表頁停留1分鐘,至到頁面上出現「搜索結束」。

3) 若是出現航班列表,對於出現「每段航班均需繳納稅費」的行隨機點選「訂票」按鈕,在展開的列表中會出現「第一程」、 「第二程」;對於沒有出現「每段航班均需繳納稅費」的行隨機點選「訂票」按鈕,在展開的列表底部中會出現「報價範圍」

4) 若是不出現航班列表,則頁面會出現「該航線當前無可售航班」

請使用maven建立java工程,引入Selenium框架,編寫WebUI代碼,實現上述人工操做和驗證。要求能隨機驗證100個城市對的3個月內的任意搜索條件。

 參見答案:http://www.cnblogs.com/tobecrazy/p/4752684.html

不少人可能第一步就卡住了,怎麼選擇7天之後的日期呢?

實際上很簡單,直接在輸入框裏輸入就行了。由於selenium支持的語言不少,這裏就用js寫一下。你們用selenium執行這段js就能夠搞定了。

var date = new Date();
date.setDate(date.getDate() + 7);

var a_week_later = date.getFullYear() + '-' (date.getMonth()+1) + '-' + date.getDate();
$('input[name=fromDate]').val(a_week_later);

參考答案: http://www.cnblogs.com/tobecrazy/p/5873288.html                                     

相關文章
相關標籤/搜索