WebDriver--定位元素的8種方式


WebDriver--定位元素的8種方式

在UI層面的自動化測試開發中,元素的定位與操作是基礎,也是經常遇到的困難所在。webdriver提供了8種定位:

id定位:

find_element_by_id("id值");id屬性是唯一的

driver.find_element_by_id("loginName").clear()#用戶名輸入框的id屬性
driver.find_element_by_id("loginName").send_keys("admin")
driver.find_element_by_id("pwdTip").send_keys(Keys.TAB)#密碼輸入框的id屬性
driver.find_element_by_id("pwdTip").send_keys("111111")

name定位:

元素的名稱,find_element_by_name("name值");name屬性值在當前頁面可以不唯一

1 driver.find_elements_by_name("PeriodName")[1].click()#選擇學段:初中
2 driver.find_elements_by_name("SubjectName")[0].click()#選擇學科:語文

find_elements_by_name("PeriodName")是因為當前頁面有一組radiobutton的name值是PeriodName,所以可以用定位一組元素的方法findElements,定位出來的是結果一個list

class定位:

元素的類名,find_element_by_class_name("class值")

driver.find_elements_by_class_name("u-btn-levred")[0].click()#選擇年級:七年級

tag定位:

頁面html文檔下的各種標簽,find_element_by_tag_name("input");

tag往往用來定義一類功能,所以通過tag識別某個元素的概率很低。任意打開一個頁面,都會發現大量的<div><input><a>等tag,所以tag name定位很少用

link定位:

專門用來定位文本鏈接,find_element_by_link_name("text");

driver.find_element_by_link_text(u"退出").click()#頁面右上方的一些個人操作,比如退出、個人中心、消息通知等

partial link定位:

是對link定位的一種補充,當鏈接上的文本內容比較長的時候,可以取文本的一部分進行定位,當然這部分可以唯一地標識這個鏈接

※注:以上的方式稍有局限,且經常頁面沒有id,name這些屬性值,class name重復性較高,link定位有針對性,所以Xpath與Css定位更靈活些。

XPath定位:

find_element_by_xpath("");有多種定位策略,用FirePath插件自動生成的涵蓋以下幾種方式

1)絕對路徑定位:對於沒有id,name、classname不好定位的,這也是我最常用的,因為可以通過Firefox的FirePath插件可以方便的獲取到xpath值

2)利用元素屬性定位:

  find_element_by_xpath(".//*[@id='Title']"),這里是用的id,也可以用元素其他能夠唯一標識的屬性,不局限於id、name、class這些;*代表的是標簽名,不指定時就可以用*代替

3)層級與屬性結合:下圖中就是這種

4)使用邏輯運算符

1 driver.find_element_by_xpath(".//*[@id='divword']/input[7]").click()#登錄
2 driver.find_element_by_xpath("html/body/div[4]/div/div[2]/div/div[3]/a[1]").click()#個人頁面的發布課程操作

CSS定位:

(薄弱,用的很少,但很強大,比xpath簡潔靈活):使用選擇器來為頁面元素綁定屬性,可以靈活地選擇控件的任意屬性;find_element_by_css_selector("");同樣也可以用FirePATH生成css喲!

1)通過class屬性定位:點號(".")表示通過class屬性定位

1 <input class="u-btn mart5" type="submit" onclick="return User.check()" value="登錄">
2 driver.find_element_by_css_selector(".u-btn.mart5").click()

2)通過id屬性定位:("#")表示通過id定位元素

driver.find_element_by_css_selector("#loginName")

3)通過其他屬性定位:("[]"),中括號里的屬性可以唯一標識這個元素就可以;屬性的值可以加引號,也可以不加

1 <input class="u-btn mart5" type="submit" onclick="return User.check()" value="登錄">
2 driver.find_element_by_css_selector("[type=submit]").click()

4)組合定位

平時使用生成的xpath,id,name,classname這些比較多,今天根據最近這段時間的實踐,並參照書上整理了下,發現原來XPath和Css下還有這么多方式,順便拿最近一些代碼試驗了下,有些簡單的css定位能夠成功,有的Firepath生成的並不可用,一些組合定位還需要再研究,是有些難度的。最后記錄一種定位方式,更接近底層實現方式的定位,But書上說webdriver更推薦前面那些寫法,為毛捏?

By定位元素:

  除find_element_by_***這種方式,還有另一套寫法,也就是統一調用find_element()方法,兩個參數,第一個參數是定位的類型,由By提供;第二個參數是定位的具體值

from selenium.webdriver.common.by import By     #使用By這種定位前要將By類導入

find_element(By.ID,"loginName")
find_element(By.NAME,"SubjectName")
find_element(By.CLASS_NAME,"u-btn-levred")
find_element(By.TAG_NAME,"input")
find_element(By.LINK_TEXT,"退出")
find_element(By.PARTIAL_LINK_TEXT,"退")
find_element(By.XPATH,".//*[@id='Title")
find_element(By.CSS_SELECTOR,"[type=submit]")

python+webdriver學習筆記

控制瀏覽器

設置瀏覽器大小:像素點

set_window_size(width,height)

maximize_window() 瀏覽器全屏顯示,不帶參數

控制瀏覽器前進、后退:

driver.forward()

