數據驅動應用
數據驅動應用是自動化測試里的一個重要功能,雖然不使用單元測試框架也一樣可以寫測試代碼和使用數據文件,但這意味着放棄了單元測試框架
提供給我們的所有功能,如 測試用例斷言、 靈活的運行機制、 結果統計和測試報告等。 這些都要去自己去實現。顯然非常麻煩。 所以拋開測試框架
談數據驅動是沒有意義的。
下面我們來討論一下數據驅動的使用, 以及 unittest 關於參數化的庫
數據驅動:
由於大多數文章和資料都把 “讀取數據文件” 看做數據驅動的標志,所以我們來討論一下這個問題。 我們創建一個 baidu_data.csv
文件作為數據驅動。數據如下:
name search_key
case1 selenium
case2 python
case3 unittest
case4 pytest
接下來創建 test_baidu_data.py ,內容如下
《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《
import csv import codecs import unittest from time import sleep from itertools import islice from selenium import webdriver from os.path import dirname, abspath class TestBaidu(unittest.TestCase): @classmethod def setUpClass(cls): cls.driver = webdriver.Firefox() cls.baseUrl = "http://www.baidu.com" @classmethod def tearDownClass(cls): cls.driver.quit() def baidu_search(self, search_key): self.driver.get(self.baseUrl) self.driver.find_element_by_id("kw").send_keys(search_key) self.driver.find_element_by_id("su").click() sleep(2) def test_search(self): baseDir = dirname(dirname(abspath(__file__))) dataFileDir = baseDir + '/datafile' dataFilePath = dataFileDir + "/datafile.csv" print(dataFilePath) with codecs.open(dataFilePath, 'r', 'utf_8_sig') as f: data = csv.reader(f) for line in islice(data, 1, None): search_key = line[1] self.baidu_search(search_key) if __name__ == '__main__': unittest.main()
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
---------------------運行結果----------------------------------------------
D:\gupan\myObject\my_object/datafile/datafile.csv
.
----------------------------------------------------------------------
Ran 1 test in 18.463s
OK
***Repl Closed***
----------------------------------------------------------------------------
這樣做似乎沒什么問題,但是所有數據被當做一條測試用例執行了。 而 unittest 是以 “test” 開頭的測試方法作為一個用例,而這里有四條數據。
而且,這4條數據,如果有一條執行失敗,那么整個測試用例就失敗。 所以這樣划分並不合理,應該每一條數據一個測試用例。
思考一個問題: 在 UI 自動化測試中,站在用戶的角度去考慮,用戶在什么場景下會使用大量數據呢? 其實, 輸入大量數據的功能很少,如果整個
系統需要用戶輸入大量數據,那么可能用戶體驗會很不好! 大多數時候,系統只是允許輸入用戶名, 密碼 和個人信息,或關鍵字等。
Parameterized 是 Python 的一個參數化庫,同時支持, unittest、 None 和 Pytest 單元測試框架。
pip install parameterized
《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《
import csv import codecs import unittest from time import sleep from itertools import islice from selenium import webdriver from os.path import dirname, abspath from parameterized import parameterized class TestBaidu(unittest.TestCase): @classmethod def setUpClass(cls): cls.driver = webdriver.Firefox() cls.baseUrl = "http://www.baidu.com" @classmethod def tearDownClass(cls): cls.driver.quit() def baidu_search(self, search_key): self.driver.get(self.baseUrl) self.driver.find_element_by_id("kw").send_keys(search_key) self.driver.find_element_by_id("su").click() sleep(2) @parameterized.expand([ ("case1", "selenium"), ("case1", "python"), ("case1", "unittest"), ("case1", "pytest"), ]) def test_search(self, name, search_key): self.baidu_search(search_key) self.assertEqual(self.driver.title, search_key + "_百度搜索") if __name__ == '__main__': unittest.main(verbosity=2)
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
-------------------------運行結果---------------------------------------------
test_search_0_case1 (__main__.TestBaidu) ... ok
test_search_1_case1 (__main__.TestBaidu) ... ok
test_search_2_case1 (__main__.TestBaidu) ... ok
test_search_3_case1 (__main__.TestBaidu) ... ok
----------------------------------------------------------------------
Ran 4 tests in 19.188s
OK
***Repl Closed***
----------------------------------------------------------------------------
在 @paramiterized.expand() 中, 每個元組都被認為是一條測試用例。 元組中的數據為該條測試用例變化的值。在測試用例
中,通過參數來取每個元組中的數據。
參數化會自動多個加上 '0', '1', '2', '3' 來區分每條用例, 在元組中定義的 'case1', 'case2', 'case3', 'case4'
也會作為每條測試用例名稱的后綴出現,
注意:test_search() 方法實際上 只用了一個參數: search_key