天天看點

selenium-web自動化測試

Web應用包含超文本标記語言(HTML)、層疊樣式表演(CSS)、JavaScript腳本的Web頁面。

HTML表單由不同類型的元素組成的,包含<form>、<input>、<button>、<label>

1 webdriver的API與定位元素

from selenium import webdriver

b = webdriver.Firefox()
b.get('http://www.baidu.com') #輸入url
print(b.title) #列印元素
print(b.current_url) #列印url      

Webdriver常用方法:

selenium-web自動化測試

1.1 8種元素定位的方法

元素名稱 webdriver API 說明
id find_element_by_id()
name find_element_by_name()
class name find_element_by_class_name()
tag name find_element_by_tag_name()
link text find_element_by_link_text()
partial link text find_element_by_partial_link_text()
xpath find_element_by_xpath()
css selector find_element_by_css_selector()
>>> ele = b.find_element_by_id('kw')
>>> ele1=b.find_element_by_name('wd')       

1.2 元素操作方式

方法 說明
clear 清除元素内容
send_keys 模拟按鍵輸入
click 點選
submit 送出表單
>>> ele.clear()
>>> ele.send_keys('自動化測試')
>>> b.back() #退回
>>> ele1.send_keys('測試')      
>>> ele2= b.find_element_by_class_name('s_ipt')
>>> ele2.send_keys('selenium')
>>> ele3=b.find_element_by_tag_name('input')
>>> ele3.size
{'height': 0.0, 'width': 0.0}
>>> ele3.id
'3e2e100e-b754-4ce1-b1d7-7872079247da'
>>> ele2.id
'2f622532-63aa-4018-8a4c-683f382ae01a'
#id不同,右鍵檢視頁面源代碼,有其他input      

WebElement功能清單:

功能/屬性 描述 執行個體
size 擷取元素的大小 element.size
tag_name 擷取元素的HTML标簽名稱 element.tag_name
text 擷取元素的文本值 element.text
>>> b.get('http://www.dji.com')
>>> b.maximize_window()  #最大化視窗
>>> ele=b.find_element_by_link_text('消費級産品')
>>> ele.click()
>>> ele1=b.find_element_by_partial_link_text('消費級')
>>> ele1.click()
>>> ele_css=b.find_element_by_css_selector('html.js.no-touch.csstransforms3d.csstransitions body.dji-zh-CN.dji-pc nav#site-header.dui-navbar.site-header.collapsed div.navbar-container div#siteHeaderNavbar ul.navbar-category li.category-item a.ga-data') 
#審查元素後複制css路徑
>>> ele_css=b.find_element_by_css_selector('input[class=\'search-input\']')  #可以定位任一進制素
>>> ele_css.send_keys('社群')      

如果沒有元素與之比對,則抛出NoSucnElementException異常。

其他WebElement常用方法:

selenium-web自動化測試

1.3 xpath定位

  • xml路徑語言:用來确定xml文檔中某部分位置的語言;
  • xpath用于在xml文檔中通過元素和屬性進行導航;
  • xpath是一個W3C标準;
  • 對xml/html有一定的了解。

xpah節點類型:元素、屬性、文本、命名空間、指令處理、注釋及文檔。

xpath:通過路徑表達式從xml文檔中選取節點或節點設定

表達式 結果
/xxx 選取根節點xx
/xxx/yyy 根據絕對路徑選擇元素
//xxx 整個文檔掃描,找到所有xxx元素
//xxx/yyy 所有父元素為xxx的yyy元素
. 選取目前節點的父元素節點
.. 選取父元素位址
//xxx[@id] 選取所有xxx元素中有id屬性的元素
//xxx[@id=yyy] 選取所有xxx元素id屬性為yyy的元素
b.get(r'C:\Users\zhouxy\Desktop\bookmark.html')
ele = b.find_element_by_xpath('/html') #絕對路徑
ele.text 
ele = b.find_element_by_xpath('/html/body/form/input') #預設第一個輸入框
ele.get_attribute('type') #-->‘text’

#第二個輸入框
ele1=b.find_element_by_xpath('/html/body/from/input[2]')

#并通過input下标找到
e= find.element_by_xpath('//input') #相對路徑
e.get_attribute('name')

ele = b.find_element_by_xpath('//input/..')
ele.tag_name #-->form 上一級目錄