driver.back()

模擬瀏覽器刷新:

driver.refresh()

實例:

from selenium import webdriver  
  
driver = webdriver.Firefox()  
driver.get(r"http://www.baidu.com/")  
  
#參數是像素點寬,高  
driver.set_window_size(800,800)  
print("瀏覽器大小是800px,800px")  
  
driver.find_element_by_link_text("新聞").click()  
driver.back()     #返回前一個頁面  
driver.forward()  #前進前一個頁面  
driver.refresh()  #刷新當前頁面  
driver.find_element_by_css_selector("#ww").send_keys("python3")  
driver.find_element_by_xpath("//*[@class='btn']").click()  
driver.refresh()  #刷新當前頁面  
driver.quit()  

clear()清除文本

send_keys("....") 模擬按鍵輸入

click() 單擊元素,前提是它是可以被單擊的對象。另外click()方法不僅可以用於單擊一個按鈕,它還能可以單擊任何可以單擊的文字、圖片、checkbox、radio、select下拉框等。

submit() 用於提交表單,同樣可以用於提交一個按鈕。

WebElement接口常用方法

submit() 用於提交表單,同樣可以用於提交一個按鈕。

先看例子:

from selenium import webdriver  
  
driver = webdriver.Firefox()  
driver.get(r"http://www.baidu.com/")  
size = driver.find_element_by_name("wd").size  
print(size)      #size屬性,返回元素的尺寸,表單輸入框之類的width、height等  
  
text = driver.find_element_by_id("jgwab").text  
print(text)      #text屬性,獲取元素的文本,可以用力判斷打開的頁面是否是預期的。  
  
attribute = driver.find_element_by_xpath(".//input[@id='kw']").get_attribute('maxlength')  
print(attribute) #get_attribute()方法可以獲取屬性值  
  
result = driver.find_element_by_partial_link_text("京公網安備").is_displayed()  
print(result)   #is_displayed() 元素是否設置可見,可見返回true則false  
  
driver.quit()  

size屬性返回元素尺寸

text屬性返回元素文本

get_attribute()方法獲取屬性值

is_displayed()方法返回該元素是否設置可見

鼠標事件

對鼠標的操作:右擊、雙擊、懸停、鼠標拖動等功能,webdriver中對鼠標的操作的方法封裝在ActionChains類中。

使用前要先導入ActionChains類:

from selenium.webdriver.common.action_chains import ActionChains

ActionChains類提供的鼠標操作常用方法:

  • context_click() 右擊
  • double_click() 雙擊
  • drag_and_drop() 拖動
  • move_to_element() 鼠標懸停
  • perform() 執行所有ActionChains類中存儲的行為,可以理解為對整個操作的提交動作

鼠標右鍵操作

from selenium import webdriver  
from selenium.webdriver.common.action_chains import ActionChains  #導入ActionChains類  
  
driver = webdriver.Firefox()  
driver.get(r"https://yunpan.360.cn/")  
driver.maximize_window ()  
driver.find_element_by_xpath("//*[@name='account']").clear()  
driver.find_element_by_xpath("//*[@name='account']").send_keys("username.com")  
driver.find_element_by_name("password").clear()  
driver.find_element_by_name("password").send_keys("pwd")  
driver.find_element_by_xpath("//*[@id='login']/div/div[2]/form/p[4]/label/input").click()  
driver.find_element_by_xpath("//*[@id='login']/div/div[2]/form/p[5]/input").click()  
  
#定位到需要右擊的元素  
right_click = driver.find_element_by_link_text("jemeter")  
  
#對定位到的元素執行鼠標郵件操作,調用ActionChains類,將瀏覽器驅動driver作為參數傳入,context_click()需要指定元素位置  
ActionChains(driver).context_click(right_click).perform()   

鼠標雙擊操作

double_click()方法模擬鼠標雙擊操作

(單擊查看詳情,雙擊彈出修改頁面就用這個方法模擬)

from selenium import webdriver  
from selenium.webdriver.common.action_chains import ActionChains  
  
driver = webdriver.Firefox()  
driver.get(r"http://www.baidu.com/")  
  
....  
#定位需要雙擊的元素  
double_click = driver.find_element_by_xpath("")  
#對定位到的元素進行雙擊操作  
ActionChains(driver).double_click(double_click).perform()  
  
a = driver.find_element_by_class_name("")  
ActionChains(driver).double_click(a).perform()  

鼠標懸停

move_to_element()方法模擬鼠標懸停

from selenium import webdriver  
import time  
from selenium.webdriver.common.action_chains import ActionChains  
  
driver = webdriver.Firefox()  
driver.get(r"http://www.baidu.com/")  
driver.set_window_size(1000,1000)  
#定位到懸停的元素  
attrible = driver.find_element_by_link_text("設置")  
#對定位到的元素進行懸停操作  
ActionChains(driver).move_to_element(attrible).perform()  
time.sleep(5)  
driver.refresh()  

以上3中鼠標操作用法相同!

鼠標拖放操作

drag_and_drop(source,target) 在源元素上按住鼠標左鍵,然后移動到目標元素上釋放。

  • source 鼠標拖動的源元素
  • target鼠標釋放的目標元素
from selenium import webdriver  
from selenium.webdriver.common.action_chains import ActionChains  
  
