自動化測試模型(數據參數化方法)以及簡單的文件讀取方式


一、自動化測試模型

  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問價的方法:

  1. read():讀取整個文件
  2. readline():讀取一行數據
  3. 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類型即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM