《手把手教你》系列練習篇之9-python+ selenium自動化測試 -番外篇 - 最後一波啊!!!(詳細教程)

1. 簡介

   原本上一篇就是練習篇的最後一篇文章了,可是有的小夥伴私下反映說是作了那麼多練習,沒有一個比較綜合的demo練練手。所以宏哥在這裏又補存了一些常見的知識點進行練習,在文章最後也經過實例給小夥伴們或者童鞋們進行了一個登陸模塊的自動化測試的實例,其餘的你能夠照貓畫虎地輕鬆的搞定和實現。html

2. python-web自動化-三種等待方式

當有元素定位不到時,好比下拉框,彈出框等各類定位不到時;python

通常是兩種問題:1 、有frame ;二、沒有加等待web

下面學習三種等待方式:ajax

2.1 強制等待 sleep(xx)或者Time.sleep

是在程序運行過程當中使用time模塊中的sleep進行代碼的休眠進行強制等待,是顯式等待中的一種極端狀況。瀏覽器

這種方法簡單粗暴,無論瀏覽器是否加載完,程序都要等待規定的xx時間,時間到了才繼續執行下面的代碼。框架

不建議老是用這種等待方式,會嚴重影響程序的執行速度。經過time模塊中sleep進行代碼的暫停,可是實際使用過程當中,若是都以sleep進行控制嚴重影響了程序的運行。dom

2.1.1 參考代碼1
# coding=utf-8🔥

# 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行

# 2.註釋:包括記錄建立時間,建立人,項目名稱。
'''
Created on 2019-12-10
@author: 北京-宏哥   QQ交流羣:705269076
Project: 《手把手教你》系列練習篇之9-python+ selenium自動化測試
'''

# 3.導入模塊

import time

# 強制等待——代碼休眠

from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
time.sleep(3)

driver.quit()
2.1.2 參考代碼2
# coding=utf-8🔥

# 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行

# 2.註釋:包括記錄建立時間,建立人,項目名稱。
'''
Created on 2019-12-10
@author: 北京-宏哥   QQ交流羣:705269076
Project: 《手把手教你》系列練習篇之9-python+ selenium自動化測試
'''

# 3.導入模塊

from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
sleep(3)#強制性等待3s再執行如下代碼
print(driver.current_url)
driver.quit()#退出驅動,關閉全部窗口

2.2 隱性等待 implicitly_wait(xx)

這種方法是設置一個最長的等待時間,若是在規定時間內網頁所有元素加載完成,則執行下一步,不然一直等待時間截止才執行下一步。比強制性等待智能些編輯器

!隱性等待對整個driver的週期都起做用,因此只要設置一次便可函數

2.2.1 參考代碼1
# coding=utf-8🔥

# 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行

# 2.註釋:包括記錄建立時間,建立人,項目名稱。
'''
Created on 2019-12-10
@author: 北京-宏哥   QQ交流羣:705269076
Project: 《手把手教你》系列練習篇之9-python+ selenium自動化測試
'''

# 3.導入模塊

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException from time import ctime driver = webdriver.Firefox() # 設置隱式等待爲10秒 driver.implicitly_wait(10) driver.get("http://www.baidu.com") try: print(ctime()) driver.find_element_by_id("kw22").send_keys('selenium') except NoSuchElementException as e: print(e) finally: print(ctime()) driver.quit()

這裏能夠看到在10秒內沒有找到想要找到的元素,可是依舊執行了10秒,而後報錯,若是修改代碼爲能夠找到,代碼執行很是迅速。post

implicitly_wait()默認參數的單位爲秒,本例中設置等待時長爲10秒。首先這10秒並不是一個固定的等待時間,它並不影響腳本的執行速度。其次,它並不針對頁面上的某一元素進行等待。當腳本執行到某個元素定位時,若是元素能夠定位,則繼續執行;若是元素定位

不到,則它將以輪詢的方式不斷地判斷元素是否被定位到。假設在第6秒定位到了元素則繼續執行,若直到超出設置時長(10秒)尚未定位到元素,則拋出異常。

2.2.2 參考代碼2
# coding=utf-8🔥

# 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行

# 2.註釋:包括記錄建立時間,建立人,項目名稱。
'''
Created on 2019-12-10
@author: 北京-宏哥   QQ交流羣:705269076
Project: 《手把手教你》系列練習篇之9-python+ selenium自動化測試
'''

# 3.導入模塊

from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
driver.implicitly_wait(30)#隱性等待,最長30s
print(driver.current_url)
driver.quit()

2.3.顯性等待 WebDriverWait

WebDriverWait配合該類的until()和until_not()方法,根據條件靈活的等待

程序每隔xx秒看一眼,若是條件成立了,則執行下一步,不然繼續等待,直到超過設置的最長時間,而後拋出TimeoutException。

