Selenium學習筆記
selenium webdriver是業界公認ui自動化測試的標准,其封裝的api可以對瀏覽器的任何地方進行操作
selenium2.0和selenium3.0的區別?
3.0任何瀏覽器的廠商都支持selenium,他們只要給予驅動就可以了,2.0只支持火狐和谷歌
webdriver工作原理?
通過webdriver創建一個瀏覽器服務,remote server(底層服務).啟動腳本后會通過驅動打開瀏覽器,並綁定端口,不同瀏覽器端口不同
client端創建一個session來請求rmote server並發送restful請求,server解析后,完成代碼的操作返回結果
如何定位html中的元素?
1.查看並分析html中所需定位的元素
2.找到對於當前頁面來說唯一的屬性
css selector與xpath區別?
其有着不同的定位方式,擇優選擇最佳的定位方式
xpath可以通過角標定位到一些css selector定位不到的元素
css selector基於html,能快速取到值,xpath底層要從xml轉換成html對代碼執行效率會受到影響,還依賴轉化的准確度
xpath定位 xpath是xml的路徑語言
/html/body/div/div/div/ul/li/a[@href="/xpath/xpath_syntax.asp"] 從祖先html開始查找定位元素,可以不用寫角標 注意:一個/表示其子元素查找,//表示模糊匹配查找
//* 獲取頁面所有元素
//*[@id='xxxx'] @表示以id屬性定位
//input[@id='xxx'] input表示以input標簽名進行定位
//input[1] 如果出現不唯一的請求可以通過角標的形式取,注意角標從1開始
//input[1]/input[1] 層級定位方式,/表示當前層級內
//input[@id='xxx' and @class='xxx'] #邏輯定位方法,通過多種屬性確立唯一
xpath(定位方法盡量少用層級定位,如果修改了層級位置會導入所有定位都失效,以屬性定位為主)
css selector定位 html的css選擇器標簽定位
#i1 表示查找id屬性為i1的元素
.i1 表示查找class屬性為i1的屬性
[name='xxx'] 表示查找name屬性定位
input[name='xxx'] 可以通過標簽名進行檢索來縮小范圍
input#name 查找input標簽中id為name的元素
input[name='xxx'][id='xxx'][class='xxx'] input標簽下多屬性確立唯一
input>input[id='xxx'] >表示遞進一層
input[name^='xxx'] ^支持前者模糊匹配
input[name$='xxx'] $支持后者模糊匹配
input[name*='xxx'] *表示包含,只要包含字段中的內容都可能會被匹配上
css selector不支持角標取值,所以我們要靈活運用xpath和css selector結合
由於css是html原始支持,還可以支持很多定位方法,以上一些我們在日常通常都可以用了,如進一步學習可以參考
http://www.w3school.com.cn/cssref/css_selectors.asp
selenium webdriver api-代碼定位,基礎操作
pip install selenium
selenium驅動安裝 https://www.cnblogs.com/RainBol/protected/p/10065838.html
from selenium import webdriver # 驅動程序,用chrome,當然還可以用firefox,ie驅動 driver = webdriver.Chrome() # 獲取網址 driver.get("http://www.baidu.com") # 設置頁面寬長
driver.get_window_size()# 獲取瀏覽器的大小 driver.set_window_size(400, 800)# 定義指定頁面長寬 driver.maximize_window()#最大頁面長寬 # 截圖
driver.get_screenshot_as_file('xx.jpg')# 在當前腳本的同一級目錄生成瀏覽器截屏的圖片文件(其他底層還有三個截圖api) # 八種單數定位方式(都需要確立唯一) driver.find_element_by_name() #通過name屬性定位 driver.find_element_by_id() #通過id屬性定位 driver.find_element_by_class_name() #通過class屬性定位 driver.find_element_by_link_text("") #文案定位 driver.find_element_by_partial_link_text() #包含文案定位 driver.find_element_by_css_selector() #css selector定位 driver.find_element_by_tag_name() #標簽名定位,如果有多個,獲取的是html頁面中第一個 driver.find_element_by_xpath(".//*[@id='kw']").clear() #xpath定位
# 八種復數定位方法
(不常用,單數的element加s就是復數,所有復數形式都返回一個列表,列表順序按html從上到下,如果元素下還有子元素,可以通過元素進行再次定位)
# 其他兩種定位
driver.find_element('id','i1') #單數形式,參數id表示通過id定位,i1表示元素值為i1進行定位
driver.find_elemnets('id','i1') #復數形式,返回列表
# 提交表單 driver.find_element_by_xpath(".//[@id='kw']").send_keys("selenium") driver.find_element_by_xpath(".//*[@id='kw']").submit() # 控制瀏覽器前進后退 driver.back() driver.forward() # 刷新頁面 driver.refresh() # 瀏覽器關閉 driver.close() # 關閉一個頁面也叫關閉一個tag,當頁面只有一個tag的時候就直接關閉瀏覽器了 driver.quit() # 退出驅動也就是關閉瀏覽器
等待,操作瀏覽器,懸浮
from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains # 引入actionchains類 from selenium.webdriver.common.keys import Keysfrom selenium.common.exceptions import NoSuchElementException from time import ctime from selenium.webdriver.support.select import Select import time browser = webdriver.Chrome() # 打開網頁驅動
#等待 一般等待分為三種,系統等待,隱士等待,顯示等待
# 隱式等待10s
"""
implicitly_wait():隱式等待
當使用了隱士等待執行測試的時候,如果 WebDriver沒有在 DOM中找到元素,將繼續等待,超出設定時間后則拋出找不到元素的異常
換句話說,當查找元素或元素並沒有立即出現的時候,隱式等待將等待一段時間再查找 DOM,默認的時間是0
一旦設置了隱式等待,則它存在整個 WebDriver 對象實例的聲明周期中,隱式的等到會讓一個正常響應的應用的測試變慢,
它將會在尋找每個元素的時候都進行等待,這樣會增加整個測試執行的時間,所以在ui自動化實現比較雞肋
"""
browser.implicitly_wait(10)
# 顯示等待 ↓
'''
顯示等待 ==>顯示等待為selenium的核心,用好它能增加自動化的執行速度,提高效率
自設置了顯示等待,在設置后到指定設置時間內,會按設置的步長等待,直到找到元素或超時
'''
browser.get("https://www.baidu.com") # 打開網址 print("設置瀏覽器寬1200、高1400顯示") browser.set_window_size(1200, 1400)
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By
element = WebDriverWait(browser, 5, 0.5).until( EC.presence_of_element_located((By.ID, "kw")) )
#browser, 5, 0.5分別表示對象,超時時間,步長
#By.ID,"kw"分別表示通過id屬性,定位的值
# 系統等待 ↓
'''
time.sleep(5)
系統等待用在測試調試階段
''' time.sleep(2)
title = browser.title # title:用於獲得當前頁面的標題。 print(title) # 打印當前頁面的title now_url = browser.current_url # 打印當前頁面URL # current_url:用戶獲得當前頁面的URL。 print(now_url) size = browser.find_element_by_id("kw").size # 找到輸入框的頁面屬性 print(size) text = browser.find_element_by_id("kw").text # 獲取搜索條目的文本信息 print(text) attribute = browser.find_element_by_id("kw").get_attribute('type') # 返回元素屬性值 print(attribute) result = browser.find_element_by_id("kw").is_displayed() # 查看是否可見 print(result) browser.find_element_by_id("kw").clear() # 清除內容 # 如果超出10s拋出異常 try: print(ctime()) search_test = browser.find_element_by_id("kw").send_keys("seleniuma") # 輸入seleniuma time.sleep(2) except NoSuchElementException as e: print(e) finally: print(ctime()) # 鍵盤按鍵 browser.find_element_by_id("kw").send_keys(Keys.BACK_SPACE) browser.find_element_by_id("su").send_keys(Keys.ENTER) time.sleep(2) browser.refresh() # 刷新 time.sleep(2) browser.find_element_by_id("kw").clear() search_test2 = browser.find_element_by_id("kw").send_keys("webdriver") # 輸入webdriver time.sleep(2) browser.find_element_by_id('su') # 提交表單 # 鼠標懸浮 adove = browser.find_element_by_class_name("pf") # 找到adove ActionChains(browser).move_to_element(adove).perform() # 方法 :定位到執行元素鼠標懸停操作 browser.find_element_by_class_name("setpref").click() # 找到下拉條中元素進行點擊操作,click:點擊事件 time.sleep(2) # 懸停下拉框+顯示條數 # search03 = browser.find_element_by_link_text("設置") # ActionChains(browser).move_to_element(search03).perform() # time.sleep(2) # 搜索結果顯示條數 sel = browser.find_element_by_xpath("//select[@id='nr']") Select(sel).select_by_value('50') # 顯示50條 time.sleep(5) browser.find_element_by_link_text("保存設置").click() time.sleep(2) # 返回原來的樣子 browser.switch_to.alert.accept() time.sleep(2) search03 = browser.find_element_by_link_text("設置") ActionChains(browser).move_to_element(search03).perform() time.sleep(2) av = browser.find_element_by_link_text("搜索設置") av.click() time.sleep(2) browser.find_element_by_id("nr").click() time.sleep(2) # 搜索結果顯示條數 sel = browser.find_element_by_xpath("//select[@id='nr']") Select(sel).select_by_value('10') # 顯示10條 # …… time.sleep(2) browser.find_element_by_link_text("保存設置").click() time.sleep(2) browser.close()
等待擴展
WebDriverWait參數
def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None): pass #driver:類的實例 #timeout:超時時間 poll_frequency=POLL_FREQUENC:#調用until或until_not中的方法的間隔時間,默認值0.5秒 ignored_exceptions=None:#忽略的異常,如果在調用until或until_not的過程中拋出這個元組中的異常, 則不中斷代碼,繼續等待,如果拋出的是這個元組外的異常,則中斷代碼,拋出異常。默認只有NoSuchElementException #以上是構造函數,下面介紹方法,總共兩個until和until_not def until_not(self, method, message=''):#當某元素消失或什么條件不成立則繼續執行 pass def until(self, method, message=''):#當某元素出現或什么條件成立則繼續執行 pass #method:在等待期間,每隔一段時間調用這個傳入的方法,直到返回值不是False #message: 如果超時,拋出TimeoutException,將message傳入異常
等待操作
from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC driver = webdriver.Chrome() driver.get('http://www.baidu.com') driver.maximize_window() # 判斷某個元素進入dom樹中,可以是不可見的元素,找到返回WebElement對象屬性 WebDriverWait(driver, 10, 1).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#kw'))) # 判斷某組元素進入dom樹中,可以是不可見的元素,找到返回WebElement對象列表 WebDriverWait(driver, 10, 1).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '#kw'))) # 判斷title是否正確,返回布爾值 WebDriverWait(driver, 10, 1).until(EC.title_is(u"百度一下,你就知道")) # 包含判斷title是否正確,返回布爾值 WebDriverWait(driver, 10, 1).until(EC.title_contains('百度')) # 判斷某個元素是否被加到了dom樹里,並不代表該元素一定可見,如果定位到就返回WebElement WebDriverWait(driver, 10, 1).until(EC.presence_of_element_located((By.ID, 'kw'))) # 判斷是否至少有1個元素存在於dom樹中,如果定位到就返回列表 WebDriverWait(driver, 10, 1).until(EC.visibility_of_all_elements_located((By.ID, 'kw'))) # 判斷某個元素是否可見 WebDriverWait(driver, 10, 1).until(EC.visibility_of(driver.find_element(by=By.ID, value='kw'))) # 判斷某個元素是否別添加到dom里並可見,可見代表元素可顯示且寬和高都大於0 WebDriverWait(driver, 10, 1).until(EC.visibility_of_element_located((By.ID, 'kw'))) # 判斷某個元素是否包含預期字符串,返回布爾值 WebDriverWait(driver, 10, 1).until(EC.text_to_be_present_in_element((By.XPATH, "//*[@id='u1']/a[8]"), u'設置')) # 判斷指定元素的屬性值中是否包含預期字符串,返回布爾值 WebDriverWait(driver, 10, 1).until(EC.text_to_be_present_in_element_value((By.CSS_SELECTOR, '#su'), '百度一下')) # 判斷該frame是否可以switch進,如果可以返回True並且switch進去,否則返回False WebDriverWait(driver,10,1).until(EC.frame_to_be_available_and_switch_to_it()) # 判斷某個元素中是否可見並且是enable的,代表可點擊 WebDriverWait(driver, 10, 1).until(EC.element_to_be_clickable((By.XPATH, "//*[@id='u1']/a[8]"))).click() # 等待某個元素從dom樹中移除WebDriverWait(driver,10,1).until(EC.staleness_of(driver.find_element(By.ID,'su'))) # 判斷某個元素是否被選中了,一般用在下拉列表 WebDriverWait(driver, 10).until(EC.element_to_be_selected(driver.find_element(By.XPATH, "//*[@id='nr']/option[1]"))) # 判斷某個元素的選中狀態是否符合預期 WebDriverWait(driver, 10).until( EC.element_selection_state_to_be(driver.find_element(By.XPATH, "//*[@id='nr']/option[1]"), True)) # 判斷某個元素的選中狀態是否符合預期 WebDriverWait(driver, 10).until(EC.element_located_selection_state_to_be((By.XPATH, "//*[@id='nr']/option[1]"), True)) # 判斷頁面上是否存在alert,如果有就切換到alert並返回alert的內容 instance = WebDriverWait(driver, 10).until(EC.alert_is_present())
文件上傳,cookie,滾動條,js執行
from selenium import webdriver import time driver = webdriver.Chrome() driver.get('http://sahitest.com/demo/php/fileUpload.htm') driver.find_element_by_name("file").send_keys("C:\\Users\\admin\Desktop\\test.txt")#選擇本地文件上傳 driver.find_element_by_name("submit").click() driver.quit() driver = webdriver.Chrome() driver.set_window_size(1920,1080) driver.get("http://www.youdao.com") # 獲得cookie信息 cookie = driver.get_cookies() # 將獲得cookie的信息打印 print(cookie) print("向cookie的name 和value中添加會話信息") driver.add_cookie({'name': 'key-aaaaaaa', 'value': 'value-bbbbbb'}) # 遍歷cookies中的name 和value信息並打印,當然還有上面添加的信息 for cookie in driver.get_cookies(): print("%s -> %s" % (cookie['name'], cookie['value'])) driver.get("http://www.testclass.net/selenium_python/javascript/") #滾動條操作 js = "window.scrollTo(100,700);" #scrollTo(x,y)
#執行js代碼 driver.execute_script(js) time.sleep(3) driver.quit()
警告框處理
from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains import time browser = webdriver.Firefox() browser.implicitly_wait(10) browser.get("https://www.baidu.com") time.sleep(2) link = browser.find_element_by_link_text("設置") ActionChains(browser).move_to_element(link).perform() browser.find_element_by_link_text("搜索設置").click() time.sleep(2) browser.find_element_by_link_text("保存設置").click() time.sleep(2) print (browser.switch_to_alert().text) #先打印再接受警告框 ar = browser.switch_to.alert.accept() #點擊確定警告框 dis = browser.switch_to.alert.dismiss() #點擊取消警告框
browser.quit()
多窗口切換
from selenium import webdriver import time driver = webdriver.Chrome() driver.implicitly_wait(10) driver.get("http://www.baidu.com") # 獲取當前對象的窗口句柄 sreach_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 != sreach_windows:#遍歷如果不屬於之前的那個頁面就執行下面操作 driver.switch_to.window(handle)#跳轉到另一個頁面 print('now register window!') driver.find_element_by_name("userName").send_keys('這個是用戶名') driver.find_element_by_id('TANGRAM__PSP_3__phone').send_keys('123456') time.sleep(2)
# 以上過於復雜,可以參考以下兩行
last_handle = driver.windows_handles[-1]# 表示拿到列表最后一個值,也就是最后一個頁面的窗口句柄
driver.switch_to.window(last_handle)# 讓瀏覽器跳到剛剛指定頁面
# 兩個頁面之間tab切換 driver.switch_to.window(all_handles[0]) time.sleep(5) driver.switch_to.window(all_handles[1]) time.sleep(5) driver.switch_to.window(all_handles[0]) driver.quit()
判斷checkbox勾選
off = driver.find_element_by_id('xxx')# 定位到checkbox勾選元素 print(on.is_selected())# 判斷是否勾選,返回布爾值
iframe定位
driver.switch_to.frame('xxx')# 切換進入到當前html下的frame層 driver.switch_to.parent_frame()# 返回上一層 driver.switch_to.default_content()# 直接返回最外層
拖拽指令
from selenium.webdriver.common.action_chains import ActionChains s1 = driver.find_element_by_id('xxx')# s1為推拽起始元素 t1 = driver.find_element_by_class_name('xxx')# t1位推拽目標元素 ActionChains(driver).drag_and_drop(s1,t1).perform()
UI自動化框架(web)
我們為什么要做ui自動化測試?
項目基於穩定的前提,由於老功能在原先基礎要增加新功能點,為了避免在舊業務上有過多資源來回歸測試,可以用ui自動化來對其業務進行回歸測試,不適用與新業務
我們為什么要做ui自動化框架?
目前互聯網公司ui自動化框架現狀:
1.運行不穩定
2.維護麻煩,源碼修改后需要重新定位
3.自動化測試用例與頁面數據腳本寫在一起,排查時業務混亂
自動化框架解決思路:
1.顯示等待框架封裝
2.PO思想(page object) 每個頁面為一個類class,每個功能為一個函數def,web端和app端都以這種思想為主
3.自動化測試用例與頁面數據腳本分離
所以可以基於selenium webdriver原生代碼,unittest單元測試api,報告,截圖,日志和現狀結合實現的框架能很好的幫助我們做好框架
框架中怎么為業務邏輯做斷言?
1.判斷元素消失,代表業務成功
2.判斷另一個元素出現,且該元素一定是唯一的
有哪些框架值得我們使用?
我個人推薦蟲師大大的框架,pyse,poium,還有seleniumbase等都是優秀的改良版測試框架,內置增加了api足夠我們使用了,當然還有一些很好用的其他框架,歡迎推薦
版權聲明:本文原創發表於 博客園,作者為 RainBol 本文歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則視為侵權。