e = b.find_element_by_xpath('//input[@id]') #'//input[@name="xxx"]'
      
#周遊所有
ele= b.find_element_by_xpath('//*') #-->html
#運用函數
ele= b.find_element_by_xpath('//*[count[input]=2]') #-->form
#從表單開始定位
ele= b.find_element_by_xpath('//form[@id=“form”/span/input]')  
#組合定位
ele= b.find_element_by_xpath('//input[@name="wd"] and @id="kw"]')      
表達式 結果
//*[count(xxx)=2] 統計xxx元素個數=2的節點
//*[local-name()='xxx'] 找到tag為xxx的元素
//*[starts-with(local_name(),'x')] 找到所有tag以x開頭的元素
//*[contain(local_name())=3] 找到所有tag包含x的元素
//*[string-length(local-name())=3] 找到所有tag長度為3的元素
//xxx | //yyy 多個路徑查找
ele1 = b.find_element_by_xpath('//*[local-name()="input"]')  #相當于('//input'),預設取第一個input

ele2 = b.find_element_by_xpath('//*[start-with(local-name(),"i")]')

ele3 = b.find_element_by_xpath('//*[contain(local-name(),"i")]') 

ele4 = b.find_element_by_xpath('//*[contain(local-name(),"i")]') 
ele5 = b.find_element_by_xpath('//*[contain(local-name(),"i")][last()]') #包含i的tag_name倒數第一個元素
ele5 = b.find_element_by_xpath('//*[contain(local-name(),"i")][last()]-1') #包含i目錄倒數第二個元素
ele.get_attribute('name') #擷取元素的屬性

ele6 = b.find_element_by_xpath('//*[string-length(local-name())=3]')  #長度等于3的tag_name

ele7=b.find_element_by_xpath('//title | // input[last()]')  #-->title      

1.4 css selector定位

選擇器 描述 舉例
* 通配選擇器,選擇所有的元素 *
<type> 選擇特定類型的元素,支援基本HTML标簽 h1
.<class> 選擇具有特定class的元素。 .class1
<type>.<class> 特定類型和特定class的交集。(直接将多個選擇器連着一起表示交集) h1.class1
#<id> 選擇具有特定id屬性值的元素 #id1
e= find_element_by_css_selector(".s_ipt")
e= find_element_by_css_selector("#kw")      

通過屬性選擇器定位:

​選擇器 描述 舉例
[attr] 選取定義attr屬性的元素,即使該屬性沒有值 [placeholder]
[attr="val"] 選取attr屬性等于val的元素 [placeholder="請輸入關鍵詞"]
[attr^="val"] 選取attr屬性開頭為val的元素 [placeholder^="請輸入"]
[attr$="val"] 選取attr屬性結尾為val的元素 [placeholder$="關鍵詞"]
[attr*="val"] 選取attr屬性包含val的元素 [placeholder*="入關"]
[attr~="val"] 選取attr屬性包含多個空格分隔的屬性,其中一個等于val的元素 [placeholder~="關鍵詞"]
[attr|="val"] 選取attr屬性等于val的元素或第一個屬性值等于val的元素 [placeholder|="關鍵詞"]

2 滑鼠和鍵盤事件

2.1 AcitonChains類與輸入事件

  1. from selenium.webdriver.common.action_chains import AcitonChains
  2. ActionCharis(driver):用于生成模拟使用者行為
  3. perform():執行存儲行為

2.2 滑鼠事件

表達式 說明
context_click 右擊事件
double_click 輕按兩下事件
drag_and_drop 拖動
move_to_element() 滑鼠停在一個元素上
click_and_hold 按下滑鼠左鍵在一個元素上
>>> from selenium import webdriver
>>> b = webdriver.Firefox()
>>> b.get('http://www.dji.com')
>>> from selenium.webdriver.common.action_chains import ActionChains
>>> ele=b.find_element_by_link_text('消費級産品')
>>> ActionChains(b).move_to_element(ele).perform()
>>> sub_ele=b.find_element_by_link_text('禦 Mavic Air')
>>> sub_ele.click()      
selenium-web自動化測試

2.3 鍵盤事件:send_keys()

from selenium.webdriver.common keys import Keys