driver = webdriver.Firefox()  
driver.get("http://www.baidu.com/")  
#定位元素的初始位置  
source = driver.find_element_by_css_selector("")  
#定位元素的要移動到的位置  
target = driver.find_element_by_name("")  
#執行元素的拖放操作  
ActionChains(driver).drag_and_drop(source,target).perform()  

鍵盤事件

Keys()類提供了鍵盤上按鍵的方法,send_keys()方法可以用來模擬鍵盤輸入,還可以用來輸入鍵盤上的按鍵、組合鍵。

在使用鍵盤按鍵方法前需要先導入keys類:

from selenium.webdriver.common.keys import Keys
實例:

from selenium import webdriver  
from selenium.webdriver.common.keys import Keys  
import time  
  
driver = webdriver.Firefox()  
driver.get(r"http://www.baidu.com/")  
driver.maximize_window()  
driver.find_element_by_name("wd").send_keys("pythonm")  
#刪除多輸入的m  
time.sleep(2)                       #刪除鍵  
driver.find_element_by_name('wd').send_keys(Keys.BACK_SPACE)  
  
  
#輸入空格鍵在輸入“selenium”       #空格鍵  
driver.find_element_by_name("wd").send_keys(Keys.SPACE)  
time.sleep(2)  
driver.find_element_by_name("wd").send_keys("selenium")  
time.sleep(2)  
  
#ctrl+a全選輸入框內容               #Ctrl+a全選  
driver.find_element_by_name("wd").send_keys(Keys.CONTROL,'a')  
time.sleep(2)  
  
#Ctrl+x剪切選中的內容               #Ctrl+x剪切  
driver.find_element_by_name("wd").send_keys(Keys.CONTROL,'x')  
time.sleep(2)  
  
#Ctrl+v粘貼選中的內容               #Ctrl+v粘貼  
driver.find_element_by_name('wd').send_keys(Keys.CONTROL,'v')  
  
#通過輸入enter鍵替代clic()單擊      #enter回車鍵  
driver.find_element_by_name('wd').send_keys(Keys.ENTER)  
driver.quit()  

獲取驗證信息

在自動化用例執行之后,我們可以在頁面上獲取一些信息來證明,用例執行成功還是失敗。

通常用到的驗證信息分別是:text、title、URL

text:獲取標簽對之間的文本信息;
title:獲取當前頁面的標題;
current_url:獲取當前頁面的URL
它們是webdriver的屬性!!!

實例:

from selenium import webdriver  
from time import sleep  
  
driver = webdriver.Firefox()  
driver.get(r"http://yunpan.360.cn")  
  
print("登錄之前:")  
  
#打印打錢頁面的title  
title = driver.title  
print(title)  
  
#打印當前頁面的URL  
now_url = driver.current_url  
print(now_url)  
  
#獲取“歡迎使用360雲盤!”的文本  
text = driver.find_element_by_tag_name("h1").text  
print(text)  
  
#登錄郵箱  
driver.find_element_by_name("account").clear() #name定位  
driver.find_element_by_name("account").send_keys("xxxqq.com")  
driver.find_element_by_xpath("//*[@name='password']").clear() #xpath元素屬性定位  
driver.find_element_by_xpath("//*[@name='password']").send_keys("yxxx36")  
#xpath元素屬性和層級結合定位  
driver.find_element_by_xpath("//div[@id='login']/div/div[2]/form/p[4]/label/input").click()  
driver.find_element_by_xpath("//*[@id='login']/div/div[2]/form/p[5]/input").click()  
sleep(5)  
  
print("登錄郵箱之后:")  
  
#再次打印title  
title = driver.title  
print(title)  
  
#打印當前的URL  
now_url = driver.current_url  
print(now_url)  
  
#獲取登錄后的文本  
text = driver.find_element_by_xpath(".//*[@id='crumb']/div/span").text  
print(text)  

可以把登錄之后的信息存放起來,作為驗證登錄是否成功。加斷言就可可以。

設置元素等待

web應用程序采用AJAX技術時,頁面上的元素不會同時被加載完成,防止定位元素會出現ElementNotVisibleException的錯誤,可以通過設置元素等待防止這種問題出現。

顯式等待

顯式等待使WebDriver等待某個條件成立時繼續執行,否則在達到最大時長拋出超時異常(TimeException)。

顯式等待用到WebDriverWait()類和expected_conditions()類中的方法,使用前需要先導入:

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

顯式等待相當於:在定位某個元素之前檢查該元素是否被加載出來了,until到當前元素被加載到DOM樹中

實例:

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 as EC  
  
driver = webdriver.Firefox()  
driver.get(r"http://www.baidu.com//")  
  
#顯式等待  
#定位第一個元素  
element = WebDriverWait(driver,5,0.5,ignored_exceptions=None).until(  
    EC.presence_of_element_located((By.ID,"kw"))  
    )  
element.send_keys("ptyh")  
#定位第二個元素  
element = WebDriverWait(driver,5,0.5,ignored_exceptions=None).until(  
    EC.presence_of_element_located((By.ID,"su"))  
    )  
