web自動化測試入門篇03——selenium使用教程

2023-2-15    前端達人

1. 目的

web自動化測試作為軟件自動化測試領(lǐng)域中繞不過去的一個“香餑餑”,通常都會作為廣大測試從業(yè)者的首選學(xué)習(xí)對象,相較于C/S架構(gòu)的自動化來說,B/S有著其無法忽視的諸多優(yōu)勢,從行業(yè)發(fā)展趨、研發(fā)模式特點、測試工具支持,其整體的完整生態(tài)已經(jīng)遠遠超過了C/S架構(gòu)方面的測試價值。接上一篇文章,我們將繼續(xù)深入探討Selenium的相關(guān)使用方法與技巧。

 
 

2. 說明

此篇中所用的技術(shù)棧為Selenium+Python,因其本身編程難度不高,總體思想都是基于面向?qū)ο蟮木幊汤砟?,故只要大家的編碼語言基礎(chǔ)不弱,就完全可以做到平替。

 
 

3. 關(guān)于解答上一篇的問題

在正式啟動瀏覽器之前,這里還需要說說上一篇沒有提及的一個問題,后臺有同學(xué)私信說在對應(yīng)驅(qū)動網(wǎng)站上完全找不到自己瀏覽器對應(yīng)版本的驅(qū)動,關(guān)于瀏覽器驅(qū)動的版本,大家都知道驅(qū)動的版本應(yīng)該是要與瀏覽器的版本完全對應(yīng)上的。但往往日常工作中因為環(huán)境或者其他客觀因素會導(dǎo)致瀏覽器的版本五花八門,也會出現(xiàn)驅(qū)動網(wǎng)站上完全沒有你目前工作環(huán)境中對應(yīng)的瀏覽器版本,這里我們大可使用中版本號一致的驅(qū)動來進行嘗試,沒有必要將版本進行完全的匹配。比如你的Chrome瀏覽器的版本號為107.0.5304.107,如果這時對應(yīng)網(wǎng)站只有107.0.5304.62108.0.5359.22的前后兩個版本的驅(qū)動比較相近,這里就有兩個選擇,第一就是卸掉原有的瀏覽器,安裝對應(yīng)的版本;第二則是選擇107.0.5304.62來進行嘗試;相信大家在成本耗時的判斷下,一般都會選擇第二個選項來進行嘗試對吧?那么我可以很負責任的告訴你,第二個判斷是完全行的通的。不必太過糾結(jié)驅(qū)動的小版本號是否完全匹配。

 
 

4. 啟動

我們將一切準備就緒后就可以開始我們的selenium之旅了,首先我們需要將使用selenium進行瀏覽器的啟動(訪問百度)。

from selenium import webdriver

browser = webdriver.Chrome() browser.get('https://www.baidu.com') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

 

如果對應(yīng)的瀏覽器驅(qū)動沒有進行環(huán)境變量的設(shè)置,可以在代碼中直接進行程序的路徑指定來進行后續(xù)的瀏覽器操作。

from selenium import webdriver

path = r'C:\Program Files\Google\Chrome\Application\chromedriver.exe' browser = webdriver.Chrome(path) browser.get('https://www.baidu.com') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

 

使用Selenium打開后的瀏覽器都會標識出正在受到自動化測試軟件控制的相關(guān)提示。

在這里插入圖片描述

 
 

5. 瀏覽器基礎(chǔ)操作

Selenium本身提供給了我們非常多的各類瀏覽器與頁面的操作函數(shù),方便我們根據(jù)所需測試業(yè)務(wù)來進行自由搭配使用甚至是二開。

 

5.1 瀏覽器窗口操作

對于瀏覽器窗口的尺寸進行控制與獲取,如最大化、最小化、指定窗口大小等。

 

窗口全屏

browser.fullscreen_window() 
  • 1

 
窗口最大化

browser.maximize_window() 
  • 1

 
窗口最小化

browser.minimize_window() 
  • 1

 
自定義窗口大?。▽扻高)

browser.set_window_size(1080, 720) 
  • 1

 
自定義窗口坐標位置與大?。▁坐標,y坐標,寬X高)

browser.set_window_rect(100, 200, 1080, 720) 
  • 1

 
獲取窗口的大小(寬X高)

