自動化測試入門從蟲師的selenium教程開始,感謝蟲師大大。進入蟲師的博客
最近在項目中開始使用Python+selenium進行自動化測試,由於大部分功能點需要使用多個場景才能覆蓋,這樣通常需要對測試的功能寫多個方法,我覺得比較麻煩,不符合Python代碼的簡潔化;所以在網上百度了下,可以使用paramunittest實現參數化,廢話不多說,直接上代碼
我使用的是Python3+unittest+selenium+ParamUnittest,HTMLTestReportCN用於生成測試報告。
** 貼上ParamUnittest的下載路徑:點此獲取
也可以使用pip進行安裝:pip install ParamUnittest
** 貼上HTMLTestReportCN的下載路徑:點此獲取
HTMLTestReportCN是從HTMLTestRunner改寫的,增加了一些樣式美化,其中jquery和bootstrap使用的是百度,需要在外網下才能使用
ParamUnittest可以從數組中獲取用例,我的方法是先將用例寫到excel中,再讀取excel獲取用例組
1、創建getDir.py用於獲取文件路徑
1 # !/usr/bin/python3 2 3 """ 4 FileName : getDir.py 5 Author : ken 6 Date : 2018-04-21 7 Describe : get path 8 """ 9 import os 10 11 currentDir = os.path.abspath(os.path.dirname(__file__)) 12 proDir = os.path.split(currentDir)[0]
2、貼上讀寫excel的代碼:
1)如下代碼中,類PyExcel使用xlwt寫數據到Excel中,xlrd從Excel中讀取數據
2)方法get_excel_value,從Excel中讀取用例組
1 # !/usr/bin/python3 2 3 """ 4 FileName : common.py 5 Author : ken 6 Date : 2018-04-21 7 Describe : common method for test 8 """ 9 10 import os 11 12 import xlrd 13 import xlwt 14 15 from commonFile import getDir 16 from commonFile.Log import MyLog 17 18 proDir = getDir.proDir 19 20 21 class PyExcel: 22 """Use the given excel_name and sheet_name, sheet_value, write excel and read excel. 23 1. write_excel 24 2. read_excel 25 """ 26 TestFile = os.path.join(proDir, "testFile") 27 suffix = ".xls" 28 29 def __init__(self, excel_name, sheet_name=None, sheet_value=None): 30 """ 31 initialization parameter 32 :param excel_name: The file suffix must be "xls" 33 :param sheet_name: set the workbook's sheetName 34 :param sheet_value: The type of object must be "list" or "tuple" 35 """ 36 self.excel_name = excel_name 37 self.sheet_name = sheet_name 38 self.sheet_value = sheet_value 39 40 self.logger = MyLog.get_log().get_logger() 41 42 if not str(self.excel_name).endswith(self.suffix): 43 raise Exception('%s suffix is not "%s"' % 44 (self.excel_name, self.suffix)) 45 self.EXCEL_PATH = os.path.join(self.TestFile, self.excel_name) 46 47 if self.sheet_value is not None: 48 try: 49 if isinstance(self.sheet_value, list) or isinstance(self.sheet_value, tuple): 50 for i in range(len(self.sheet_value)): 51 assert isinstance(self.sheet_value[i], list) 52 except TypeError as e: 53 self.logger.error(e, exc_info=True) 54 print(e) 55 56 def write_excel(self): 57 if self.sheet_name is not None: 58 wb = xlwt.Workbook() 59 sheet = wb.add_sheet(self.sheet_name) 60 61 for i in range(len(self.sheet_value)): 62 for j in range(len(self.sheet_value[i])): 63 sheet.write(i, j, self.sheet_value[i][j]) 64 65 wb.save(self.EXCEL_PATH) 66 print("write date success!") 67 else: 68 return False 69 70 def read_excel(self): 71 workbook = xlrd.open_workbook(self.EXCEL_PATH) 72 if self.sheet_name: 73 work_sheet = workbook.sheet_by_name(self.sheet_name) 74 else: 75 work_sheet = workbook.sheet_by_index(0) 76 77 for i in range(work_sheet.nrows): 78 for j in range(work_sheet.ncols): 79 print(work_sheet.cell_value(i, j), "\t", end="") 80 print() 81 82 83 def get_excel_value(excel_name, sheet_name): 84 """ 85 get excel value by given excel_name and sheet_name 86 :param excel_name: 87 :param sheet_name: 88 :return: cls 89 """ 90 cls = [] 91 excel_path = os.path.join(proDir, "testFile", excel_name) 92 workbook = xlrd.open_workbook(excel_path) 93 sheet = workbook.sheet_by_name(sheet_name) 94 nrows = sheet.nrows 95 96 for i in range(nrows): 97 if sheet.row_values(i)[0] != "case_name": 98 cls.append(sheet.row_values(i)) 99 return cls 100 101 102 if __name__ == "__main__": 103 value = ( 104 ["case_name", "username", "password", "excepted"], 105 ["用戶名正確,密碼錯誤", "qiutiandeyanjin@163.com", "efg", "用戶名或密碼不正確"], 106 ["有用戶名沒有密碼", "qiutiandeyanjin@163.com", "", "請輸入密碼"], 107 ["沒有用戶名有密碼", "", "efg", "請輸入帳號"] 108 ) 109 excel = PyExcel(excel_name="loginCase.xls", sheet_name="login_test", sheet_value=value) 110 excel.write_excel() 111 excel.read_excel() 112 # test = get_excel_value(excel_name="loginCase.xls", sheet_name="login_test") 113 # print(test)
** 附上寫入成功的Excel截圖
3、如下為登錄小米網站的測試用例
1)如下47行代碼這樣寫是為了能將用例名稱寫入到測試報告(不是很清楚這樣寫對不對,但是還是搞定了,😄),嘗試了多次才搞定這個小功能,所以遇到問題無法解決時,是可以從源碼開始找解決方案的,雖然也有可能解決不了,但是也會讓你離問題的原因越來越近
1 # !/usr/bin/python3 2 3 """ 4 FileName : test_login.py 5 Author : ken 6 Date : 2018-04-21 7 Describe : user the paramUnittest, test login 8 """ 9 import os 10 import time 11 import unittest 12 from time import sleep 13 14 import paramunittest 15 from selenium import webdriver 16 17 from commonFile import getDir 18 from commonFile.common import get_excel_value 19 20 proDir = getDir.proDir 21 now = time.strftime("%Y_%m_%d %H:%M:%S") 22 loginCase = get_excel_value("loginCase.xls", "login_test") 23 24 25 @paramunittest.parametrized(*loginCase) 26 class LoginTest(unittest.TestCase): 27 def setParameters(self, case_name, username, password, excepted): 28 """ 29 從 excel 中獲取用例 30 :param case_name: 用例名稱 31 :param username: 用戶名 32 :param password: 密碼 33 :param excepted: 期望值 34 :return: 35 """ 36 self.case_name = case_name 37 self.username = username 38 self.password = password 39 self.excepted = excepted 40 41 def setUp(self): 42 self.baseUrl = "http://www.mi.com" 43 self.driver = webdriver.Chrome() 44 self.driver.implicitly_wait(10) # 靜默等待10s 45 46 def test_login(self): 47 self._testMethodDoc = self.case_name # 設置用例名稱 48 driver = self.driver 49 driver.get(self.baseUrl) 50 driver.find_element_by_xpath("//div[@class='topbar-info']/a[1]").click() 51 sleep(2) 52 driver.find_element_by_css_selector("[id='username']").clear() 53 driver.find_element_by_css_selector("[id='username']").send_keys(self.username) 54 driver.find_element_by_css_selector("[id='pwd']").clear() 55 driver.find_element_by_css_selector("[id='pwd']").send_keys(self.password) 56 driver.find_element_by_css_selector("[class='btns_bg']>input").click() 57 sleep(1) 58 # 獲取登錄錯誤信息 59 error_msg = driver.find_element_by_css_selector("#login-main-form > div > " 60 "div.err_tip > div > span").text 61 self.assertEqual(error_msg, self.excepted) 62 63 def get_screenshot(self): 64 file_path = os.path.join(proDir, "testFile", "shots") 65 if not os.path.exists(file_path): 66 os.mkdir(file_path) 67 shot_name = "screenshot_%s.png" % now 68 shot_path = os.path.join(proDir, file_path, shot_name) 69 self.driver.get_screenshot_as_file(shot_path) 70 71 def tearDown(self): 72 self.get_screenshot() 73 self.driver.quit() 74 75 76 if __name__ == "__main__": 77 unittest.main(verbosity=2)
4、使用unittest.defaultTestLoader.discover獲取用例,再使用HTMLTestReportCN生成測試報告
1 # !/usr/bin/python3 2 3 """ 4 FileName : run_test.py 5 Author : ken 6 Date : 2018-04-22 7 Describe : use the unittest and HTMLTestRunner, run all test case 8 """ 9 import os 10 import time 11 import unittest 12 13 from commonFile import getDir 14 from commonFile.HTMLTestReportCN import HTMLTestRunner 15 16 proDir = getDir.proDir 17 now = time.strftime("%Y_%m_%d") 18 19 if __name__ == "__main__": 20 # setting report dir 21 ReportDir = os.path.join(proDir, "testReport") 22 23 # setting case dir 24 CaseDir = os.path.join(proDir, "testCase") 25 26 # search test case 27 discover = unittest.defaultTestLoader.discover(start_dir=CaseDir, pattern="test_*.py") 28 29 # setting report fileName 30 fileName = "parameterTest_%s.html" % now 31 fp = open(os.path.join(ReportDir, fileName), 'wb') 32 33 runner = HTMLTestRunner(stream=fp, 34 title="ParameterTest", 35 description="use case execution: ", 36 tester="ken", 37 verbosity=2) 38 39 runner.run(discover)
5、運行測試用例,生成如下的測試報告,但其實使用參數化的方法還是不夠完美,執行用例的時間太長,之后再找找解決方案吧