element.click()  
driver.quit()  

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

  • driver:瀏覽器驅動
  • timeout:最長超時時間,默認單位是秒
  • poll_frequency:檢測的間隔時間,默認是0.5秒
  • ignored_exceptions:超時后的異常信息,默認拋出NoSuchElementException異常。

WebDriverWait()一般由until()或until_not()方法一起使用:

until(method,message = 'xxx')
until_not(method,message = ‘XXX’)

例子中until()的method是EC.presence_of_element_located((By.Id,"kw"))

expected_conditions()類所提供的預期條件判斷方法還很多!!P97

除了預期類提供的判斷外還可以用is_displayed()方法判斷元素是否可見:

#利用is_displayed()方法判斷元素是否可見  
''''' 
for循環10次每次循環判斷元素的is_diaplayed()狀態 
是否是true,若為true,則break跳出循環;否則sleep(1) 
后繼續循環判斷,知道10次循環結束后,打印“time_out”信息。 
'''  
from selenium import webdriver  
from time import sleep,ctime  
  
driver = webdriver.Firefox()  
driver.get(r"http://www.baidu.com/")  
  
print(ctime())  
for i in range(10):  
    try:  
        element = driver.find_element_by_id("kw33")  
        if element.is_displayed():  
            break  
    except:pass  
    sleep(1)  
else:  
    print("time_out!")  
driver.close()  
print(ctime())  

隱式等待

隱式等待是通過一定的時長等待頁面上某元素加載完成。如果超出了設置的時長元素還沒有加載,會拋出NoSuchElementException異常。

webdriver的implicitly_wait()方法來實現隱式等待,默認設置為0。

隱式等待使用到拋出異常,NoSuchElementException異常需要先導入:

from selenium .common.exceptions import NoSuchElementException

implicitly_wait()方法由webdriver提供。

實例:

from selenium import webdriver  
#from selenium.common.exceptions import NoSuchElementException  
from time import ctime  
  
driver = webdriver.Firefox()  
  
#設置隱式等待是10s  
driver.implicitly_wait(10)  
driver.get("http://www.baidu.com/")  
try:  
    print(ctime())  
    driver.find_element_by_id("kw22").send_keys("python")  
except NoSuchElementException as e:  
    print(e)  
finally:  
    print(ctime())  
    driver.quit()  
  • implicitly_wait()默認參數單位是秒,這里的5秒並不是一個固定的等待時間,它不影響腳本的執行速度。
  • implicitly_wait()並不針對頁面上的某一元素進行等待,當腳本執行到某個元素定位時,若元素可以定位,則繼續執行;若元素定位不到,則它將以輪詢的方式不斷判斷元素是否被定位到,直到超出設置時長還沒有定位到元素,則拋出異常。

sleep休眠方法

希望腳本執行到某個位置做固定休眠,可以使用sleep()方法。sleep()方法由Python的time提供:

from time import sleep

實例:(結合隱式等待、鍵盤事件)

隱式等待利用語句:try...except...else...finally...

先對定位元素進行判斷,若在設置的時間內定位元素失敗就執行except語句拋出NoSuchElementException,定位到元素執行else語句代碼繼續執行。

from selenium import webdriver  
from selenium.webdriver.common.keys import Keys  
from time import sleep,ctime  
from selenium.common.exceptions import NoSuchElementException  
  
driver = webdriver.Firefox()  
print(ctime())  
  
#設置隱式等待  
driver.implicitly_wait(10)  
  
#先執行try定位元素位置  
try:  
    driver.get(r"http://www.baidu.com/")  
    driver.maximize_window () #全屏顯示  
    sleep(2)  
    el = driver.find_element_by_name("wd")  
    sleep(3) #休眠3秒  
  
#找不到元素位置就執行except      
except NoSuchElementException as e:  
    print(e)  
  
#找到元素位置執行else語句  
else:  
    el.send_keys("pythonm")  
  
    #刪除多輸入的m  
    driver.find_element_by_name("wd").send_keys(Keys.BACK_SPACE)  
    sleep(3)  
    #輸入空格+“自動化測試”  
    driver.find_element_by_name("wd").send_keys(Keys.SPACE)  
    sleep(3)  
    driver.find_element_by_name("wd").send_keys("自動化測試")  
    sleep(3)  
    #輸入enter鍵百度一下  
    driver.find_element_by_id("su").send_keys("Keys.ENTER")  
    sleep(3)  
  
#定不定位到元素都會執行finally語句  
finally:  
    print(ctime())  
    driver.quit()  

定位一組元素

webdriver提供了定位一組元素的方法:

  • find_elements_by_id()
  • find_elements_by_name()
  • find_elements_by_class_name()
  • find_elements_by_tag_name()
  • find_elements_by_xpath()
  • find_elements_by_css_selector()
  • find_elements_by_link_text()
  • find_elements_by_partial_link_text()

原來定位一組元素和定位一個元素基本一樣,唯一不同的是elements復數。

定位一組元素用於:

  • 批量操作元素,如勾選復選框checkbox、單選框radio。
  • 先獲取一組元素,再從這組元素對象中過濾出需要操作的元素,如定位頁面所有的復選框,然后選擇其中一個進行其他操作。

如操作下面一段代碼:checkbox.html