顯式等待是你在代碼中定義等待必定條件發生後再進一步執行你的代碼。

A. 使用前,先引用相關庫

B. 肯定元素的定位表達式

C.  使用expected_conditions對應的方法來生成判斷條件

WebDriverWait(driver,10,1).until(EC.visibility_of_element_located((By.ID,ele_locator)))
WebDriverWait(driver,10,1).until(EC.visibility_of_element_located((By.XPATH,ele_locator)))

D.  調用WebDriverWait類設置等待總時長、輪詢週期

2.3.1 參考代碼1
# coding=utf-8🔥

# 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行

# 2.註釋:包括記錄建立時間,建立人,項目名稱。
'''
Created on 2019-12-10
@author: 北京-宏哥   QQ交流羣:705269076
Project: 《手把手教你》系列練習篇之9-python+ selenium自動化測試
'''

# 3.導入模塊

#A. 使用前,先引用相關庫
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
 
driver = webdriver.Chrome()#打開Chrome瀏覽器
driver.get('https://www.baidu.com/')#打開百度
driver.find_element_by_xpath('//div[@id="u1"]//a[@name="tj_login"]').click()#點擊【登陸】;click() 方法,可模擬在按鈕上的一次鼠標單擊。
# B. 肯定元素的定位表達式
ele_locator = "TANGRAM__PSP_10__footerULoginBtn"#經過id,肯定‘用戶名登陸’元素
 
# C.  使用expected_conditions對應的方法來生成判斷條件
# EC.方法名(定位方式,定位表達式)
# EC.visibility_of_element_located(By.ID,ele_locator)#元素可見
 
# D.  調用WebDriverWait類設置等待總時長、輪詢週期
# WebDriverWait(driver, 超時時長, 調用頻率(默認0.5s)).until(可執行方法, 超時時返回的信息)
# 等待10秒鐘,每隔1秒去查看對應的元素是否可見;若是可見,繼續下一步操做;若是不可見,則繼續等待,直到10s結束,若是元素仍是不可見,則拋出超時異常
WebDriverWait(driver,10,1).until(EC.visibility_of_element_located((By.ID,ele_locator)))

driver.find_element_by_id('TANGRAM__PSP_10__footerULoginBtn').click()#點擊【用戶名登陸】
 
driver.close()#關閉當前窗口
2.3.2 參考代碼2
# coding=utf-8🔥

# 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行

# 2.註釋:包括記錄建立時間,建立人,項目名稱。
'''
Created on 2019-12-10
@author: 北京-宏哥   QQ交流羣:705269076
Project: 《手把手教你》系列練習篇之9-python+ selenium自動化測試
'''

# 3.導入模塊

from time import ctime
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 dr = webdriver.Chrome() dr.get('https://www.baidu.com') try: print(ctime()) element = WebDriverWait(dr, 10).until( EC.presence_of_element_located((By.ID, "kw")) ) # WebDriverWait(driver=self.driver, timeout=300, poll_frequency=0.5, ignored_exceptions=None) # driver:瀏覽器驅動 # timeout:最長超時等待時間 # poll_frequency:檢測的時間間隔,默認爲500ms # ignore_exception:超時後拋出的異常信息,默認狀況下拋 NoSuchElementException 異常 print("我已找到") finally: print(ctime()) dr.quit()

執行結果:

以上代碼執行後就發現,整段代碼執行速度很是快,即便我在WebDriverWait中設置10秒,也不會等待10秒的狀況,由於在不到一秒內,已經完成了加載並定位id爲「kw」的元素。

經過WebDriverWait 和 ExpectedCondition 組合使用,讓咱們的代碼執行只須要等待須要的時長,而不是固定的時長,這樣最大限度的節省時間。

 此外ExpectedCondition類中提供了不少預期條件判斷方法,省去了再建立包的功夫:

"""
title_is:判斷當前頁面的title是否等於預期
title_contains:判斷當前頁面的title是否包含預期字符串
presence_of_element_located:判斷某個元素是否被加到了dom樹裏,並不表明該元素必定可見
visibility_of_element_located:判斷某個元素是否可見. 可見表明元素非隱藏,而且元素的寬和高都不等於0
visibility_of:跟上面的方法作同樣的事情,只是上面的方法要傳入locator,這個方法直接傳定位到的element就行了
presence_of_all_elements_located:判斷是否至少有1個元素存在於dom樹中。舉個例子,若是頁面上有n個元素的class都是'column-md-3',那麼只要有1個元素存在,這個方法就返回True
text_to_be_present_in_element:判斷某個元素中的text是否 包含 了預期的字符串
text_to_be_present_in_element_value:判斷某個元素中的value屬性是否包含了預期的字符串
frame_to_be_available_and_switch_to_it:判斷該frame是否能夠switch進去,若是能夠的話,返回True而且switch進去,不然返回False
invisibility_of_element_located:判斷某個元素中是否不存在於dom樹或不可見
element_to_be_clickable - it is Displayed and Enabled:判斷某個元素中是否可見而且是enable的,這樣的話才叫clickable
staleness_of:等某個元素從dom樹中移除,注意,這個方法也是返回True或False
element_to_be_selected:判斷某個元素是否被選中了,通常用在下拉列表
element_located_to_be_selected
element_selection_state_to_be:判斷某個元素的選中狀態是否符合預期
element_located_selection_state_to_be:跟上面的方法做用同樣,只是上面的方法傳入定位到的element,而這個方法傳入locator
alert_is_present:判斷頁面上是否存在alert
"""

另外這裏使用了until()函數也可使用until_not()

  until_not(method, message='')

  調用該方法體提供的回調函數做爲一個參數,直到返回值爲False

  until(method, message='')

  調用該方法體提供的回調函數做爲一個參數,直到返回值爲True

3. 下拉框or彈框

一般狀況下,在網頁中會有一些下拉框進行選擇或者給你一個彈框告訴你須要進行確認,遇到這樣的狀況如何解決呢,宏哥在這裏就來簡單地說一說……‘’

3.1 代碼實現:

3.2 參考代碼:

# coding=utf-8🔥

# 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行

# 2.註釋:包括記錄建立時間,建立人,項目名稱。
'''
Created on 2019-12-09
@author: 北京-宏哥   QQ交流羣:705269076
Project: python+ selenium自動化測試練習篇8
'''

# 3.導入模塊

import time

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


driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
time.sleep(5)

# driver.find_element(By.ID, "kw").send_keys("selenium&python")
# driver.find_element(By.ID, "su").click()
# driver.find_element(By.XPATH, '/html/body/div[1]/div[5]/div[1]/div[2]/div[1]/div[2]/div[1]').click()
# driver.find_element(By.XPATH, '/html/body/div[1]/div[5]/div[1]/div[2]/div[1]/div[1]/span[2]').click()
# 折騰半天才發現定位出來的不是下拉框……
driver.find_element(By.LINK_TEXT, '設置').click()
driver.find_element(By.LINK_TEXT, '搜索設置').click()
time.sleep(2)

sel = driver.find_element(By.XPATH, '//*[@id="nr"]')  # 定位下拉框
Select(sel).select_by_value('50')  # 經過value的值進行選定條目
driver.find_element(By.CLASS_NAME, 'prefpanelgo').click()
time.sleep(2)
driver.switch_to.alert.accept()  # 此處贊成警告框提示內容
time.sleep(2)

driver.quit()

3.3 運行結果:

運行代碼後,控制檯打印以下圖的結果

3.4 瀏覽器

瀏覽器跳轉到設置頁面,會提示「已記錄下您的偏好」

在百度首頁想要進行設置每次搜索頁面顯示的數目,就會有一個下拉框進行選擇,這裏能夠導入Select這個模塊進行對下拉框進行選擇,一般下拉框的列表是包含一個值的,這樣就能夠經過value來選定,完成設置以後,固然是要保存設置啦,點擊保存發現,竟然有

一個彈框,這可如何是好,切換至alert以後接受吧……

經過在編輯器中的提示,咱們一樣能夠給彈框發送一個值,固然這裏設置中並無出現這類狀況。

此次對下拉框和彈框的處理過程當中,折騰了不短期,緣由就是元素等待的問題,下回要仔細研究下元素等待的問題了。

4. 自動化測試demo

使用selenium進行測試,固然是須要進行驗證的,此時結合python的斷言函數就變得很是有用了。測試中設定好預期,當實際狀況與預期有差異,給出錯誤信息,好像正是所但願的。

來一段簡單的代碼看下斷言的基本使用:

複製代碼
# coding:utf-8 import time from selenium import webdriver dr = webdriver.Chrome() dr.maximize_window() dr.get("https://www.baidu.com") print(dr.title) try: assert (dr.title == "百度,你就知道") except: print('標題錯誤,請查看錯誤信息') time.sleep(5) dr.quit()
複製代碼

獲取頁面的title是否符合咱們的預期,當打開的網頁title不是咱們想要的,不只從函數assert的提示信息看到緣由,也可輸出簡單的提示信息。

Web登陸測試是很常見的測試,手動測試你們再熟悉不過了,那如何進行自動化登陸測試呢!本文就基於python+selenium結合unittest單元測試框架來進行一次簡單但比較完整的cnblog自動化登陸測試,可提供點參考!下面就包括測試代碼和每種測試狀況的截圖。

 另外一種方式是結合python測試框架unittest進行驗證。如下的代碼只是爲了演示:

