一、discover方法
discover方法可以根據標准加載用例,並將結果返回給測試套件(suite),start_dir:待測試的目錄,pattern:測試用例文件名的匹配規。
如:
start_dir = './test_case'suites = unittest.defaultTestLoader.discover(start_dir ,pattern='test.*py')
當執行多個目錄的測試用例時,如何查找test_case下的其他目錄吃里的測試用例文件呢?就是在test_case下每個目錄里加__init__.py文件,這樣會把這個目錄當做標記成一個標准的Python模塊。
二、測試用例的執行順序是根據ASCLL碼的順序執行的。如:test_aaa.py優先於test_bbb.py。
三、裝飾器 。這些裝飾器不僅用在方法上,同樣適用於類。四#跳過測試和預期失敗
class MyTest(unittest.TestCase):
@unittest.skip('直接跳過測試')
def test_skip(self):
print('test aaa')
@unittest.skipIf(3>2,'條件為真時跳過裝飾的測試')
def test_skip_if(self):
print('test bbb')
@unittest.skipUnless(3>2,'條件為真時執行裝飾的測試')
def test_skip_unless(self):
print('test ccc')
@unittest.expectedFailure
def test_expected_failure(self):
self.assertEqual(3,3)
if __name__ == '__main__':
unittest.main()
四、Fixture 執行一個或者多個測試所需要的環境。如創建臨時或者代理 數據庫、目錄、或者啟動服務器進程。
import unittest
def setUpModule():
print('test module start >>>>>>>>>>>>>>>>')
def tearDownModule():
print('test module end >>>>>>>>>>>>>>>>>>')
class MyTest2(unittest.TestCase):
@classmethod
def setUpClass(cls):
print('test class start >>>>>>>>>>>>>>')
@classmethod
def tearDownClass(cls):
print('test class end >>>>>>>>>>>>>>>>')
def setUp(self):
print('test case start>>>>>>>>>>>>>>')
def tearDown(self):
print('test case end>>>>>>>>>>>>>>>')
def test_case1(self):
print('test case1')
def test_case2(self):
print("test case2")
if __name__ == '__main__':
unittest.main()
五、斷言方法。
class TestAssert(unittest.TestCase):
def test_equal(self):
self.assertEqual(2+2,4)
self.assertEqual('python','python')
self.assertNotEqual('python','pythno')
def test_in(self):
self.assertIn('hello','hello world')
self.assertNotIn('hi','hello')
def test_true(self):
self.assertTrue(1) # or Ture
self.assertFalse(0) # or False
六、數據驅動應用。
常用的csv讀取數據執行用例,會導致所有數據被當做一條用例來執行,只要有一條用例失敗,那么整個用例就執行失敗了。一種解決方法是將數據讀取到列表中,在用例中按照下標來調用。
但是這樣有兩個問題,一是每次都要讀取文件,耗費空間,二是數據在列表中,如果插入一條數據,或者刪除一條數據,那么用例在調用數據時就會非常容易出錯,不利於維護。
下面介紹2個模塊來解決數據驅動問題。
Parameterized是Python的一個庫。支持unittest、pytest、Nose框架。
import unittest
from time import sleep
from selenium import webdriver
from parameterized import parameterized
class TestBaidu(unittest.TestCase):
'''百度搜索測試'''
@classmethod
def setUpClass(cls):
cls.driver = webdriver.Chrome()
cls.base_url = 'https://www.baidu.com'
def baidu_search(self,search_key):
self.driver.get(self.base_url)
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'),
('case2', 'unittest'),
('case3', 'parameterized'),
])
def test_search(self,name,search_key):
''''''
self.baidu_search(search_key)
self.assertEqual(self.driver.title,search_key + '_百度搜索')
@classmethod
def tearDownClass(cls):
cls.driver.quit()
if __name__ == '__main__':
unittest.main()
在@parameterized.expand()中每個元組都是一條測試用例。name對應的是元組中第一列數據,search_key對應的是第二列數據。參數化會自動加上0,1,2來區分每條用例。元組中的數據作為用例名的后綴出現在測試報告中。
DDT是uittest的一個擴展庫。
測試類需要通過@ddt裝飾器進行裝飾。DDT提供不同形式的參數化,比如列表,元組,字典等。需要注意字典的KEY與測試方法的參數要保持一致。
DDT也支持數據文件(json)的參數化。
import unittest
from time import sleep
from selenium import webdriver
from ddt import ddt,data,file_data,unpack
@ddt
class TestBaidu(unittest.TestCase):
'''百度搜索測試'''
@classmethod
def setUpClass(cls):
cls.driver = webdriver.Chrome()
cls.base_url = 'https://www.baidu.com'
def baidu_search(self,search_key):
self.driver.get(self.base_url)
self.driver.find_element_by_id('kw').send_keys(search_key)
self.driver.find_element_by_id('su').click()
sleep(2)
@data(['case1','selenium'],['case2','unittest'],['case3', 'parameterized'])
@unpack
def test_search1(self,name,search_key):
print('第一組測試用例:', name)
self.baidu_search(search_key)
self.assertEqual(self.driver.title,search_key + '_百度搜索')
@data(('case1','selenium'),
('case2', 'unittest'),
('case3', 'parameterized'),)
@unpack
def test_search2(self, name, search_key):
print('第二組測試用例:',name)
self.baidu_search(search_key)
self.assertEqual(self.driver.title, search_key + '_百度搜索')
@data({"search_key":"python"},{"search_key":"ddt"},{"search_key":"Selenium"})
@unpack
def test_search2(self, search_key):
print('第三組測試用例:',search_key)
self.baidu_search(search_key)
self.assertEqual(self.driver.title, search_key + '_百度搜索')
# @file_data('ddt_data_file.json')
# def test_search4(self, search_key):
# print('第四組測試用例:',search_key)
# self.baidu_search(search_key)
# self.assertEqual(self.driver.title, search_key + '_百度搜索')
@classmethod
def tearDownClass(cls):
cls.driver.quit()
if __name__ == '__main__':
unittest.main()
ddt_data_file.json
{
"case1":{"search_key":"python"},
"case2":{"search_key":"ddt"},
"case3":{"search_key":"Selenium"}
}
七、HTML測試報告。HTMLTestRunner支持Python3的下載地址:https://github.com/defnngj/HTMLTestRunner
#獲取當前的時間
now_time = time.strftime('%Y-%m-%d %H_%M_%S')
HTML_report = './test_report/'+now_time+'result.html'
fp = open(HTML_report,'wb')
runner = HTMLTestRunner(stream=fp,title='Fixture', description='運行環境:Windows 10,Chrome瀏覽器')
runner.run(suites)
#關閉
fp.close()