一、自動化測試模型
1.線性測試
錄制或編寫對應應用程序操作步驟產生,每個線性腳本相互獨立,相互之間不依賴,不調用彼此,即單純地模擬用戶完整操作場景。不易維護。
2.模塊化與類庫
將重復的操作單獨封裝成公共模塊。在測試用例執行過程中,當需要用到模塊封裝時對其進行調用,如此一來便最大限度的消除了重復,從而提高測試用例的可維護性。
3.數據驅動測試
定義:數據的改變驅動自動化測試的執行,最終引起測試結果的改變。簡單理解就是把數據驅動所需要的測試數據參數化,可以用多種方式來存儲和管理這些參數化的數據(txt,html,csv,xml,json)
4.關鍵字驅動測試
又被稱為【表驅動測試】或【基於動作字測試】。這類框架會把自動化操作封裝為“關鍵字”,避免測試人員直接接觸代碼,多以“填表格”的形式降低腳本的編寫難度。
Robot Framework是主流的關鍵字驅動測試框架之一,通過它自帶的Robot Framework RIDE編寫。
二、模塊化與參數化
1.簡單的一個文件線性測試
一般需要配合使用,即在創建函數或類方法時為它們設置入參,使其可以根據不同的參數執行相應的操作,下面以一個簡單的126郵箱登錄為例:
1 from selenium import webdriver 2 from time import sleep 3 4 driver = webdriver.Chrome() 5 driver.maximize_window() 6 driver.get("http://www.126.com") 7 # 登錄 8 sleep(5) 9 10 login = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div/div[3]/div[3]/div[4]/a[1]") 11 login.click() 12 driver.switch_to.frame(0) 13 """ 14 (driver.find_element_by_xpath("/html/body/div[2]/div[3]/div/div[3]/div[4]/div[1]/div/iframe")) 15 """ 16 sleep(3) 17 user = driver.find_element_by_name("email") 18 user.clear() 19 user.send_keys("zudangli") 20 driver.find_element_by_name("password").clear() 21 driver.find_element_by_name("password").send_keys("19820818kai") 22 driver.find_element_by_id("dologin").click() 23 # 登錄之后的動作 24 sleep(3) 25 # 退出 26 driver.find_element_by_link_text("退出").click() 27 driver.quit()
<這里涉及到一個表單切換的問題,因為打開這個郵箱的網址后主頁面顯示的是掃碼登錄,要切換到賬戶密碼登錄的表單下,但是在嘗試了多種定位iframe的方式之后(name、css_selector、xpath),切換是切換成功無疑了,因為可以找到該iframe下的元素,但就是不能執行操作,報錯:(selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable),也搜了很多辦法,最終也無疾而終,最后只能在切換表單之前手動切換到賬號登錄的iframe下,暫時先這樣解決吧,隨着后面進一步的學習再回來看看是怎么費事!!!>
2.將重復的動作模塊化
好了,言歸正傳,繼續來康康如何一步步模塊化……要實現郵箱的自動化登錄測試項目,那每條測試用例都需要有登錄動作和退出動作,此時,需要創建一個新的module.py文件存放登錄和退出動作。
1 from time import sleep 2 3 4 class Mail: 5 6 def __init__(self, driver): 7 self.driver = driver 8 9 def login(self): 10 login = self.driver.find_element_by_xpath("/html/body/div[2]/div[3]/div/div[3]/div[3]/div[4]/a[1]") 11 login.click() 12 self.driver.switch_to.frame(0) 13 14 sleep(3) 15 user = self.driver.find_element_by_name("email") 16 user.clear() 17 user.send_keys("zudangli") 18 self.driver.find_element_by_name("password").clear() 19 self.driver.find_element_by_name("password").send_keys("19820818kai") 20 self.driver.find_element_by_id("dologin").click() 21 22 def logout(self): 23 self.driver.find_element_by_link_text("退出").click()
首先創建一個Mail類,在__init__()初始化方法中接收driver驅動並賦值給self.driver,在login()和logout()方法中分別使用self.driver實現郵箱的登錄和退出動作,接下來修改test_mail.py測試調用Mail類中的這兩個方法:
1 from selenium import webdriver 2 from time import sleep 3 4 from files.module import Mail 5 6 driver = webdriver.Chrome() 7 driver.maximize_window() 8 driver.get("http://www.126.com") 9 sleep(5) 10 # 調用Mail類並接受driver驅動 11 mail = Mail(driver) 12 # 登錄 13 mail.login() 14 sleep(5) 15 # 退出 16 mail.logout() 17 driver.quit()
3.將模塊中的方法參數化
接着再進一步,如果需求是測試登錄功能,雖然測試步驟是固定的,但是測試數據(賬號)不同,這時就需要把login()方法參數化。修改的module.py文件代碼如下:
1 from time import sleep 2 3 4 class Mail: 5 6 def __init__(self, driver): 7 self.driver = driver 8 login = self.driver.find_element_by_xpath("/html/body/div[2]/div[3]/div/div[3]/div[3]/div[4]/a[1]") 9 login.click() 10 self.driver.switch_to.frame(0) 11 sleep(3) 12 13 def login(self, username, password): 14 sleep(2) 15 self.driver.find_element_by_name("email").clear() 16 self.driver.find_element_by_name("email").send_keys(username) 17 self.driver.find_element_by_name("password").clear() 18 self.driver.find_element_by_name("password").send_keys(password) 19 self.driver.find_element_by_id("dologin").click() 20 sleep(3) 21 22 def logout(self): 23 self.driver.find_element_by_link_text("退出").click()
(這里對Mail類中的初始化方法做了微調,由於考慮到各種測試案例下,只需要一次定位到iframe就將iframe的定位操作放到了初始化方法中)
這樣就進一步提高了login()方法的可復用性,不再使用一個固定的賬號登錄,而是根據被調用者傳來的用戶名和密碼執行登錄操作,相應的修改測試用例test_mail.py文件:
1 driver = webdriver.Chrome() 2 driver.maximize_window() 3 driver.get("http://www.126.com") 4 sleep(5) 5 # 調用Mail類並接受driver驅動 6 mail = Mail(driver) 7 # 登錄賬號為空 8 mail.login("", "") 9 10 # 用戶名為空 11 mail.login("", "19820818kai") 12 13 # 密碼為空 14 mail.login("zudangli", "") 15 16 # 用戶名密碼錯誤 17 mail.login("error", "error") 18 19 # 正確的賬號登錄 20 mail.login("zudangli", "19820818kai") 21 mail.login("pegawayatstudying", "19970507zudangli") 22 # ……
4.讀取數據文件
- txt文件
Python提供了一下幾種讀取txt問價的方法:
- read():讀取整個文件
- readline():讀取一行數據
- readlines():讀取所有行的數據
test.txt文件如下:
:19820818kai
zudangli:
error:error
zudangli:19820818kai
pegawayatstudying:19970507zudangli
創建read_txt.py文件,用於讀取txt文件
1 # 讀取文件 2 with(open("./test.txt", "r")) as user_file: 3 data = user_file.readlines() 4 5 # 格式化處理 6 users = [] 7 for line in data: 8 user = line[:-1].split(":") 9 users.append(user) 10 11 # 打印users二維數組 12 print(users)
首先通過open()以讀(“r”)的方式打開test.txt文件,readlines()可讀取文件中的所有行並賦值給變量data。接下來循環data中的每一行數據,[:-1]可對字符串進行切片,以省略最后一個字符,因為讀取的每一行數據結尾都有一個換行符“\n”。spilt()通過冒號(:)對每行數據進行拆分,會得到數組['','19820818kai'],最后使用append()把每一組用戶名和密碼追加到users數組中。取users數組中的數據,得到的數組用不同的用戶名/密碼進行登錄,代碼如下:
1 from selenium import webdriver 2 from time import sleep 3 from files.module import Mail 4 from files.read_txt import users 5 6 driver = webdriver.Chrome() 7 driver.maximize_window() 8 driver.get("http://www.126.com") 9 sleep(5) 10 # 調用Mail類並接受driver驅動 11 mail = Mail(driver) 12 # 登錄賬號為空 13 mail.login(users[0][0], users[0][1]) 14 15 # 用戶名為空 16 mail.login(users[1][0], users[1][1]) 17 18 # 密碼為空 19 mail.login(users[2][0], users[2][1]) 20 21 # 用戶名密碼錯誤 22 mail.login(users[3][0], users[3][1]) 23 24 # 正確的賬號登錄 25 mail.login(users[4][0], users[4][1]) 26 mail.login(users[5][0], users[5][1]) 27 # ……
- CSV文件
注:可以把WPS表格或Excel表格通過文件另存為CSV類型的文件,但不要直接修改文件的后綴名來創建CSV文件,因為這樣的文件並非真正的CSV文件。這里遇到一個問題:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd3 in position 0: invalid continuation byte。解決辦法:https://blog.csdn.net/moledyzhang/article/details/78978312簡單來說就是用記事本打開該文件,另存為時編碼格式選擇UTF-8即可
1 import codecs 2 import csv 3 from itertools import islice 4 5 # 讀取本地CSV文件 6 data = csv.reader(codecs.open('./csv.csv', 'r', 'utf_8_sig')) 7 # 存放用戶數據 8 users = [] 9 # 循環輸出每行信息 10 for line in islice(data, 1, None): 11 users.append(line) 12 # 打印 13 print(users)
通過Python讀取CSV文件比較簡單,但會遇到兩個問題:
1.中文亂碼問題。codecs是Python標准的模塊編碼和解碼器。首先通過codecs提供的open()方法,在打開文件時可以指定編碼類型,如utf_8_sig,然后導入CSV模塊,通過reader()方法讀取文件,即可避免中文亂碼問題。
2.跳過CSV文件的首行。因為一般會在第一行定義測試字段的名字,所以在讀取數據時要跳過。Python的內建模塊itertools提供了用於操作迭代對象的函數,即islice()函數,可以返回一個迭代器第一個參數指定迭代對象,第二個參數指定開始迭代的位置,第三個參數表示結束位。
- XML文件
當需要讀取的數據是不規則時,可以用XML文件。比如需要用一個配置文件來配置當前自動化測試平台、瀏覽器、URL、登錄的用戶名和密碼等,這時就需要使用XML文件存放這些數據。其特點是數據保存在標簽對之間,或者是作為標簽的屬性存放。
1 <?xml version="1.0" encoding="utf-8" ?> 2 <info> 3 <platforms> 4 <platform>Windows</platform> 5 <platform>Linux</platform> 6 <platform>macOS</platform> 7 </platforms> 8 <browsers> 9 <browser>Firefox</browser> 10 <browser>Chrome</browser> 11 <browser>Edge</browser> 12 </browsers> 13 <url>http:www.xxxx.com</url> 14 <login username="admin" password="123456"/> 15 <login username="guest" password="654321"/> 16 </info>
1 from xml.dom.minidom import parse 2 # 打開XML文件 3 dom = parse('./config.xml') 4 # 得到文檔元素對象 5 root = dom.documentElement 6 # 獲取一組標簽 7 tag_name = root.getElementsByTagName('platform') 8 9 print(tag_name[0].firstChild.data) 10 print(tag_name[1].firstChild.data) 11 print(tag_name[2].firstChild.data)
Python自帶讀取XML文件的模塊,通過parse()方法可讀取XML文件。documentElement()方法用於獲取文檔元素對象,getElementsByTagName()方法用於獲取文件中的標簽。這里不需要指定標簽的層級關系,即獲取的標簽可以是任意層級的。接下來,獲取標簽數組中的某個元素。firstChild屬性可返回被選節點的第一個子節點,data表示獲取該節點的數據,它和WebDriver中的text語句作用相似。上面的代碼是來獲取標簽對之間的數據,下面來看看如何獲取標簽的屬性值:
1 from xml.dom.minidom import parse 2 dom = parse('./config.xml') 3 root = dom.documentElement 4 login_info = root.getElementsByTagName('login') 5 # 獲得login標簽的username屬性值 6 username = login_info[0].getAttribute("username") 7 print(username) 8 # 獲得login標簽的password屬性值 9 password = login_info[0].getAttribute("password") 10 print(password) 11 12 # 獲得第二個login標簽的username屬性值 13 username = login_info[1].getAttribute("username") 14 print(username) 15 # 獲得第二個login標簽的password屬性值 16 password = login_info[1].getAttribute("password") 17 print(password)
這里主要使用getAttribute()方法獲取元素的屬性值,它和WebDriver中的get_attribute()方法作用相似
- JSON文件
JSON是一種輕量級的數據交換格式,層次結構清晰,創建user_info.json文件:
1 [ 2 {"username": "", "password": ""}, 3 {"username": "", "password": "123"}, 4 {"username": "user", "password": ""}, 5 {"username": "error", "password": "error"}, 6 {"username": "admin", "password": "admin123"} 7 ]
創建read_json.py文件:
1 import json 2 3 with open("./user_info.json", "r") as f: 4 data = f.read() 5 6 user_list = json.loads(data) 7 print(user_list)
通過open()方法可讀取user_info.json文件。因為測試數據本身是以列表和字典格式存放的,所以讀取整個文件內容后,通過JSON提供的表將str類型轉換為list類型即可。