表達式 說明
send_keys(Keys.BACKSPACE) 倒退鍵
send_keys(Keys.CONTRL,'a') 全選
send_keys(Keys.CONTRL,'v') 粘貼
send_keys(Keys.CONTRL,'c') 複制
send_keys(Keys.CONTRL,'x') 剪切
send_keys(Keys.ENTER') 回車
>>> s =b.find_element_by_name('q')
>>> s.sent_keys('大疆')
>>> s.clear()
>>> s.send_keys('大疆啊')
>>> from selenium.webdriver.common.keys import Keys
>>> s.send_keys(Keys.BACKSPACE)
>>> s.send_keys(Keys.CONTROL,'a')
>>> s.send_keys(Keys.CONTROL,'x')
>>> s.send_keys(Keys.CONTROL,'v')
>>> ele=b.find_element_by_link_text('大疆司空')
>>> s.send_keys(Keys.ENTER)      

3 對話框與多視窗管理

>>> d = webdriver.Firefox()
>>> d.get('http://www.baidu.com')
>>> d.find_element_by_id('kw').clear()
>>> d.find_element_by_id('kw').send_keys('大疆科技')
>>> d.find_element_by_id('su').click()
>>> d.find_element_by_partial_link_text('DJI大疆創新 - 所有産品').click()
>>> d.window_handles
['4294967297', '4294967301'] #列出所有的句柄
>>> d.current_window_handle
'4294967297' #顯示目前句柄
>>>d.switch_to_window(d.window_handles[0]) #切換句柄
>>> d.close()  #關閉tab
>>> d.quit()   #退出浏覽器      

4 下拉框處理

 需要特定的Select類并導入,from selenium.webdriver.support.select import Select

selenium-web自動化測試

5 alter對話框處理

需要先切換到彈框上的,alert = driver.switch_to_alert()

Alter方法:

swich_to_alert() 切到alter,傳回一個alter對象
accept 确認
dismiss 取消
send_keys() 有輸入框才能使用,否則報錯

>>>alert=b.swich_to_alert

6 測試腳本中的等待方法

6.1 元素等待機制

隐式等待:為了解決由于網絡延遲或利用Ajax動态加載元素所導緻的程式響應時間不一緻。當一個測試用例執行的時候,WebDriver找不到任意一個元素,将會等待,等待時間超過後,則抛出NoSuchElementException。

顯式等待:可以為腳本設定一些預置或定制化的條件,等待條件滿足後再執行測試。顯示等待可以隻作用于有同步需求的測試用例。

                  WebDriver提供WebDriverWait類和expected_conditions類來實作顯式等待。

implicitly_wait() 設定webdriver等待時間,等待時間後報異常
WebDriverWait

等待條件滿足或者逾時後退出

from selenium.webdriver.support.ui import WebDriverWait

6.2 WebDriverWair方法:

構造函數:def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY)
poll_frequency-->check-->until-->method return Not False
                      -->not until-->method return False      
import  time
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait


Url = 'http://10.10.200.86:10004/ccs-web/index.jsp'
Account = 'zhouxy'
Password = '111'

def get_ele_time(driver,times,func): return WebDriverWait(driver,times).until(func) def login_test(): b = webdriver.Firefox() #啟動浏覽器 b.get(Url) #輸入url  b.maximize_window() login_ele = get_ele_time(b,10,lambda b:b.find_element_by_xpath('/html/body/form/ \ table/tbody/tr[3]/td/table/tbody/tr[3]/td/table/tbody/tr[1]/td[7]/img')) #也可以用expected_conditions有定義好的預期等待條件 username_ele = b.find_element_by_id('j_username') #使用者名元素 username_ele.clear() #清空 username_ele.send_keys(Account) #輸入使用者名 password_ele = b.find_element_by_id('j_password') password_ele.clear() password_ele.send_keys(Password) login_ele.click() try : ele = b.find_element_by_link_text('Login fail: 錯誤的憑證') print('登入失敗') except: print('登入成功') time.sleep(10) b.close() if __name__ == '__main__': login_test()      
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

'''
10秒鐘等待浏覽器彈出的對話框,如果出現,就點選确定按鈕
'''
WebDriverWait(chromedriver,10).until(EC.alert_is_present()).accept()      

7 檔案上傳

7.1 普通上傳(通過input框)

# -*- coding: utf-8 -*-
from selenium import webdriver

driver = webdriver.Firefox()
driver.get('http://sahitest.com/demo/php/fileUpload.htm')
upload = driver.find_element_by_id('file')
upload.send_keys('d:\\baidu.py')  # send_keys
print upload.get_attribute('value')  # check value