# coding=utf-8🔥

# 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行

# 2.註釋:包括記錄建立時間,建立人,項目名稱。
'''
Created on 2019-12-10
@author: 北京-宏哥   QQ交流羣:705269076
Project: python+ selenium自動化測試練習篇9
'''

# 3.導入模塊

import unittest
from selenium import webdriver
from time import sleep
'''
cnblog的登陸測試,分下面幾種狀況:
(1)用戶名、密碼正確
(2)用戶名正確、密碼不正確
(3)用戶名正確、密碼爲空
(4)用戶名錯誤、密碼正確
(5)用戶名爲空、密碼正確(還有用戶名和密碼均爲空時與此狀況是同樣的,這裏就不單獨測試了)
'''

class LoginCase(unittest.TestCase):

    def setUp(self):
        self.dr = webdriver.Chrome()
        self.dr.maximize_window()

    # 定義登陸方法
    def login(self, username, password):
        self.dr.get('https://passport.cnblogs.com/user/signin')  # cnblog登陸頁面
        self.dr.find_element_by_id('LoginName').send_keys(username)
        self.dr.find_element_by_id('Password').send_keys(password)
        self.dr.find_element_by_id('submitBtn').click()

    def test_login_success(self):
        '''用戶名、密碼正確'''
        self.login('北京-宏哥', '!qaz2wsx')  # 正確用戶名和密碼
        sleep(3)
        link = self.dr.find_element_by_id('lnk_current_user')
        self.assertTrue('北京-宏哥' in link.text)  # 用assertTrue(x)方法來斷言  bool(x) is True 登陸成功後用戶暱稱在lnk_current_user裏
        self.dr.get_screenshot_as_file("D:\\cnblogtest\\login_success.jpg")  # 截圖  可自定義截圖後的保存位置和圖片命名

    def test_login_pwd_error(self):
        '''用戶名正確、密碼不正確'''
        self.login('北京-宏哥', 'kemi')  # 正確用戶名,錯誤密碼
        sleep(2)
        error_message = self.dr.find_element_by_class_name('ajax-error-box').text
        self.assertIn('用戶名或密碼錯誤', error_message)  # 用assertIn(a,b)方法來斷言 a in b  '用戶名或密碼錯誤'在error_message裏
        self.dr.get_screenshot_as_file("D:\\cnblogtest\\login_pwd_error.jpg")

    def test_login_pwd_null(self):
        '''用戶名正確、密碼爲空'''
        self.login('北京-宏哥', '')  # 密碼爲空
        error_message = self.dr.find_element_by_id('Password-error').text
        self.assertEqual(error_message, '請輸入密碼')  # 用assertEqual(a,b)方法來斷言  a == b  請輸入密碼等於error_message
        self.dr.get_screenshot_as_file("D:\\cnblogtest\\login_pwd_null.jpg")

    def test_login_user_error(self):
        '''用戶名錯誤、密碼正確'''
        self.login('北京-宏哥1', '!qaz2wsx')  # 密碼正確,用戶名錯誤
        sleep(2)
        error_message = self.dr.find_element_by_id('ajax-error-box').text
        self.assertIn('用戶名或密碼錯誤', error_message)  # 用assertIn(a,b)方法來斷言 a in b
        self.dr.get_screenshot_as_file("D:\\cnblogtest\\login_user_error.jpg")

    def test_login_user_null(self):
        '''用戶名爲空、密碼正確'''
        self.login('', '!qaz2wsx')  # 用戶名爲空,密碼正確
        error_message = self.dr.find_element_by_id('LoginName-error').text
        self.assertEqual(error_message, '請輸入登陸用戶名')  # 用assertEqual(a,b)方法來斷言  a == b
        self.dr.get_screenshot_as_file("D:\\cnblogtest\\login_user_null.jpg")

    def tearDown(self):
        sleep(2)
        print('自動測試完畢!')
        self.dr.quit()


if __name__ == '__main__':
    unittest.main()

經過以上代碼,咱們能夠看到使用selenium和unittest框架結合,已經能夠對用戶登錄的模塊作一個簡單的自動化測試。

可是如今博客園的登錄機制的改變有可能部分用例不成功,可是你知道怎麼作就能夠了。

測試截圖以下:

 正確用戶名和密碼登陸成功!

 用戶名正確,密碼爲空

 用戶名爲空,密碼正確

5. 小結

 好了,今天的分享就到這裏吧!!!謝謝各位的耐心閱讀。

 

您的確定就是我進步的動力。若是你感受還不錯,就請鼓勵一下吧!記得點波 推薦 不要忘記哦!!!

 

相關文章
相關標籤/搜索