<!DOCTYPE HTML>  
<html lang="ch-zh">  
 <head>  
  <meta charset="utf-8">  
  <title>checkbox test~</title>  
  <style type="text/css">  
  
  </style>  
 </head>  
 <body>  
   <h2>選擇你喜歡的食物:</h2>  
   <form action="" method="get" id="myform">  
    <p>  
      <label>  
       <input type="checkbox" name="checkbox1" value="1">蘋果  
      </label>  
      <label>  
       <input type="checkbox" name="checkbox2" value="2">栗子  
      </label>  
      <label>  
       <input type="checkbox" name="checkbox3" value="3">西瓜  
      </label>  
      <label>  
       <input type="checkbox" name="checkbox4" value="4">芒果  
      </label>  
      <label>  
       <input type="checkbox" name="checkbox5" value="5">芒果  
      </label>  
    </p>  
   <h2>你是男士還是女士:</h2>  
    <p>  
      <label>  
        <input type="radio" name="sex" value="man">男士  
      </label>  
      <label>  
        <input type="radio" name="sex" value="woman">女士  
      </label>  
      <label>  
         <input type="radio" name="sex" value="no">保密  
      </label>  
    </p>  
   </form>  
 </body>  
</html>  

把checkbox復選框全部選擇:

find_elements_by_tag_name()定位,需要判斷是否是checkbox

from selenium import webdriver  
import time  
  
driver = webdriver.Firefox()  
  
driver.get(r"http://192.168.225.137/html5/checkbox.html")  
  
#選擇頁面上所有tag_name是input的元素  
inputs = driver.find_elements_by_tag_name("input")  
  
#然后過濾出type為checkbox的元素  
for i in inputs:  #用tag_name定位需要判斷是否是checkbox,如下:  
    if i.get_attribute("type") == "checkbox":  
        i.click()  
        time.sleep(1)  
inputs.pop().click()  
inputs.pop().click(2)  

通過find_elements_by_xpath()和find_elements_by_css_selector()直接定位到checkbox:

不需要判斷了,選擇所有的復選框后取消第二個和最后一個:

from selenium import webdriver  
from time import sleep  
  
driver = webdriver.Firefox()  
driver.get(r"http://192.168.225.137/html5/checkbox.html")  
driver.set_window_size(1000,1000)  
  
#通過css定位  
checkboxs = driver.find_elements_by_css_selector("[type='checkbox']")  
#通過xpath定位  
inputs = driver.find_elements_by_xpath("//*[@type='checkbox']")  
#通過以上兩種方式定位就不需要判斷定位的標簽是否是復選框的了  
for i in checkboxs:  
    i.click()  
    sleep(1)  
      
#打印當前頁面上input="checkbox" 的個數  
print(len(inputs))  
  
#把頁面上第二個checkbox取到勾選  
inputs.pop(1).click()  
sleep(2)  
driver.find_elements_by_xpath("//*[@type='checkbox']").pop(-1).click()  
#前面已經把所有checkbox勾上了,通過pop().click()對某個checkbox再勾選,即是取消勾選。  
  • len()方法可以計算定位到的元素個數;
  • pop()方法獲取列表中某個元素,pop().click()定位到某個checkbox后取消勾選;
  • pop()\pop(-1)都表示最后一個checkbox;
  • pop(0)第一個checkbox;

多表單切換

webdriver只能在一個頁面上定位和識別元素,對於iframe或frame不能直接定位。

通過switch_to.frame()方法將當前的主體切換為frame或iframe表單的內嵌頁面中。

myframe.html

<!DOCTYPE HTML>  
<html lang="ch-zn">  
  <head>  
   <title>myframe test!!!</title>  
   <meta charset="utf-8">  
   <style type="text/css">  
    h3{text-align:center;color:blue;}  
    div{text-align:center;}  
   </style>  
  </head>  
  <body>  
   <h3>myframe</h3>  
   <div>  
     <iframe src="http://www.baidu.com/" width="800px" height="200px" name="myframe" id="if"></iframe>  
   </div>  
  </body>  
</html>  

如上內聯框架,定位里面的百度頁面元素時,先要使用switch_to.frame()找到<iframe>標簽,然后再定位百度頁面的元素。

實例:

from selenium import webdriver  
from time import sleep  
from selenium.common.exceptions import NoSuchElementException  
  
driver =webdriver.Firefox()  
driver.get(r"http://192.168.225.137/html5/myframe.html")  
driver.set_window_size(2000,2000)  
  
#切換到iframe里面,iframe(name='myframe')  
driver.switch_to.frame("myframe")  
  
#下面就是正常操作  
#隱式等待10s  
driver.implicitly_wait(10)  
try:  
    el = driver.find_element_by_xpath("//*[@id='kw']")  
    el1 = driver.find_element_by_id("su")  
    sleep(2)  
except NoSuchElementException as e:  
    print(e)  
else:  
    el.send_keys("python")  
    el1.click()  
finally:  
    driver.quit()  

switch_to.frame()默認可以去id或name屬性值定位,如果沒有id或name屬性,可以用下面方式定位:

from selenium import webdriver  
from time import ctime,sleep  
  
driver = webdriver.Firefox()  
  
driver.implicitly_wait(10)  
print(ctime())  
  
driver.get(r"http://192.168.225.137/html5/myframe.html")  
  