driver.quit()      

7.2 flash上傳(非input标簽)

有幾種解決方案:

  1. autoIT,借助外力,我們去調用其生成的au3或exe檔案。
  2. Python pywin32庫,識别對話框句柄,進而操作
  3. SendKeys庫
  4. keybd_event,跟3類似,不過是模拟按鍵,ctrl+a,ctrl+c, ctrl+v…

8 檔案下載下傳

對于Firefox,需要設定Profile:

  • browser.download.dir

    :指定下載下傳路徑
  • browser.download.folderList

    :設定成 

    2

     表示使用自定義下載下傳路徑;設定成   表示下載下傳到桌面;設定成 

    1

     表示下載下傳到預設路徑
  • browser.download.manager.showWhenStarting

    :在開始下載下傳時是否顯示下載下傳管理器
  • browser.helperApps.neverAsk.saveToDisk

    :對所給出檔案類型不再彈出框進行詢問
from selenium import webdriver
from time import sleep

profile = webdriver.FirefoxProfile()
profile.set_preference('browser.download.dir', 'd:\\')
profile.set_preference('browser.download.folderList', 2)
profile.set_preference('browser.download.manager.showWhenStarting', False)
profile.set_preference('browser.helperApps.neverAsk.saveToDisk', 'application/zip')

driver = webdriver.Firefox(firefox_profile=profile)

driver.get('http://sahitest.com/demo/saveAs.htm')
driver.find_element_by_xpath('//a[text()="testsaveas.zip"]').click()
sleep(3)
driver.quit()      

9 滾動條

from selenium import webdriver
import os
dr = webdriver.Firefox()
dir = os.path.join('file:///'+os.getcwd()+'\\h1.html')
dr.get(dir)
dr.implicitly_wait(3)
js='document.getElementsByClassName("scroll")[0].scrollTop=0'
# 就是這麼簡單,修改這個元素的scrollTop就可以
dr.execute_script(js)      
document.getElementsByClassName("scroll")[0].scrollHeight # 擷取滾動條高度
document.getElementsByClassName("scroll")[0].scrollWidth # 擷取橫向滾動條寬度
document.getElementsByClassName("scroll")[0].scrollLeft=xxx # 控制橫向滾動條位置      

10 自動發送郵件

10.1 SMTP子產品發送郵件

SMTP(Simple Mail Transfer Protocol)即簡單郵件傳輸協定。

import  smtplib
from email.mime.text import MIMEText
from email.header import Header

def sent_email(SMTP_host,Username,Password,Content,Subject,Revicer):
    #1.執行個體化SMTP
    smtp = smtplib.SMTP()

    #2.連結郵件伺服器
    smtp.connect(SMTP_host)

    #3.配置發送者郵箱密碼
    smtp.login(Username,Password)

    #4.配置發送内容msg
    msg = MIMEText(Content,'html','utf-8') # 三個參數:第一個為文本内容,第二個置文本格式,第三個設定編碼
    msg['Subject']= Header(Subject,'utf-8') #郵件主題
    msg['From'] = Username
    msg['To'] = Revicer

    #5.配置發送郵箱,接收郵箱,以及發送内容
    smtp.sendmail(Username,Revicer,msg.as_string())

    #6.關閉郵件服務
    smtp.quit()

if __name__ == '__main__':
    sent_email('smtp.163.com','****@163.com','******','<html><h1>你好</h1></html>','郵件主題','****@163.com')      

10.2 email子產品

email子產品下有mime包,mime英文全稱為“Multipurpose Internet Mail Extensions”,即多用途網際網路郵件擴充,是目前網際網路電子郵件普遍遵循的郵件技術規範。

該mime包下常用的有三個子產品:text,image,multpart。

  • 構造一個郵件對象就是一個

    Message

    對象
  • 如果構造一個

    MIMEText

    對象,就表示一個文本郵件對象(如果發送内容為中文,需要選擇“plain”,要不然無法顯示)
  • 如果構造一個

    MIMEImage

    對象,就表示一個作為附件的圖檔
  • 要把多個對象組合起來,就用

    MIMEMultipart

    對象
  • MIMEBase

    可以表示任何對象。它們的繼承關系如下:
