自动化测试入门从虫师的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、运行测试用例,生成如下的测试报告,但其实使用参数化的方法还是不够完美,执行用例的时间太长,之后再找找解决方案吧