【Selenium學習】WebDriverApi介面和二次開發
WebDriverApi介面詳解
瀏覽器操作
1 driver.back() # 後退 2 driver.forward() # 前進 3 driver.refresh() # 重新整理
視窗操作
1 driver.get_window_size() # 獲取瀏覽器大小 2 driver.set_window_size(‘500‘,‘500‘) # 設定瀏覽器大小 3 driver.maximize_window() # 最大化瀏覽器 4 driver.current_window_handle() # 返回當前操作的瀏覽器控制代碼 5 driver.window_handles() # 返回所有開啟server的瀏覽器控制代碼
擷取當前頁面(截圖)
1 driver.get_screenshot_as_file(‘pic.png‘) # 檔名必須以小寫的.png結尾
執行JavaScript語句
1 driver.execute_script(‘JavaScript Commond‘) 2 driver.execute_script(‘window.scrollTo(0,0);‘) # 操作滾動條到瀏覽器最上面
Cookie操作
1 # 根據cookieKey,獲取cookie資訊 2 cookie = driver.get_cookie(‘cookieKey‘) 3 4 # 獲取所有cookie資訊 5 cookies = driver.get_cookies() 6 7 # 新增cookie,嚴格按照格式新增,cookie的key為name,value為value 8 driver.add_cookie({‘name‘: ‘tmp‘,‘value‘: ‘123123123‘}) 9 10 # 刪除所有cookie資訊 11 driver.delete_all_cookies() 12 13 # 根據cookieKey刪除對應cookie 14 driver.delete_cookie(‘UiCode‘)
瀏覽器控制代碼及切換
1 print(driver.window_handles) # 獲取所有開啟server的瀏覽器控制代碼,返回的是一個list 2 bl = driver.find_element_by_css_selector(‘[href="/new-index/"]‘) 3 bl.click() # 點選連線開啟一個新的頁面 4 print(driver.window_handles) # 再次獲取所有開啟server的瀏覽器控制代碼 5 handes = driver.window_handles 6 driver.switch_to.window(handes[1]) # 切換瀏覽器控制代碼到新開啟的這個頁面 7 cl = driver.find_element_by_css_selector(‘#newtag‘) 8 cl.send_keys(‘AAAA‘) 9 driver.close() # 關閉當前指標指向控制代碼的頁面 10 driver.switch_to.window(handes[0]) # 手動將瀏覽器指標切換回之前的頁面 11 driver.find_element_by_css_selector(‘#i1‘).send_keys(‘EEEE‘) 12 driver.quit() # 關閉所有頁面
關閉與退出
1 driver.close() # 關閉當前頁面,關閉頁面後如果指標切換了,必須手動切回來 2 driver.quit() # 關閉所有頁面,退出驅動
ElementApi介面
1 # 根據標籤屬性名稱,獲取屬性value 2 element.get_attribute(‘style‘) 3 4 # 向輸入框輸入字串 如果input的type為file型別 可以輸入檔案絕對路徑上傳檔案 5 element.send_keys() 6 7 # 清除文字內容 8 element.clear() 9 10 # 滑鼠左鍵點選操作 11 element.click() 12 13 # 通過屬性名稱獲取屬性 14 element.get_property(‘id‘) 15 16 # 返回元素是否可見 True or False 17 element.is_displayed() 18 19 # 返回元素是否被選中 True or False 20 element.is_selected() 21 22 # 返回標籤元素的名字 23 element.tag_name 24 25 # 獲取當前標籤的寬和高 26 element.size 27 28 # 獲取元素的文字內容 29 element.text 30 31 # 模仿回車按鈕 提交資料 32 element.submit() 33 34 # 獲取當前元素的座標 35 element.location 36 37 # 擷取圖片 38 element.screenshot()
彈框處理
1 driver.find_element_by_css_selector(‘#confirm‘).click() # 點選按鈕,彈出彈框 2 print(driver.switch_to.alert.text) # 列印彈框返回的文字文字 3 driver.switch_to.alert.accept() # 確認 4 driver.switch_to.alert.dismiss() # 取消
常見異常
1 NoSuchElementException:沒有找到元素 2 3 NoSuchFrameException:沒有找到iframe 4 5 NoSuchWindowException:沒找到視窗控制代碼handle 6 7 NoSuchAttributeException:屬性錯誤 8 9 NoAlertPresentException:沒找到alert彈出框 10 11 ElmentNotVisibleException:元素不可見 12 13 ElementNotSelectableException:元素沒有被選中 14 15 TimeoutException:查詢元素超時
ActionChainsApi介面詳解
UI自動化測試過程中,經常遇到那種,需要滑鼠懸浮後,要操作的才會元素出現的這種場景,那麼我們就要模擬滑鼠懸浮到某一個位置,做一系列的連貫操作,Selenium給我們提供了ActionChains模組。
引入方式
1 from selenium.webdriver.common.action_chains import ActionChains
move_to_element
1 # 滑鼠移動到某一個元素上,結束elementObj 2 ActionChains(driver).move_to_element(e) 3 4 # 滑鼠移動到制定的座標上,引數接受x,y 5 ActionChains(driver).move_by_offset(e[‘x‘],e[‘y‘]) 6 7 例: 8 # 滑鼠懸浮操作 9 from selenium.webdriver.common.action_chains import ActionChains 10 fl = driver.find_element_by_css_selector(‘#a‘) # 獲取滑鼠要懸浮的元素 11 dis1 = driver.find_element_by_css_selector(‘#dis1‘) # 獲取要點選的按鈕 12 ActionChains(driver).move_to_element(fl).click(dis1).perform() # 鏈式程式設計,可以一直點下去
1 from selenium.webdriver.common.action_chains import ActionChains 2 from selenium import webdriver 3 import time 4 driver = webdriver.Chrome() 5 driver.maximize_window() 6 driver.get(‘http://ui.imdsx.cn/uitester/‘) 7 time.sleep(2) 8 driver.execute_script(‘window.scrollTo(0,0);‘) 9 time.sleep(1) 10 a = driver.find_element_by_id(‘a‘).location # 獲取元素座標,返回的是一個字典 11 # {‘x‘: 716,‘y‘: 112} 12 dis = driver.find_element_by_id(‘dis1‘) 13 ActionChains(driver).move_by_offset(a[‘x‘],a[‘y‘]).double_click(dis).perform()
實際上ActionChains這個模組的實現的核心思想就是,當你呼叫ActionChains的方法時,不會立即執行,而是會將所有的操作按順序存放在一個List裡,當你呼叫perform()方法時,佇列中的時間會依次執行。
drag_and_drop
1 # 將source元素拖放至target元素處,引數為兩個elementObj 2 ActionChains(driver).drag_and_drop(source=source,target=target) 3 4 # 將一個source元素 拖動到針對source坐上角坐在的x y處 可存在負寬度的情況和負高度的情況 5 ActionChains(driver).drag_and_drop_by_offset(source,x,y) 6 7 # 這種也是拖拽的一種方式,都是以源元素的左上角為基準,移動座標 8 ActionChains(driver).click_and_hold(dom).move_by_offset(169,188).release().perform() 9 10 例子: 11 # 拼圖,拖動圖片到指定位置 12 from selenium.webdriver.common.action_chains import ActionChains 13 gl = driver.find_element_by_css_selector(‘[href="/move/"]‘) 14 gl.click() 15 handes = driver.window_handles 16 driver.switch_to.window(handes[1]) 17 source = driver.find_element_by_css_selector(‘#dragger‘) 18 target = driver.find_element_by_css_selector(‘#i1‘) 19 source1 = driver.find_element_by_css_selector(‘#dragger1‘) 20 target1 = driver.find_element_by_css_selector(‘#i2‘) 21 source2 = driver.find_element_by_css_selector(‘#dragger2‘) 22 target2 = driver.find_element_by_css_selector(‘#i3‘) 23 source3 = driver.find_element_by_css_selector(‘#dragger3‘) 24 target3 = driver.find_element_by_css_selector(‘#i4‘) 25 # drag_and_drop 拖拽 26 ActionChains(driver).drag_and_drop(source,target).drag_and_drop(source1,target1).drag_and_drop(source2,target2).drag_and_drop(source3,target3).perform()
click
1 # 單擊事件,可接受elementObj 2 ActionChains(driver).click() 3 4 # 雙擊事件,可接受elementObj 5 ActionChains(driver).double_click() 6 7 # 點選滑鼠右鍵 8 ActionChains(driver).context_click() 9 10 # 點選某個元素不鬆開,接收elementObj 11 ActionChains(driver).click_and_hold() 12 13 # # 某個元素上鬆開滑鼠左鍵,接收elementObj 14 ActionChains(driver).release()
key_up與key_down
有時我們需要模擬鍵盤操作時,那麼就需要用到ActionChains中的key操作了,提供了兩個方法,key_down與key_up,模擬按下鍵盤的某個鍵子,與鬆開某個鍵子,接收的引數是按鍵的Keys與elementObj。可以與send_keys連用(例:全選、複製、剪下、貼上)
1 # key_down 模擬鍵盤摁下某個按鍵 key_up 鬆開某個按鍵,與sendkey連用完成一些操作,每次down必須up一次否則將出現異常 2 ActionChains(driver).key_down(Keys.CONTROL,dom).send_keys(‘a‘).send_keys(‘c‘).key_up(Keys.CONTROL)3 .key_down(Keys.CONTROL,dom1).send_keys(‘v‘).key_up(Keys.CONTROL).perform()
Keys 實際是Selenium提供的一個鍵盤事件模組,在模擬鍵盤事件時需要匯入Keys模組
引入方式
1 from selenium.webdriver.common.keys import Keys
Switch與SelectApi介面詳解
我們在UI自動化測試時,總會出現新建一個tab頁面、彈出一個瀏覽器級別的彈框或者是出現一個iframe標籤,這時我們用WebDriver提供的Api介面就無法處理這些情況了。需要用到Selenium單獨提供的模組switch_to模組
SwitchToWindows
1 handles = driver.window_handles 2 3 # SwitchToWindows接受瀏覽器TAB的控制代碼 4 driver.switch_to.window(handles[1])
例子:
1 # 瀏覽器控制代碼及指標切換 2 print(driver.window_handles) # 獲取所有開啟server的瀏覽器控制代碼,返回的是一個list 3 bl = driver.find_element_by_css_selector(‘[href="/new-index/"]‘) 4 bl.click() # 點選連線開啟一個新的頁面 5 print(driver.window_handles) # 再次獲取所有開啟server的瀏覽器控制代碼 6 handes = driver.window_handles 7 driver.switch_to.window(handes[1]) # 切換瀏覽器控制代碼到新開啟的這個頁面 8 cl = driver.find_element_by_css_selector(‘#newtag‘) 9 cl.send_keys(‘AAAA‘) 10 driver.close() # 關閉當前指標指向控制代碼的頁面 11 driver.switch_to.window(handes[0]) # 手動將瀏覽器指標切換回之前的頁面 12 driver.find_element_by_css_selector(‘#i1‘).send_keys(‘EEEE‘) 13 driver.quit() # 關閉所有頁面
SwitchToFrame
1 # SwitchToFrame支援id、name、frame的element 2 3 # 接受定位到的iframe的Element,這樣就可以通過任意一種定位方式進行定位了 4 frameElement = driver.find_element_by_name(‘top-frame‘) 5 driver.switch_to.frame(frameElement) 6 7 # 通過fame的name、id屬性定位 8 driver.switch_to.frame(‘top-frame‘) 9 10 # 當存在多層iframe巢狀時,需要一層一層的切換查詢,否則將無法找到 11 driver.switch_to.frame(‘top-frame‘) 12 driver.switch_to.frame(‘baidu-frame‘) 13 14 # 跳轉到最外層的頁面 15 driver.switch_to.default_content() 16 17 # 多層Iframe時,跳轉到上一層的iframe中 18 driver.switch_to.parent_frame()
例子:
1 # 多層iframe切換,需要一層一層進入,但是能從任意一層切換到最外層 2 # 切換到top-frame 3 driver.switch_to.frame(‘top-frame‘) 4 import time 5 time.sleep(1) 6 # 輸入newtag文案 7 driver.find_element_by_css_selector(‘#newtag‘).send_keys(‘XXXX‘) 8 # 切換到baidu-frame 9 driver.switch_to.frame(‘baidu-frame‘) 10 time.sleep(1) 11 # 輸入kw文案 12 driver.find_element_by_css_selector(‘#kw‘).send_keys(‘YYYY‘) 13 # 返回上一層frame,即top-frame 14 driver.switch_to.parent_frame() 15 # 清空top-frame的輸入 16 driver.find_element_by_css_selector(‘#newtag‘).clear() 17 # 再切換到baidu-frame 18 driver.switch_to.frame(‘baidu-frame‘) 19 # 再清空baidu-frame的輸入 20 driver.find_element_by_css_selector(‘#kw‘).clear() 21 # 切換到最外層frame 22 driver.switch_to.default_content() 23 # 輸入i1文案 24 driver.find_element_by_css_selector(‘#i1‘).send_keys(‘NNNN‘)
SwitchToAlert
1 # alert 實際上也是Selenium的一個模組 2 from selenium.webdriver.common.alert import Alert 3 4 # 也可以通過Webdriver的switch_to來呼叫 5 6 # 點選確認按鈕 7 driver.switch_to.alert.accept() 8 9 # 如果是確認彈框,相當於點選需要和X按鈕 10 driver.switch_to.alert.dismiss() 11 12 13 # 如果alert上有文字框時,可以輸入文字。(注: 沒遇到過) 14 driver.switch_to.alert.send_keys() 15 16 # 返回Alert上面的文字內容 17 text = driver.switch_to.alert.text
例子:
1 # 彈框處理 2 driver.find_element_by_css_selector(‘#confirm‘).click() # 點選按鈕,彈出彈框 3 print(driver.switch_to.alert.text) # 列印彈框返回的文字文字 4 driver.switch_to.alert.accept() # 確認 5 driver.switch_to.alert.dismiss() # 取消
Select
在UI自動化測試過程中,經常會遇到一些下拉框,如果我們基於Webdriver操作的話就需要click兩次,而且很容易出現問題,實際上Selenium給我們提供了專門的Select(下拉框處理模組)。
1 # 通過select選項的索引來定位選擇對應選項(從0開始計數) 2 Select(s).select_by_index(5) 3 4 # 通過選項的value屬性值來定位 5 Select(s).select_by_value(‘2‘) 6 7 # 通過選項的文字內容來定位 8 Select(s).select_by_visible_text(‘牡丹江‘) 9 10 # 返回第一個選中的optionElement物件 11 Select(s).first_selected_option 12 13 # 返回所有選中的optionElement物件 14 Select(s).all_selected_options 15 16 # 取消所有選中的option 17 Select(s).deselect_all() 18 19 # 通過option的index來取消對應的option 20 Select(s).deselect_by_index(1) 21 22 # 通過value屬性,來取消對應option 23 Select(s).deselect_by_value(‘‘) 24 25 # 通過option的文字內容,取消對應的option 26 Select(s).deselect_by_visible_text(‘‘)
例子:
1 # 點選下拉選單再點選一個值 2 from selenium.webdriver.support.select import Select 3 driver.get(‘http://ui.imdsx.cn/html/‘) 4 driver.execute_script(‘window.scrollTo(0,1500);‘) 5 select = driver.find_element_by_xpath(‘//select[1]‘) 6 # 例項化select,接收一個select標籤,如果不是select標籤則拋異常 7 Select(select).select_by_value(‘2‘) # 通過select標籤的option中的value的值定位 8 Select(select).select_by_index(‘2‘) # 通過select標籤的option中的下標定位,從0開始
如果一個標籤下還有子集,可以繼續在這個標籤小查詢,如下:
1 driver.get(‘http://ui.imdsx.cn/html/‘) 2 driver.execute_script(‘window.scrollTo(0,1500);‘) 3 select = driver.find_element_by_xpath(‘//select[1]‘) 4 # 獲取select標籤下所有的option的元素 5 options = select.find_elements_by_tag_name(‘option‘) 6 for opt in options: 7 print(opt.get_attribute(‘value‘)) # 迴圈獲取select(‘//select[1]‘)標籤下的option的value屬性 8 print(opt.get_attribute(‘index‘)) # 迴圈獲取select(‘//select[1]‘)標籤下的option的下標
二次開發
1 #!/usr/bin/env python 2 # encoding: utf-8 3 import unittest 4 5 import json 6 from selenium.webdriver.common.keys import Keys 7 from selenium.webdriver.support.select import Select 8 from uitester.common.logger import * 9 from selenium import webdriver 10 from selenium.webdriver.support.wait import WebDriverWait 11 from selenium.webdriver.common.by import By 12 from selenium.webdriver.chrome.options import Options 13 from selenium.webdriver import ActionChains 14 from selenium.webdriver.support import expected_conditions as EC 15 from selenium.common.exceptions import * 16 17 18 class BasePage(object): 19 # Page基類,所有其他Page全部繼承此類,負責元素和driver方法的封裝 20 def __init__(self,driver): 21 self.driver = driver 22 self.mgr_info = {} 23 self.agent_info = {} 24 self.read_config() 25 self.mgr_version = self.mgr_info.get(‘stable_platform_ver‘,‘‘) 26 mgr_version_split = self.mgr_version.split(‘.‘) 27 # 方便版本比較,e.g. 3216 28 self.mgr_version_format = int(mgr_version_split[0] + mgr_version_split[1] + mgr_version_split[2][:2]) 29 30 def read_config(self): 31 # 方便適配版本 32 # uitester會以包的形式被引用 33 # config_path = os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))),‘config.json‘)) 34 for name in os.listdir("C:\\jenkins\\workspace\\"): 35 if ‘agent_‘ in name: 36 agent_name = name 37 break 38 config_path = os.path.join(r‘C:\Jenkins\workspace\{}‘.format(agent_name),‘config.json‘) 39 if os.path.exists(config_path): 40 with open(config_path) as f: 41 config_content = eval(f.read()) 42 config_content = json.loads(json.dumps(config_content)) 43 self.mgr_info = config_content[‘mgr_cfg‘] 44 self.agent_info = config_content[‘agent_cfg‘] 45 else: 46 LOG_DEBUG(‘配置檔案config.json不存在!‘) 47 48 def find_element(self,loc,strict=False,timeout=10): 49 """ 50 51 :param loc: 52 :param strict: type: bool e.g.True:若找不到元素直接拋錯,False:若找不到元素,日誌列印報錯,不拋錯 53 :return: 54 """ 55 try: 56 WebDriverWait(self.driver,timeout,0.5).until(EC.presence_of_element_located(loc)) 57 except Exception as e: 58 LOG_DEBUG(‘[1] 頁面未找到元素,loc: {}‘.format(loc)) 59 try: 60 WebDriverWait(self.driver,0.5).until(EC.visibility_of_element_located(loc)) 61 return self.driver.find_element(*loc) 62 except Exception as e: 63 LOG_DEBUG(‘[1] ERROR [find_element]: {}‘.format(e)) 64 LOG_DEBUG(‘[1] 頁面未找到元素,loc: {}‘.format(loc)) 65 self.refresh() 66 time.sleep(8) 67 try: 68 WebDriverWait(self.driver,0.5).until(EC.presence_of_element_located(loc)) 69 except Exception as e: 70 LOG_DEBUG(‘[2] 頁面未找到元素,loc: {}‘.format(loc)) 71 try: 72 WebDriverWait(self.driver,0.5).until(EC.visibility_of_element_located(loc)) 73 return self.driver.find_element(*loc) 74 except Exception as e: 75 LOG_DEBUG(‘[2] ERROR [find_element]: {}‘.format(e)) 76 LOG_DEBUG(‘[2] 頁面未找到元素,loc: {}‘.format(loc)) 77 if strict: 78 raise e 79 80 def find_elements(self,timeout=10): 81 try: 82 WebDriverWait(self.driver,0.5).until(EC.presence_of_element_located(loc)) 83 except Exception as e: 84 LOG_DEBUG(‘ERROR [find_element]: {}‘.format(e)) 85 LOG_DEBUG(‘頁面未找到元素: {}‘.format(loc)) 86 try: 87 WebDriverWait(self.driver,0.5).until(EC.visibility_of_element_located(loc)) 88 return self.driver.find_elements(*loc) 89 except Exception as e: 90 LOG_DEBUG(‘ERROR [find_elements]: {}‘.format(e)) 91 LOG_DEBUG(‘頁面未找到元素: {}‘.format(loc)) 92 if strict: 93 raise e 94 95 def clear(self,loc=None,ele=None,strict=False): 96 if not (loc or ele): 97 LOG_ERROR(‘loc: {},ele: {},請至少輸入一個有效引數!‘.format(loc,View Code