Message
+- MIMEBase
   +- MIMEMultipart
   +- MIMENonMultipart
      +- MIMEMessage
      +- MIMEText
      +- MIMEImage
           

10.2.1 添加普通文本

text = "This is a text\nHere is the link you want:\nhttp:\\www.baidu.com"
2 msg = MINEText(text, 'plain', utf-8)      

10.2.2 添加超文本

html = """
<html>  
  <body>  
    <p> 
       Here is the <a href="http://www.baidu.com" target="_blank" rel="external nofollow" >link</a> you wanted.
    </p> 
 </body>  
</html>  
"""    
msg = MIMEText(html,'html', 'utf-8')        

10.2.3 添加附件

sendfile = open('D:\\python\\sendfile.txt', 'rb').read()
msg = MINEText(sendfile, 'base64', 'utf-8')
msg['Content-type'] = 'application/octet-stream'
msg['Content-Disposition'] = 'attachment;filename= "檔案顯示名字.txt"'      

10.2.4 添加圖檔

sendimagefile=open(r'D:\pythontest\testimage.png','rb').read()
msg = MIMEImage(sendimagefile)
msg.add_header('Content-ID','<image1>')      
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.header import Header
import os

def send_file(SMTP_host,from_addr,from_pwd,to_addr,file_addr,subject):

    smtp = smtplib.SMTP(SMTP_host)

    smtp.login(from_addr,from_pwd)
    # 郵件主題/發送者/接受者
    msg = MIMEMultipart()
    msg['Subject']= Header(subject,'utf-8')
    msg['From'] = from_addr
    msg['To'] = to_addr
    # 郵件正文
    msg.attach(MIMEText('如附件所示','plain','utf-8'))
    # 郵件附件
    with open(file_addr,'rb') as f :
        file = f.read()
    att = MIMEText(file,'base64','utf-8')
    att['Content-type'] = 'application/octet-stream'
    att['Content-Dispositon'] = 'attachment;filename="test.html"' #檔案名
    msg.attach(att)

    smtp.sendmail(from_addr,to_addr,msg.as_string())
    smtp.quit()

if __name__ == '__main__':
    try:
        dir = os.path.join(os.getcwd()+'//h1.html')
        send_file('smtp.163.com','****@163.com','******','****@163.com',dir,'主題')
        print('郵件發送成功')
    except smtplib.SMTPException:
        print('Error:無法發送郵件')      

10.3 自動發送郵件

import unittest,smtplib
from test_mathfunc import TestMathFunc
from HTMLTestRunner import HTMLTestRunner
import time,os,sys
email_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(email_path)
from web_test.test_email import send_file

def SendReport(report_dir):
    # 擷取最新報告
    case_list = os.listdir(report_dir) #擷取report目錄下所有檔案,以清單形式傳回
    case_list.sort(key=lambda fn:os.path.getatime(report_dir+'\\'+fn)) #對case_list中所有元素按時間從大到小排序
    latest_report = os.path.join(report_dir,case_list[-1])
    print(latest_report)
    return latest_report

if __name__ == '__main__':
    suite = unittest.TestSuite()
    tests = [TestMathFunc('test_add'),TestMathFunc('test_minus'),TestMathFunc('test_divide')]
    suite.addTests(tests)
    now = time.strftime('%Y%m%d%H%M%S')
    with open(now+'HTMLReport.html','wb') as f:
        runner = HTMLTestRunner(stream=f,
                                title='電腦測試',
                                description = '測試報告',
                                verbosity=2)
        runner.run(suite)
    R = SendReport("C:\\Users\\zhouxy\\PycharmProjects\\untitled\\unit_test")
    try:
        send_file('smtp.163.com','****@163.com','******','****@163.com',R,'主題')
        print('郵件發送成功')
    except smtplib.SMTPException:
        print('Error:無法發送郵件')      

11 測試用例設計

selenium-web自動化測試
selenium-web自動化測試
selenium-web自動化測試

資料設計:字典形式

key val
url 打開位址
text_id 登入元素
userid/pwdid/loginid 輸入賬号元素
uname/pwd 輸入賬号資訊
errorid 檢查錯誤條件

練手網站推薦:http://sahitest.com/demo/index.html

資源推薦:https://blog.csdn.net/huilan_same/article/details/52615123

轉載于:https://www.cnblogs.com/cirr-zhou/p/8920622.html