#定位iframe的位置保存到變量el  
el = driver.find_element_by_xpath("//*[@class='if']")  
#切換到該frame  
driver.switch_to.frame(el)  
#對iframe頁面操作  
driver.find_element_by_css_selector("#kw").send_keys("iframe")  
driver.find_element_by_css_selector("#su").click()  
print(ctime())  
  
#跳出當前一級表單  
driver.switch_to.parent_frame ()  
#切換到最外層的頁面  
driver.switch_to.default_content()  

多窗口切換

在頁面操作過程中有時候點擊某個鏈接會彈出新的窗口,

webdriver的switch_to.window()方法,可以實現在不同窗口之間的切換。

實例:

打開百度首頁,打開新的窗口注冊窗口,在返回百度首頁窗口。

from selenium import webdriver  
from time import *  
  
driver = webdriver.Firefox()  
driver.implicitly_wait(10)  
driver.get(r"http://www.baidu.com/")  
driver.maximize_window()  
  
#獲得百度搜索窗口句柄  
search_windows = driver.current_window_handle  
  
driver.find_element_by_link_text("登錄").click()  
driver.find_element_by_link_text("立即注冊").click()  
  
#獲得當前所有打開窗口的句柄,這里一共就兩個句柄。  
all_handles = driver.window_handles  
  
#進入注冊窗口  
for handle in all_handles:  
    if handle != search_windows: #不是百度句柄,就是注冊句柄了。  
        driver.switch_to.window(handle)  
        print("現在是注冊窗口!")  
        #獲取當前頁面的title  
        title = driver.title  
        print(title)  
        pass  
        #獲取當前注冊頁面的URL  
        url = driver.current_url  
        print(url)  
  
  
#回到搜索窗口  
for handle in all_handles:  
    if handle ==search_windows: #百度句柄了  
        driver.switch_to.window(handle)  
        print("現在是搜索窗口!")  
          
        #關閉百度登錄框  
        driver.find_element_by_xpath(".//*[@id='TANGRAM__PSP_2__closeBtn']").click()  
          
        title = driver.title  
        print(title)  
        pass  
        url = driver.current_url  
        print(url)  
        #百度搜索  
        driver.find_element_by_id("kw").send_keys("python")  
        driver.find_element_by_id("su").click()  
        sleep(2)  
driver.quit()  

webdriver新的屬性和方法:

  • current_window_handle:獲取當前窗口句柄
  • Window_handles:獲取所有窗口的句柄
  • switch_to.window():切換到相應的窗口。用於不同窗口的切換;switch_to.frame()用於不同表單的切換。

警告框處理

webdriver中處理js所生成的alert、confirm、prompt警告框:(怎么區分是不是警告框的一種方法:利用firebug的“點擊查看元素”,是不能定位到警告框的元素位置的,定位到的就不是警告框了,可以通過一般的方式操作該頁面的元素,這里要理解警告是怎么產生的,一般是js腳本)

使用switch_to_alert()方法定位到alert、confirm、prompt,然后使用text、accept、dismiss、send_keys等方法進行操作。

  • text:返回alert、confirm、prompt中的文字信息;
  • accept():接受現有警告框;
  • dismiss():解散現有警告框;
  • send_keys(keysToSend):發送文本到警告框。keyToSend:將文本發送到警告框

操作實例:

from selenium import webdriver  
from time import *  
from selenium.webdriver.common.action_chains import ActionChains  
  
driver = webdriver.Firefox()  
driver.get(r"http://www.baidu.com/")  
driver.maximize_window()  
#鼠標懸停  
el = driver.find_element_by_link_text("設置")  
ActionChains(driver).move_to_element(el).perform()  
#打開搜索設置  
driver.find_element_by_link_text("搜索設置").click()  
#點擊恢復默認  
driver.find_element_by_link_text("恢復默認").click()  
sleep(2)  
#返回警告框中的文本信息  
text = driver.switch_to_alert().text  
print(text)  
#接受現有警告框  
driver.switch_to_alert().accept()  
  
driver.quit()  

上傳文件

file.html

通過input標簽實現的上傳功能

<!DOCTYPE html>  
<html lang="en">  
 <head>  
  <title>file test!</title>  
  <meta charset="utf-8">  
 </head>  
 <body>  
  <p style="color:blue;text-align:left;font-size:30px;">請上傳一個文件:</p>  
  <form action="" method="get" id="myform">  
   <input type="file" name="file" accept="" multiple="multiple">  
  </form>  
 </body>  
</html>  

實例:通過input標簽實現上傳功能的可以通過send_keys("文件地址")上傳

from selenium import webdriver  
 
driver = webdriver.Firefox()  
driver.get(r"http://192.168.225.137/html5/file.html")  
#通過send_keys()上傳  
driver.find_element_by_css_selector("[type='file']").send_keys("C:\\Users\\Administrator\\Desktop\\html5.txt")  

下載文件

實例:下載一個文件(此實例只適合Firefox瀏覽器)

from selenium import webdriver  
import os  
import time  
  
#為了能夠讓Firefox()實現下載,需要對FirefoxPile()進行設置  
fp = webdriver.FirefoxProfile()  
  