browser.get_window_size() 
  • 1

 
獲取窗口的坐標位置,返回一個字典對象

browser.get_window_position() 
  • 1

 
獲取窗口的坐標與大小(x坐標,y坐標,寬X高)

browser.get_window_rect() 
  • 1

 
獲取當前窗口的句柄

browser.current_window_handle 
  • 1

 
獲取當前所有窗口的句柄

browser.window_handles 
  • 1

 
 

5.2 頁面基礎(chǔ)操作

對于瀏覽器當前頁面的一些操作,如前進、后退、刷新等。

 
前進(下一頁面)

browser.forward() 
  • 1

 
后退(上一頁面)

browser.back() 
  • 1

 
刷新(當前頁面)

browser.refresh() 
  • 1

 
截圖并保存為test.png(當前頁面)

browser.save_screenshot('test.png') 
  • 1

 
截圖并保存為png文件(當前頁面)

browser.get_screenshot_as_file('test_02.png') 
  • 1

 
截圖并將信息轉(zhuǎn)為base64編碼的字符串

browser.get_screenshot_as_base64() 
  • 1

 
 

5.3 信息操作

對于瀏覽器當前一些信息的獲取與操作。

 
獲取頁面URL(當前頁面)

browser.current_url 
  • 1

 
獲取日志類型,會返回一個列表對象

browser.log_types 
  • 1

 
獲取瀏覽器操作日志,注意函數(shù)內(nèi)的參數(shù)為固定值類型’browser’

browser.get_log('browser') 
  • 1

 
獲取設(shè)備操作日志,參數(shù)原理同上

browser.get_log('driver') 
  • 1

 
獲取當前頁面標題

browser.title 
  • 1

 
獲取當前瀏覽器的名字

browser.name 
  • 1

 
 

5.4 元素操作

Selenium中最基礎(chǔ)也是最重要的一環(huán),基本上對于頁面的業(yè)務(wù)操作大多數(shù)都集中與此。另外需要注意的是元素定位所使用的find_element_by的方法在很早之前就已經(jīng)被廢棄,這里同樣也會使用最新的find_element方法進行講解。
如何查看頁面中的元素與其相關(guān)屬性,這里以Chrome為例,我們只需按F12或者右鍵頁面選擇“檢查”,再點擊調(diào)試窗口的左上角的箭頭標志或者使用快捷鍵Ctrl+Shift+C來進行元素的選取,此時Elements標簽頁中會將焦點對應(yīng)跳轉(zhuǎn)至該元素的html代碼行中,接下來我們就可以針對不同的元素和不同的屬性來進行定位操作。

 
在這里插入圖片描述

 

5.4.1 name定位

通過一個元素的name屬性來進行定位。

 

比如定位百度中的搜索欄,我們通過name屬性來進行定位。該元素的html構(gòu)造如下:

<input type="text" class="s_ipt" name="wd" id="kw" maxlength="100" autocomplete="off"> 
  • 1

 
我們只需將name屬性后面的值拿出,賦予給find_element方法即可。新的By方法我們只需要導(dǎo)入selenium.webdriver.common.by下的By方法即可。

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.NAME, 'wd') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

 

5.4.2 class name定位

通過一個元素的class屬性來進行定位。

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.CLASS_NAME, 's_ipt') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 

5.4.3 id定位

通過一個元素的id屬性來進行定位。

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.ID, 'kw') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 

5.4.4 css定位

css selector也被成為選擇器定位,它通過頁面內(nèi)的元素的id、name、tag三個屬性來進行定位,根據(jù)元素屬性的重復(fù)程度,可以單獨屬性定位也可組合屬性來進行定位。而且相較于xpath定位方式來說,博主更推薦使用此方法來進行定位,無論是易用度還是維護性來說比xpath定位好的多。

 
單屬性定位–tag屬性

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.CSS_SELECTOR, 'input') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 
單屬性定位–id屬性

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.CSS_SELECTOR, '#kw') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 
單屬性定位–class屬性

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.CSS_SELECTOR, '.s_ipt') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 
多屬性定位–tag+id屬性

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.CSS_SELECTOR, 'input#kw') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 
多屬性定位–tag+class屬性

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.CSS_SELECTOR, 'input.s_ipt') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 
同樣的,其他的組合方式大家可以舉一反三,不斷嘗試,比如模糊匹配input[class ~= "局部關(guān)鍵字"]、層級定位#form > span > input等等等等。

 

5.4.5 link text定位

這種定位方式適用于頁面中帶有超鏈接的元素,直接通過超鏈接標簽內(nèi)的文字進行元素定位。

我們以百度首頁為例,可以看到該頁面中有很多的超鏈接標簽,如果我們想模擬點擊跳轉(zhuǎn)至新聞對應(yīng)頁面的操作,就可以用link text的元素定位方法來進行實現(xiàn)。

在這里插入圖片描述
 
使用超鏈接標簽對中的“新聞”一詞來進行定位。

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.LINK_TEXT, '新聞').click() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 

5.4.6 partial link text定位

這個定位方式與link text定位十分相像,實際上也就是link text的模糊查找定位方式,對象也是超鏈接內(nèi)的文字,只不過他匹配的不是全部文字而是局部。

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.PARTIAL_LINK_TEXT, '新').click() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 

5.4.7 tag定位

tag定位的效率總體來說不高,也不太推薦單獨使用,html頁面中一般也是由很多相同或不同的標簽對組成。就tag而言標簽重復(fù)的越多,定位的效率其實也就越低。

比如我們想在百度的搜索欄中輸入“selenium”關(guān)鍵字,那么光使用tag其實就很難達到我們的目的,甚至無法準確定位到我們想要的元素。如果運氣好,搜索欄的input標簽在html頁面中排在第一位那還好,只要不是第一位,我們就需要編寫其他的代碼邏輯來輔助我們繼續(xù)定位這個元素。
 

所以下面的代碼實在是不能稱之為高效的執(zhí)行代碼

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.TAG_NAME, 'input').send_keys('selenium') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 

5.4.8 xpath定位

一般來說無法通過以上的這些元素定位方法定位的情況下,我們會使用xpath定位方法。但這里需要特別注意,xpath方法分為絕對路徑和相對路徑兩種定位方式,博主只推薦如果真要使用xpath就使用相對路徑+正則表達式的方式來進行元素定位。不推薦絕對路徑的原因就不用博主多說了吧,只要你敢用,后期的腳本維護與復(fù)用絕對會讓你抓狂的。

 

還是老樣子,我們使用xpath的相對路徑寫法來定位百度首頁的搜索欄。

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.XPATH, '//*[@id="kw"]').send_keys('selenium') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 
另外與find_element方法相對應(yīng)的find_elements方法這里就不多做介紹了,該種方法是將當前頁面中所有能匹配上對應(yīng)元素定位方法的元素全部獲取。大家可以根據(jù)自己的需求來進行選取和使用。

 
 

5.5 延時方式

我們加載頁面時通常會因為網(wǎng)絡(luò)環(huán)境等各方面的客觀因素而導(dǎo)致元素加載的速度各不相同,如果此時我們沒有對業(yè)務(wù)操作進行一定的延時執(zhí)行,那么大概率業(yè)務(wù)操作會出現(xiàn)各類的no such element報錯。
那么我們就需要在頁面元素加載完成之后再對相應(yīng)的元素進行業(yè)務(wù)操作來規(guī)避上面說的這個問題。Selenium內(nèi)可以使用三種延時的函數(shù)來進行對應(yīng)的延時業(yè)務(wù)操作。

 

5.5.1 隱式等待

隱式等待的作用是在頁面加載是隱性的進行特定時長的等待,如果在規(guī)定的等待時長內(nèi)頁面加載完畢,則會繼續(xù)進入下一個業(yè)務(wù)操作,如果沒有加載完畢,則會拋出一個超時的異常。這里其實有兩個問題,第一,隱式等待是全局性質(zhì)的,也就是說一旦你設(shè)置了個5秒,那整個程序都會使用這個等待時間類進行配置,靈活性較低;第二,如果碰到了有些頁面中的元素是局部加載的話,那整個頁面的加載是否完成也就沒有了其意義,隱式加載無法針對這樣的情況作出調(diào)整,智能度較低。所以一般來說只要是對于頁面的整體加載要求不高或者元素的加載比較穩(wěn)定的程序,都可以使用隱式等待來進行延時操作。

 

from selenium import webdriver from selenium.webdriver.common.by import By

browser = webdriver.Chrome() browser.get('https://www.baidu.com') browser.implicitly_wait(5) browser.find_element(By.XPATH, '//*[@id="kw"]').send_keys('selenium') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

 

5.5.2 顯式等待

顯式等待的作用則是使用特定的等待時長來進行某些業(yè)務(wù)邏輯判斷,如果判斷(比如元素是或否加被定位)在時間完成那繼續(xù)執(zhí)行下一個業(yè)務(wù)操作,如果判斷失敗也會拋出no such element的異常,而顯式等待的默認檢查元素周期為0.5秒。乍一看好像與隱式等待差不多,其實不然,首先顯式等待是針對頁面中某個或某組特定元素而執(zhí)行的,隱式則是全局,對所有的元素都生效;其二,顯式等待可以通過自定義條件來進行元素的定位和選取,隱式則不行。

 

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC

browser = webdriver.Chrome() browser.get('https://www.baidu.com') ele = WebDriverWait(browser, 10, 0.5).until(EC.presence_of_element_located((By.XPATH, '//*[@id="kw"]'))) ele.send_keys('selenium') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

 

5.5.3 強制等待

這個應(yīng)該是平時大家代碼中用的最多的等待方式了吧,sleep是針對線程進行掛起的一種等待方式,等待時長根據(jù)指定的參數(shù)來進行決定。最大的好處就是簡單粗暴,無任何邏輯在里面,所以也被稱為強制等待。

 

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.XPATH, '//*[@id="kw"]').send_keys('selenium') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

 
那么以上的三種等待方式其實各有各的特點與缺點,三者之間沒有絕對的好用和不好用,而在我們的日常工作場景中也希望大家可以根據(jù)實際的情況有選擇性的使用。

 
 

5.6 超時等待

元素加載超時我們可以使用以上三種延時方式來進行處理,那么頁面超時了又該如何操作呢?selenium也為我們準備了兩個函數(shù)來對應(yīng)這樣的局面。
 
頁面加載超時

browser.set_page_load_timeout(30) 
  • 1

這里推薦將超時的時間有效的拉長,不宜過短。過短的超時時間容易導(dǎo)致整體頁面出現(xiàn)未加載html代碼情況下直接令驅(qū)動無法工作的情況。
 
 
頁面異步j(luò)s或ajax操作超時

browser.set_script_timeout(30) 
  • 1

這個函數(shù)是用于execute_async_script()相關(guān)的異步j(luò)s操作超時報錯,由于是異步操作,等待時間同理也不易過短。

 
 

5.7 鍵鼠操作

瀏覽器中鍵盤與鼠標的操作也是不可或缺的重要一環(huán),在被測對象的業(yè)務(wù)要求中往往占有不少的戲份。

 
文字輸入

browser.find_element(By.ID, 'kw').send_keys('selenium') 
  • 1

 
點擊

browser.find_element(By.ID, 'kw').click() 
  • 1

 
點擊并按住不放(左鍵長按),這些模擬鼠標操作需要導(dǎo)入ActionChains包

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw') act.click_and_hold(ele).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
右鍵點擊

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw') act.context_click(ele).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
雙擊

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw') act.double_click(ele).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
拖拽元素至另一個元素處,ele_a 為source,ele_b 為target

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele_a = browser.find_element(By.ID, 'btn_a') ele_b = browser.find_element(By.ID, 'btn_b') act.drag_and_drop(ele_a, ele_b).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

 
拖拽元素至指定位置后松開,元素后為x,y坐標值

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'btn_a') act.drag_and_drop_by_offset(ele, 200, 100).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

 
鼠標移動至指定元素

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'btn_a') act.move_to_element(ele).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

 
按下指定的鍵位(示例代碼中是回車鍵)

from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw').send_keys('selenium') act.key_down(Keys.ENTER).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

 
松開指定的鍵位,這里也可以用鏈式寫法

