python自動化過程中的數據驅動以及關鍵字驅動
我們公司最近一直在推自動化,意在提高測試效率,減少在回歸過程中的大量重復發工作量。UI自動化靠的是seleniumIDE的錄制配合導出的py文件結合unittest來做簡單的自動化。但是在實現中可能為遇到這樣一個問題,一個頁面存在大量表單填寫,或者同一個流程需要填寫不同的參數進行測試時,我們總不可能重新錄制一遍流程,或者在已經錄制好的腳本中一條數據一條數據的去改動,這個時候我們就需要結合數據驅動來優化我們的腳本。
數據驅動以及關鍵字驅動:
關鍵字驅動:比如在我們公司的推的UI自動化場景中,將錄制好的腳本封裝成函數,結合unittest調用,這樣的方式實現測試動作,就是關鍵字驅動。封裝好的函數就可看成是關鍵字。甚至可以這樣理解,函數式編程就是關鍵字驅動。在測試框架中最出名的關鍵字驅動框架應該RobotFramework框架,這款框架其實還挺不錯的,也是一定程度上降低了自動化的代碼能力的要求(測試腳本的組裝過程),但是關鍵字的封裝過程還是有些難度的。這框架跟我們國產的編程語言:易語言有些相像,有興趣的小伙伴可以自行了解一下。
數據驅動:還是這個場景,我們將封裝好的函數,每次調用只能滿足一個特定的測試場景,而且維護起來很麻煩,就算將函數中需要輸入的值參數化,放在其他地方(比如csv文件,列表,元祖...)這也只是減少了維護的成本,優化了代碼。要是進一步的通過提前准備好的數據,讓腳本根據准備好的數據來進行不同場景的業務覆蓋,那么我們就實現了最簡單數據驅動測試...
數據驅動測試實現:
舉兩個個小例子讓大家了解什么是數據驅動,以及如何實現。
1、簡單的數據驅動測試:
業務場景:周報考勤系統的登錄(登錄操作的測試:1、正確用戶名密碼; 2、正確用戶名,錯誤密碼;3、錯誤的用戶名,密碼)
實現:需要用到python中的ddt庫,為了創建數據驅動測試,我們需要在測試類上使用@ddt裝飾符,在測試方法上使用@data裝飾符。@data裝飾符把參數當作測試數據,參數可以是單個值、列表、元組、字典。對於列表,需要用@unpack裝飾符把元組和列表解析成多個參數。
#python的單元測試框架 import unittest #python用來實現數據驅動的庫ddt(pip install ddt 即可安裝下載) from ddt import ddt, data, unpack #selenium 實現UI自動化 from selenium import webdriver import time @ddt #@ddt裝飾符,在測試方法上使用@data裝飾符 class LearnDDT(unittest.TestCase): #測試用例的前置動作 def setUp(self) -> None: #實例化一個瀏覽器驅動 self.driver = webdriver.Chrome() self.driver.implicitly_wait(30) #隱式等待時間 self.driver.maximize_window() #窗口最大化 self.driver.get('http://kq.thunisoft.com:8080/kqgl/logout') #打開登錄地址 #@data裝飾符把參數當作測試數據,參數可以是單個值、列表、元組、字典 @data(('right_name', 'right_passwdl'), ('right_name', 'wrong_passwd'), ('wrong_name', 'right_passwd')) #提前准備好的測試數據 # @unpack裝飾符把元組和列表解析成多個參數 @unpack def test_login(self, name, passwd): ''' 把下面的三步操作封裝成函數,再在case中調用該函數,就可以理解為關鍵字驅動,調用的函數名就是關鍵字。 def login(name, passwd) self.driver.find_element_by_name('j_username').send_keys(name) self.driver.find_element_by_name('j_password').send_keys(passwd) self.driver.find_element_by_id('submit_button').click() ''' self.driver.find_element_by_name('j_username').send_keys(name) #輸入用戶名 self.driver.find_element_by_name('j_password').send_keys(passwd) #輸入密碼 self.driver.find_element_by_id('submit_button').click() #點擊登錄 time.sleep(5) #測試用例的后置動作 def tearDown(self) -> None: self.driver.quit() #退出瀏覽器操作 if __name__ == '__main__': main = unittest.main(verbosity=2)
運行該測試腳本,則會使用列表中三組數據,分別覆蓋業務場景。用一套代碼,覆蓋到了不同的業務場景。
2、還是簡單的數據驅動測試(將數據存在csv文件中):
業務場景:還是周報考勤系統的登錄(登錄操作的測試:1、正確用戶名密碼; 2、正確用戶名,錯誤密碼;3、錯誤的用戶名,密碼)
實現:還是用到了ddt庫,但是這次將數據存在csv文件中,就像這樣:

封裝從一個函數:專門中csv文件中獲取數據(這里不限於csv文件,可以是excel,txt等等文件)
import csv #引入操作csv文件的庫
def get_data(filename):
datas = [] #創建一個空列表接收數據
with open(filename, 'r') as f: #讀取csv文件
reader = csv.reader(f) #創建csv實例化對象
next(reader) #去除頭部信息
for row in reader:
datas.append(row)
return datas
測試場景覆蓋:(代碼和上面的那段幾乎沒有變動,唯一變得是@data裝飾符后面跟的參數)
from ddt import ddt, data, unpack
import time
from selenium import webdriver
import unittest
@ddt
class LearnDDT2(unittest.TestCase):
def setUp(self) -> None:
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(30)
self.driver.maximize_window()
self.driver.get('http://kq.thunisoft.com:8080/kqgl/logout')
@data(*get_data("login.csv")) #調用獲取測試數據的函數,由於傳入的是個列表,所以前面需要加上“ * ”。
@unpack
def test_login2(self, name, passwd):
self.driver.find_element_by_name('j_username').send_keys(name)
self.driver.find_element_by_name('j_password').send_keys(passwd)
self.driver.find_element_by_id('submit_button').click()
self.assertEqual()
time.sleep(5)
def tearDown(self) -> None:
self.driver.quit()
if __name__ == '__main__':
main = unittest.main(verbosity=2)
有興趣的小伙伴,可以自己實驗一下,讓后運行腳本,看看到底是怎樣的一個效果。這樣會幫你更加了解什么是數據驅動測試。當然這只是最簡單的數據驅動測試。僅單單從測試數據入手,其實還可以實現更復雜的業務場景,再結合PO設計模式就可以將測試腳本調到最優...