#browser.download.folderList設置為0,下載到瀏覽器默認的路徑;設置為2則可以設置下載路徑  
fp.set_preference('browser.download.folderList',2)  
#browser.download.manager.showWhenStarting設為false不顯示開始,設為true顯示開始  
fp.set_preference('browser.download.manager.showWhenStarting',False)  
#browser.download.dir用於指定下載文件的目錄,os.getcwd()當前目錄  
fp.set_preference('browser.download.dir',os.getcwd())  
#browser.helperApps.neverAsk.saveToDisk指定下載頁面的Content-type值,“application/octet-stream”是文件的類型  
fp.set_preference('browser.helperApps.neverAsk.saveToDisk',  
                   'application/octet-stream')  
#將所有設置的信息在調用webdriver的Firefox時作為參數傳遞給瀏覽器,Firefox瀏覽器就是根據折現設置信息將文件下載到設定的腳本目錄下。  
driver = webdriver.Firefox(firefox_profile = fp)  
driver.get('https://pypi.python.org/pypi/selenium')  
driver.find_element_by_partial_link_text("selenium-3.0").click()  
time.sleep(30)  
driver.quit()  

為了能夠讓Firefox()實現下載,需要對FirefoxPile()進行設置:

  • browser.download.folderList設置為0,下載到瀏覽器默認的路徑;設置為2則可以設置下載路徑
  • browser.download.manager.showWhenStarting設為false不顯示開始,設為true顯示開始
  • browser.download.dir用於指定下載文件的目錄,os.getcwd()當前目錄
  • browser.helperApps.neverAsk.saveToDisk指定下載頁面的Content-type值,“application/octet-stream”是文件的類型

HTTP Content-type常用的對照表:http://tool.oschina.NET/commons

操作cookie

有時候我們需要驗證瀏覽器中cookie是否正確。webdriver提供了操作cookie的相關方法,可以讀取、添加、刪除cookie信息。

webdriver操作cookie的方法:

  • get_cookies():獲取所有的cookie信息
  • get_cookie(name):返回字典的key為name的cookie信息
  • add_cookie(cookie_dict) :添加cookie。cookie_dict值字典對象,必須有name和value值
  • delete_cookie(name,optionString):刪除cookie信息。name是要刪除的cookie名稱,optionString是該cookie的選項,目前支持的選項包括“路徑”,“域”
  • delete_all_cookies():刪除所有的cookie信息

get_cookie()實例:

from selenium import webdriver  
  
driver = webdriver.Firefox()  
driver.get(r"http://www.hao123.com/")  
#獲取所有cookies  
cookies = driver.get_cookies()  
print(cookies)  
driver.quit()  

添加cookie實例:add_cookie()

from selenium import webdriver  
  
driver = webdriver.Firefox()  
driver.get(r"http://www.baidu.com/")  
#添加cookie,字典形式且必須有name、value值  
driver.add_cookie({"name":"user","value":"tester"})  
#遍歷所有的cookies中的name、value並打印出來,就會顯示添加的信息了  
for i in driver.get_cookies():  
    print("%s => %s"%(i['name'],i['value']))  
driver.quit()   

調用JavaScript

webdriver對與瀏覽器的滾動條沒有提供相應的操作方法,可以接着JavaScript來控制瀏覽器的滾動條。webdriver提供了execute_script()方法來執行JavaScript代碼。

調整瀏覽器的滾動條位置的JavaScript方法:

window.scrollTo(水平位置,垂直位置);

水平位置是指水平的左間距;

垂直位置是指垂直的上邊距;

實例:操作百度搜結果

for i in range(10):  
    from selenium import webdriver  
    from time import *  
  
    driver = webdriver.Firefox()  
    driver.get(r'http://www.baidu.com/')  
    driver.set_window_size(600,600)  
    driver.find_element_by_css_selector('#kw').clear()  
    driver.find_element_by_css_selector('#kw').send_keys("python接口測試")  
    driver.find_element_by_xpath("//*[@id='su']").click()  
    sleep(2)  
    #通過JavaScript設置瀏覽器窗口的滾動條位置  
    js = "window.scrollTo(100,300);"  
    driver.execute_script(js)  
    sleep(3)  
    driver.quit()  

另外JavaScript的作用還可以想textarea多行文本框輸入內容:

多行文本.html

<!DOCTYPE HTML>  
<html lang="en">  
 <head>  
  <meta charset="utf-8">  
  <title>多行文本 test!!</title>  
 </head>  
 <body>  
   <h3>請輸入你的建議:</h3>  
   <form action="" method="get" name="1">  
    <textarea name="suggest" cols="50" rows="10"></textarea>  
    <br>  
    <input type="submit" id="3" value="提交叻">  
   </form>  
 </body>  
</html>  

操作textarea文本框

from selenium import webdriver  
from time import *  
  
driver = webdriver.Firefox()  
driver.get(r"http://192.168.225.137/html5/textarea.html")  
driver.maximize_window()  
#首先text定義要輸入的內容  
text = "我的建議是,哈哈哈哈哈哈哈哈"  
#然后將text與JavaScript代碼通過“+”拼接,這樣是使輸入的內容變得可以自定義  
js = "var sum=document.get_element_by_name('suggest');sum.value='" + text + "';"  
#通過execute_script()執行js代碼  
driver.execute_script(js)  
  