from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw').send_keys('selenium') act.key_down(Keys.ENTER) act.key_up(Keys.ENTER) # 鏈式寫法 act.key_down(Keys.ENTER).act.key_up(Keys.ENTER).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

 
移動鼠標到指定坐標位置

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw').send_keys('selenium') act.move_by_offset(100, 200).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
移動到距離指定元素多少距離的位置(從左上角0, 0開始計算)

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw').send_keys('selenium') act.move_to_element_with_offset(ele, 100, 200).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
在指定元素位置松開鼠標

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw').send_keys('selenium') act.click_and_hold(ele).release(ele).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
發(fā)送指定的鍵或者內(nèi)容至指定元素

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw').send_keys('selenium') act.send_keys_to_element(ele, 'selenium').perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
暫停所有操作,默認單位為秒

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw').send_keys('selenium') act.context_click(ele).pause(5).double_click(ele).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
 

5.8 組件操作

頁面中也存在著很多不同種類的組件,比如單選框、多選框、下拉列表、選項卡等。這些操作也可以通過selenium提供的函數(shù)進行實現(xiàn)。

 
清除指定元素中的內(nèi)容(輸入框等)

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw') ele.send_keys('selenium') sleep(2) ele.clear() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

 
提交確認(類似于Keys.ENTER的效果)

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw') ele.send_keys('selenium') sleep(2) ele.submit() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

 
下拉列表,我們就可以使用Select方法來實現(xiàn)選取操作
使用Select方法需要從selenium.webdriver.support.select導(dǎo)入該方法
例如下圖中某網(wǎng)站的下拉列表對象

在這里插入圖片描述

 
html構(gòu)造如下
在這里插入圖片描述

 
select_by_index()方法

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.select import Select

browser = webdriver.Chrome() browser.get('https://www.xxxx.com') ele = browser.find_element(By.ID, 'input_factor_gj_count') # 需要注意下標要從0開始,選擇1%那一項 Select(ele).select_by_index('0') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
select_by_value()方法

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.select import Select

browser = webdriver.Chrome() browser.get('https://www.xxxx.com') ele = browser.find_element(By.ID, 'input_factor_gj_count') # 指定元素的value屬性值,選擇1%那一項 Select(ele).select_by_value('0.01') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
select_by_value()方法

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.select import Select

browser = webdriver.Chrome() browser.get('https://www.xxxx.com') ele = browser.find_element(By.ID, 'input_factor_gj_count') # 指定元素的文本值,選擇1%那一項 Select(ele).select_by_visible_text('1%') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
框架切換(Frame)
如果在頁面中定位某一個元素失敗并檢查其屬性并沒有問題時,就該考慮是否在祖先節(jié)點中是否存在frame或者iframe標簽。這樣的頁面就表名存在多層框架嵌套,這時我們就需要進行框架切換的操作,來準確定位到指定元素。

例如某頁面存在兩層frame嵌套,內(nèi)部框架的xpath為://*[@id="mainDiv"]/iframe,此時如果定位某個輸入框失敗之后,我們就應(yīng)該轉(zhuǎn)而跳入該frame內(nèi)進行元素定位。
 

from selenium import webdriver from selenium.webdriver.common.by import By

browser = webdriver.Chrome() browser.get('https://www.xxxx.com') # 定位到指定的frame path = browser.find_element(By.XPATH, '//*[@id="mainDiv"]/iframe') # 切換至該frame內(nèi) browser.switch_to_frame(path) ele = browser.find_element(By.CLASS_NAME, 'input') ele.send_keys('selenium') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

 
標簽頁切換
我們?yōu)g覽器在使用中一般會打開多個瀏覽窗口,也就是多個標簽頁。此時我們就可以通過每個標簽頁的句柄來進行定位和互相切換。

switch_to_window()
我們利用瀏覽器窗口的句柄來進行標簽頁的切換

from selenium import webdriver from selenium.webdriver.common.by import By

browser = webdriver.Chrome() browser.get('https://www.baidu.com') # 第一個窗口的句柄下標為0,打開第二個就是1 browser.switch_to_window(browser.window_handles[1]) # 此時就會使用第二個標簽頁去訪問淘寶 browser.get('https://www.taobao.com') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

 
彈窗處理
頁面中時常也存在著各類的彈窗,比如警告、確認、提示等等,那么對于這些彈窗我們也有著相應(yīng)的業(yè)務(wù)處理方法。
 
首先我們需要明確的是每種類型的彈窗中元素也是各不相同,所以我們針對不同的彈窗使用不同的屬性來定位和操作。

 
警告彈窗
一般來說就是告知到使用者執(zhí)行某些操作與頁面之后將要注意的事項,這種窗口只需確認。

from time import sleep from selenium import webdriver from selenium.webdriver.common.by import By

browser = webdriver.Chrome() browser.get('https://www.xxxx.com') browser.find_element(By.ID, 'btn_tg_title').click() sleep(1) # 在警告彈窗中點擊確認按鈕 browser.switch_to_alert().accept() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
確認彈窗
多用于在用戶執(zhí)行提交操作后的動作確認,有確認和取消兩個選項。

from time import sleep from selenium import webdriver from selenium.webdriver.common.by import By

browser = webdriver.Chrome() browser.get('https://www.xxxx.com') browser.find_element(By.ID, 'btn_submit').click() sleep(1) #確認二選一 browser.switch_to_alert().accept() #取消二選一 browser.switch_to_alert().dismiss() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

 
提示彈窗
這個通常用來處理用戶信息交互的場景,用戶可以通過彈窗輸入一些文字信息,來傳遞與進行后續(xù)的業(yè)務(wù)處理。

from time import sleep from selenium import webdriver from selenium.webdriver.common.by import By

browser = webdriver.Chrome() browser.get('https://www.xxxx.com') browser.find_element(By.ID, 'btn_info_inquiry').click() sleep(1) # 這里傳遞信息到提示彈窗,警告與確認兩類彈窗不可使用,會報錯 browser.switch_to_alert().send_keys('20100909') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
 

5.9 鑒權(quán)操作

既然是web自動化測試,那我們又怎么能少了Cookie的相關(guān)操作呢?用戶的狀態(tài)和業(yè)務(wù)請求都的需要用他來進行鑒權(quán)。在selenium中對Cookie進行操作其實也很簡單,首先我們需要手動的登錄被測網(wǎng)站一次,待網(wǎng)站Cookie存入本地后即可使用Selenium自帶的函數(shù)對齊進行業(yè)務(wù)操作。

 
首先我們獲取對應(yīng)網(wǎng)站的Cookie值

import json from selenium import webdriver

browser = webdriver.Chrome() browser.get('https://www.baidu.com') # 寫入保存為文件還是直接打印至控制臺,各取所需 with open('cookies.txt', 'w') as f: f.write(json.dumps(browser.get_cookies())) cookies = browser.get_cookies() print(cookies) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

 
接下來我們簡單的對獲得的Cookie進行處理

# 刪除所有的cookies browser.delete_all_cookies() # 循環(huán)打印cookie中的name和value for c in cookies: # 查看打印出的cookie對應(yīng)的鍵值對 print("%s : %s" % (c['name'], c['value'])) # 根據(jù)自己的業(yè)務(wù)需求進行cookie的增刪改 cookie = {"name": "xxxx", "value": "xxxx"} # 最后添加即可 driver.add_cookie(cookie) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

 
 

5.9 js操作

Selenium也為我們提供了可執(zhí)行js腳本相關(guān)的函數(shù),他們的作用是在某些頁面中模擬一些業(yè)務(wù)動作(畫面滑動,選擇日期等)。在一些僅靠webdriver無法實現(xiàn)的業(yè)務(wù)場景中,我們就可以依靠此函數(shù)來輔助測試目的的達成。

 

js的查找元素方法(ID)

document.getElementById("id") 
  • 1

 
js的查找元素方法(name)

document.getElementsByName('name') 
  • 1

 
js的查找元素方法(class)

document.getElementsByClassName("class_name") 
  • 1

 
js的查找元素方法(tag)

document.getElementsByTagName('tag_name') 
  • 1

 
js的查找元素方法(css)

document.querySelector("css selector") 
  • 1

 
js的查找元素方法(css_list)

document.querySelectorAll("css selector") 
  • 1

 
execute_script()
從上可以看出其實js的定位元素方法和selenium中的差不多,接下來我們就可以將需要執(zhí)行的js語句放入到執(zhí)行函數(shù)中使用。

from selenium import webdriver

browser = webdriver.Chrome() browser.get('https://www.baidu.com') # 定位后修改指定元素的value屬性 js_script_exec = 'document.getElementById("form_motion").value="list_modify";' browser.execute_script(js_script_exec) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

 
 

6. 注意點與小技巧

  1. 對于某些動態(tài)div標簽(窗口),一般的方法不太奏效的情況下,可以嘗試下switch_to_default_content()方法,跳轉(zhuǎn)到最外層;

  2. 使用模擬鍵鼠操作的時候,無論是單獨使用還是鏈式寫法,記得在結(jié)尾加上perform()方法進行執(zhí)行;

  3. 如果元素定位時報錯element click intercepted,記得檢查界面上是否有其他元素進行覆蓋,元素有可能也是具有隱藏屬性的;

  4. 元素過期報錯element is not attached to the page document,可以嘗試重新刷新頁面,這里不推薦直接使用refresh方法,還是養(yǎng)成好習(xí)慣先懟上try…except…捕捉到異常后在進行刷新或重置操作;

  5. 對于屬性值為動態(tài)的元素,墻裂推薦使用CSS selector或者xpath方法來進行元素定位,正則表達式也推薦大家最好能掌握;

  6. 如果前期對xpath的相對路徑寫法比較頭疼,推薦使用F12調(diào)試工具自帶的元素復(fù)制功能,在你想要復(fù)制的元素所在的標簽對這行右鍵,選擇copy —— Copy XPath選項即可;

  7. 輸入框默認存在內(nèi)容想要刪除再輸入信息的話,不推薦模擬鍵盤操作Ctrl+A,然后模擬退格鍵,試試clear()方法吧;

  8. 抓不到元素可以使用延時方法,輸入文字也是一樣的道理,業(yè)務(wù)場景中需要大量輸入文字的,無論是從文件中還是提取又或者是遍歷,出現(xiàn)少字漏字的話,同樣也可以使用延時的方法,適當?shù)姆怕幚淼乃俣龋?

  9. 在頁面中總會有些不可見的元素,這種情況使用is_displayed()方法即可快速定位找到;

  10. 有些被測頁面需要驗證碼,無論是手機的還是圖片驗證,和開發(fā)同學(xué)溝通一下,留個萬能的就行了,其本身的功能手工回歸一下即可,不必太過糾結(jié);

  11. 三方登錄功能也是如此,不推薦直接使用web自動化去搞,三方的一般是不開源的,有這折騰的時間還不如跑跑接口和黑盒,自動化的話繞過去即可;

  12. 自動化測試用例這塊的話博主還是推薦不要有依賴,和功能測試用例同理,每次的執(zhí)行順序或者數(shù)量都會根據(jù)需求與業(yè)務(wù)場景發(fā)生變化,一旦依賴了會大大增加測試同學(xué)的維護成本,后面有空我會單獨出一期自動化測試用例的文章來為大家介紹。




藍藍設(shè)計建立了UI設(shè)計分享群,每天會分享國內(nèi)外的一些優(yōu)秀設(shè)計,如果有興趣的話,可以進入一起成長學(xué)習(xí),請加藍小助,微信號:ben_lanlan,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務(wù)合作,也請與我們聯(lián)系01063334945。


分享此文一切功德,皆悉回向給文章原作者及眾讀者.
免責聲明:藍藍設(shè)計尊重原作者,文章的版權(quán)歸原作者。如涉及版權(quán)問題,請及時與我們?nèi)〉寐?lián)系,我們立即更正或刪除。


藍藍設(shè)計www.bouu.cn )是一家專注而深入的界面設(shè)計公司,為期望卓越的國內(nèi)外企業(yè)提供卓越的UI界面設(shè)計、BS界面設(shè)計 、 cs界面設(shè)計 、 ipad界面設(shè)計 、 包裝設(shè)計 、 圖標定制 、 用戶體驗 、交互設(shè)計、 網(wǎng)站建設(shè) 平面設(shè)計服務(wù)、UI設(shè)計公司、界面設(shè)計公司、UI設(shè)計服務(wù)公司、數(shù)據(jù)可視化設(shè)計公司、UI交互設(shè)計公司、高端網(wǎng)站設(shè)計公司、UI咨詢、用戶體驗公司、軟件界面設(shè)計公司

分享本文至:

日歷

鏈接

個人資料

藍藍設(shè)計的小編 http://www.bouu.cn

存檔