driver.find_element_by_xpath("//*[@id='3']").click()  
sleep(5)  
  
driver.quit()  

窗口截圖

webdriver提供了截圖函數get_screenshot_as_file('保存文件的路徑')來截取當前窗口。

實例1:截取百度

from selenium import webdriver  
import time  
driver = webdriver.Firefox()  
driver.get(r'http://www.baidu.com/')  
driver.maximize_window()  
driver.find_element_by_css_selector('#kw').send_keys("selenium")  
driver.find_element_by_id('su').click()  
time.sleep(3)  
#截取當前窗口,並將圖片保存到指定位置  
driver.get_screenshot_as_file('E:\\screenshot\\baidu.jpg')  
driver.quit()  

實例2:截取126郵箱

from selenium import webdriver  
import time  
  
driver = webdriver.Firefox()  
driver.get(r'http://www.126.com/')  
driver.maximize_window()  
driver.implicitly_wait(5)  
url = driver.current_url  
print(url)  
title = driver.title  
print(title)  
  
#使用截圖函數,截取當前頁面  
driver.get_screenshot_as_file('E:\\screenshot\\login.jpg')  
  
#登錄126郵箱  
driver.find_element_by_xpath("//*[@id='login-form']/div/div/div[2]/input").clear()  
driver.find_element_by_xpath("//*[@id='login-form']/div/div/div[2]/input").send_keys('XXX—you')  
driver.find_element_by_xpath("//*[@type='password']").clear()  
driver.find_element_by_xpath("//*[@type='password']").send_keys('yuexxx.')  
driver.find_element_by_id('dologin').click()  
time.sleep(3)  
title = driver.title  
print(title)  
url = driver.current_url  
print(url)  
  
#截取登錄后的頁面  
driver.get_screenshot_as_file("E:\\screenshot\\afterlogin")  
time.sleep(3)  
  
#退出郵箱  
driver.find_element_by_link_text("退出").click()  
driver.quit()  

打開E盤screeshot目錄就看到截取的JPG圖片了!

在做UI自動化測試時,可以把該截圖函數:get_screenshot_as_file()封裝成單獨一個模塊,需要截取的時直接使用該方法。

''''' 
定義截圖函數。 
創建截圖函數insert_img(),為了保持自動化項目的可移植性,采用相對 
路徑的方式將測試截圖保存到.\report\image\目錄中。 
 
'''  
  
from selenium import webdriver  
import os  
  
#截圖函數  
def insert_img(driver,file_name):  
    #獲取當前運行腳本的路徑保存到base_dir里面  
    base_dir = os.path.dirname(os.path.dirname(__file__))  
    #把獲取到的路徑轉為字符串  
    base_dir = str(base_dir)  
    #字符串函數replace()把路徑中的“\\”變成“/”  
    base_dir = base_dir.replace('\\','/')  
    #利用split()方法把字符串以“/test_case/”分割為兩部分,split分割字符串后保存為列表,把左邊的保存到base列表中  
    base = base_dir.split('/test_case')[0]  
    #利用字符串拼接重新組合文件路徑。get_screenshot_as_file(文件路徑+截取到的文件名)  
    file_path = base +"/report/image/" + file_name  
    driver.get_screenshot_as_file(file_path)  
  
if __name__ == "__main__":  
    driver = webdriver.Firefox()  
    driver.get("https://www.126.com/")  
    #調用截圖函數  
    insert_img(driver,"126.jpg")  
    driver.quit()  

驗證碼處理

對於有些登錄系統是需要驗證碼的,怎么處理呢?

去掉驗證碼

但如果自動化腳本是在正式環境中測試,這種做法就會給系統帶來一定的風險。

設置萬能的驗證碼

只要測試時輸入一個萬能驗證碼,程序就認為驗證通過,否則就判斷用戶輸入的驗證碼是否正確。設計萬能驗證碼的方式只需要對用戶的輸入信息多加一個邏輯判斷,如下:

number.py

from random import randint  
  
#生成1000到9999之間一個隨機數  
verify = randint(1000,9999)  
print(u"生成的隨機數是:%s"%verify)  
  
number =input("請輸入一個驗證碼:")  
number = int(number)    #把number轉為int和隨機數類型一致  
print(number)  
  
if number == verify:    #number和verify類型要一致才有可比性  
    print("驗證碼正確!")  
elif number == 1234:  
    print("驗證嗎正確!")  
else:  
    print("驗證碼錯誤!!!")  

這個程序分別輸入正確的驗證碼、萬能驗證碼、錯誤驗證碼。

記錄cookie

通過向瀏覽器中添加cookie可以要過登錄的驗證碼。

基本操作函數

driver.標簽語句.click()

執行一次點擊事件,就是點一下當前的標簽

driver.標簽語句.send_keys('')

向當前標簽輸入一段內容為字符串

driver.標簽語句.size()

返回元素尺寸

driver.標簽語句.text()

返回元素文本

driver.標簽語句.get_attribute()

方法獲取屬性值

driver.標簽語句.is_displayed()

返回該元素是否可見

driver.back()

返回上一個頁面

driver.forward()

前進前一個頁面

driver.refresh()

刷新當前頁面

driver.quit()

退出瀏覽器,表示結束


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM