搭建关键字驱动自动化测试框架,阿里P8大牛从零开始教软件测试开源框架

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新软件测试全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注软件测试)
img

正文

  1. 2 import win32con
  2. 3
  3. 4 class KeyBoardKeys(object):
  4. 5 '''
  5. 6 模拟键盘
  6. 7 '''
  7. 8 # 键盘编码
  8. 9 vk_code ={
  9. 10 'enter':0x0D,
  10. 11 'tab' : 0x09,
  11. 12 'ctrl':0x11,
  12. 13 'v':0x56
  13. 14 }
  14. 15 @staticmethod
  15. 16 def keyDown(keyName):
  16. 17 '''
  17. 18 模拟按下键
  18. 19 :param keyName:
  19. 20 :return:
  20. 21 '''
  21. 22 try:
  22. 23 win32api.keybd_event(KeyBoardKeys.vk_code[keyName],0,0,0)
  23. 24 except Exception as e:
  24. 25 raise e
  25. 26 @staticmethod
  26. 27 def keyUp(keyName):
  27. 28 '''
  28. 29 释放键
  29. 30 :param keyName:
  30. 31 :return:
  31. 32 '''
  32. 33 try:
  33. 34 win32api.keybd_event(KeyBoardKeys.vk_code[keyName],0,win32con.KEYEVENTF_KEYUP,0)
  34. 35 except Exception as e:
  35. 36 raise e
  36. 37 @staticmethod
  37. 38 def oneKey(key):
  38. 39 '''
  39. 40 模拟当个按键
  40. 41 :param key:
  41. 42 :return:
  42. 43 '''
  43. 44 try:
  44. 45 KeyBoardKeys.keyDown(key)
  45. 46 KeyBoardKeys.keyUp(key)
  46. 47 except Exception as e:
  47. 48 raise e
  48. 49
  49. 50 @staticmethod
  50. 51 def twoKeys(key1, key2):
  51. 52 '''
  52. 53 模拟组合按键
  53. 54 :param key1:
  54. 55 :param key2:
  55. 56 :return:
  56. 57 '''
  57. 58 try:
  58. 59 KeyBoardKeys.keyDown(key1)
  59. 60 KeyBoardKeys.keyDown(key2)
  60. 61 KeyBoardKeys.keyUp(key1)
  61. 62 KeyBoardKeys.keyUp(key2)
  62. 63 except Exception as e:
  63. 64 raise e
  64. 65
  65. 66 if __name__=='__main__':
  66. 67 from selenium import webdriver
  67. 68
  68. 69 driver = webdriver.Firefox()
  69. 70 driver.get('http://www.baidu.com')
  70. 71 driver.find_element_by_id('kw').send_keys('python')
  71. 72 KeyBoardKeys.oneKey('enter')

5.新建DirAndTime.py文件,主要实现获取当前时间,生成特殊路径,这里主要用来生成屏幕截图保存的路径及图片名称

    • 1 from datetime import datetime, date
  • 2 from config.VarConfig import *
  • 3
  • 4 class DirAndTime(object):
  • 5 @staticmethod
  • 6 def getCurrentDate():
  • 7 '''
  • 8 获取当前日期
  • 9 :return:
  • 10 '''
  • 11 try:
  • 12 currentDate = date.today()
  • 13 except Exception as e:
  • 14 raise e
  • 15 else:
  • 16 return str(currentDate)
  • 17 @staticmethod
  • 18 def getCurrentTime():
  • 19 '''
  • 20 获取当前时间
  • 21 :return:
  • 22 '''
  • 23 try:
  • 24 Time = datetime.now()
  • 25 currentTime = Time.strftime('%H_%M_%S')
  • 26 except Exception as e:
  • 27 raise e
  • 28 else:
  • 29 return currentTime
  • 30 @staticmethod
  • 31 def CreatePicturePath():
  • 32 '''
  • 33 创建图片存放路径路径
  • 34 :return:
  • 35 '''
  • 36 try:
  • 37
  • 38 picturePath = os.path.join(exceptionPath , DirAndTime.getCurrentDate())
  • 39 if not os.path.exists(picturePath):
  • 40 os.makedirs(picturePath) # 生成多级目录
  • 41 except Exception as e:
  • 42 raise e
  • 43 else:
  • 44 return picturePath
  • 45
  • 46 if __name__=='__main__':
  • 47 print(DirAndTime.getCurrentDate())
  • 48 print(DirAndTime.getCurrentTime())
  • 49 print(DirAndTime.CreatePicturePath())

6.新建ParseExcel.py用来解析excel文件

    • 1 from openpyxl import load_workbook
  • 2 from config.VarConfig import *
  • 3 from datetime import datetime, date
  • 4
  • 5 class ParseExcel(object):
  • 6 '''
  • 7 解析excel文件的封装
  • 8 '''
  • 9 def __init__(self):
  • 10 # 加载excel文件到内存
  • 11 self.wb = load_workbook(excelPath)
  • 12
  • 13 def getRowValue(self, sheetName, rawNo):
  • 14 '''
  • 15 获取某一行的数据
  • 16 :param sheetName:
  • 17 :param rawNo:
  • 18 :return: 列表
  • 19 '''
  • 20 sh = self.wb[sheetName]
  • 21 rowValueList = []
  • 22 for y in range(2, sh.max_column+1):
  • 23 value = sh.cell(rawNo,y).value
  • 24 rowValueList.append(value)
  • 25 return rowValueList
  • 26 def getColumnValue(self, sheetName, colNo):
  • 27 '''
  • 28 获取某一列的数据
  • 29 :param sheetName:
  • 30 :param colNo:
  • 31 :return: 列表
  • 32 '''
  • 33 sh = self.wb[sheetName]
  • 34 colValueList = []
  • 35 for x in range(2, sh.max_row +1):
  • 36 value = sh.cell(x, colNo).value
  • 37 colValueList.append(value)
  • 38 return colValueList
  • 39
  • 40 def getCellOfValue(self, sheetName, rowNo, colNo):
  • 41 '''
  • 42 获取某一个单元格的数据
  • 43 :param sheetName:
  • 44 :param rowNo:
  • 45 :param colNo:
  • 46 :return: 字符串
  • 47 '''
  • 48 sh = self.wb[sheetName]
  • 49 value = sh.cell(rowNo, colNo).value
  • 50 return value
  • 51 def writeCell(self, sheetName, rowNo, colNo, value):
  • 52 '''
  • 53 向某个单元格写入数据
  • 54 :param rowNo: 行号
  • 55 :param colNo: 列号
  • 56 :param value:
  • 57 :return: 无
  • 58 '''
  • 59 sh = self.wb[sheetName]
  • 60 sh.cell(rowNo, colNo).value = value
  • 61 self.wb.save(excelPath)
  • 62 def writeCurrentTime(self, sheetName, rowNo, colNo):
  • 63 '''
  • 64 向某个单元格写入当前时间
  • 65 :return:
  • 66 '''
  • 67 sh = self.wb[sheetName]
  • 68 Time = datetime.now()
  • 69 currentTime = Time.strftime('%Y:%m:%d %H:%M:%S')
  • 70 sh.cell(rowNo, colNo).value = currentTime
  • 71 self.wb.save(excelPath)
  • 72
  • 73 def writeTestResult(self, sheetName, rowNo, result, errorInfo = None, errorPic = None):
  • 74 ParseExcel().writeCurrentTime(sheetName, rowNo, testStep_testRunTime)
  • 75 ParseExcel().writeCell(sheetName, rowNo, testStep_testResult, result)
  • 76 if errorInfo and errorInfo:
  • 77 ParseExcel().writeCell(sheetName, rowNo, testStep_testErrorInfo, errorInfo)
  • 78 ParseExcel().writeCell(sheetName, rowNo, testStep_testErrorPic, errorPic)
  • 79 else:
  • 80 ParseExcel().writeCell(sheetName, rowNo, testStep_testErrorInfo, '')
  • 81 ParseExcel().writeCell(sheetName, rowNo, testStep_testErrorPic, '')
  • 82 if __name__=='__main__':
  • 83 p = ParseExcel()
  • 84 print(p.getRowValue('126account',2))
  • 85 print(p.getColumnValue('126account',3))
  • 86 print(p.getCellOfValue('126account', 2, 3))

7.新建Log.py文件,用来记录代码运行日志

    • 1 import logging
  • 2 import time
  • 3 from config.VarConfig import *
  • 4
  • 5 class Logger(object):
  • 6 '''
  • 7 封装的日志模块
  • 8 '''
  • 9 def __init__(self, logger, CmdLevel=logging.INFO, FileLevel=logging.INFO):
  • 10 """
  • 11
  • 12 :param logger:
  • 13 :param CmdLevel:
  • 14 :param FileLevel:
  • 15 """
  • 16 try:
  • 17 self.logger = logging.getLogger(logger)
  • 18 self.logger.setLevel(logging.DEBUG) # 设置日志输出的默认级别
  • 19 # 日志输出格式
  • 20 fmt = logging.Formatter('%(asctime)s - %(filename)s:[%(lineno)s] - [%(levelname)s] - %(message)s')
  • 21 # 日志文件名称
  • 22 # self.LogFileName = os.path.join(conf.log_path, "{0}.log.txt".format(time.strftime("%Y-%m-%d")))# %H_%M_%S
  • 23 currTime = time.strftime("%Y-%m-%d")
  • 24 self.LogFileName = logPath+currTime+'.txt'
  • 25 # 设置控制台输出
  • 26 # sh = logging.StreamHandler()
  • 27 # sh.setFormatter(fmt)
  • 28 # sh.setLevel(CmdLevel)# 日志级别
  • 29
  • 30 # 设置文件输出
  • 31 fh = logging.FileHandler(self.LogFileName)
  • 32 fh.setFormatter(fmt)
  • 33 fh.setLevel(FileLevel)# 日志级别
  • 34
  • 35 # self.logger.addHandler(sh)
  • 36 self.logger.addHandler(fh)
  • 37 except Exception as e:
  • 38 raise e
  • 39
  • 40 if __name__ == '__main__':
  • 41 logger = Logger("fox",CmdLevel=logging.DEBUG, FileLevel=logging.DEBUG)
  • 42 logger.logger.debug("debug")
  • 43 logger.logger.log(logging.ERROR,'%(module)s %(info)s',{'module':'log日志','info':'error'}) #ERROR,log日志 error
业务操作功能模块

新建action文件夹,主要存储页面的各种操作,如点击操作,输入操作等1.文件夹下新建PageAction.py文件

    • 1 from util.ObjectMap import *
  • 2 from util.ClipboardUtil import Clipboard
  • 3 from util.KeyBoardUtil import KeyBoardKeys
  • 4 from util.WaitUntil import WaitUnit
  • 5 from util.DirAndTime import *
  • 6 from selenium import webdriver
  • 7
  • 8 driver = None
  • 9 waitUtil = None
  • 10 # 打开浏览器
  • 11 def openBrowser(browser):
  • 12 global driver, waitUtil
  • 13 try:
  • 14 if browser.lower() =='ie':
  • 15 driver = webdriver.Ie(executable_path=iePath)
  • 16 elif browser.lower() == 'chrome':
  • 17 driver = webdriver.Chrome(executable_path=chromePath)
  • 18 else:
  • 19 # driver = webdriver.Firefox(executable_path=fireFox)
  • 20 driver = webdriver.Firefox()
  • 21 except Exception as e:
  • 22 raise e
  • 23 else:
  • 24 waitUtil = WaitUnit(driver) # driver 创建之后, 创建等待类实例对象
  • 25
  • 26 # 浏览器窗口最大化
  • 27 def maximize_browser():
  • 28 try:
  • 29 driver.maximize_window()
  • 30 except Exception as e:
  • 31 raise e
  • 32 # 加载网址
  • 33 def loadUrl(url):
  • 34 try:
  • 35 driver.get(url)
  • 36 except Exception as e:
  • 37 raise e
  • 38
  • 39 # 强制等待
  • 40 def sleep(sleepSeconds):
  • 41 try:
  • 42 import time
  • 43 time.sleep(sleepSeconds)
  • 44 except Exception as e:
  • 45 raise e
  • 46 # 清除输入框的内容
  • 47 def clear(by, locator):
  • 48 try:
  • 49 getElement(driver, by, locator).clear()
  • 50 except Exception as e:
  • 51 raise e
  • 52 # 输入框中输入内容
  • 53 def inputValue(by, locator, value):
  • 54 try:
  • 55 element = getElement(driver, by, locator)
  • 56 # element.click()
  • 57 element.send_keys(value)
  • 58 except Exception as e:
  • 59 raise e
  • 60 # 点击操作
  • 61 def clickBtn(by, locator):
  • 62 try:
  • 63 getElement(driver, by, locator).click()
  • 64 except Exception as e:
  • 65 raise e
  • 66 # 断言页面的title
  • 67 def assertTitle(titleStr):
  • 68 try:
  • 69 assert titleStr in driver.title, "%s not found in title!" % titleStr
  • 70 except AssertionError as e:
  • 71 raise AssertionError(e)
  • 72 except Exception as e:
  • 73 raise e
  • 74
  • 75 # 断言目标字符串是否包含在页面源码中
  • 76 def assert_string_in_page_source(assertString):
  • 77 try:
  • 78 assert assertString in driver.page_source, "%s not found in page source!" % assertString
  • 79 except AssertionError as e:
  • 80 raise AssertionError(e)
  • 81 except Exception as e:
  • 82 raise e
  • 83
  • 84 # 获取当前页面的title
  • 85 def getTitle():
  • 86 try:
  • 87 return driver.title
  • 88 except Exception as e:
  • 89 raise e
  • 90
  • 91 # 获取页面源码
  • 92 def getPageSource():
  • 93 try:
  • 94 return driver.page_source
  • 95 except Exception as e:
  • 96 raise e
  • 97 # 切换到frame里面
  • 98 def switchToFrame(by, locator):
  • 99 try:
  • 100 driver.switch_to.frame(getElement(driver, by, locator))
  • 101 except Exception as e:
  • 102 raise e
  • 103
  • 104 # 跳到默认的frame
  • 105 def switchToDefault():
  • 106 try:
  • 107 driver.switch_to.default_content()
  • 108 except Exception as e:
  • 109 raise e
  • 110
  • 111 # 模拟ctrl+v键
  • 112 def ctrlV(value):
  • 113 try:
  • 114 Clipboard.setText(value)
  • 115 sleep(2)
  • 116 KeyBoardKeys.twoKeys('ctrl', 'v')
  • 117 except Exception as e:
  • 118 raise e
  • 119
  • 120 # 模拟tab键
  • 121 def tabKey():
  • 122 try:
  • 123 KeyBoardKeys.oneKey('tab')
  • 124 except Exception as e:
  • 125 raise e
  • 126
  • 127 # 模拟enter键
  • 128 def enterKey():
  • 129 try:
  • 130 KeyBoardKeys.oneKey('enter')
  • 131 except Exception as e:
  • 132 raise e
  • 133
  • 134 # 屏幕截图
  • 135 def saveScreenShot():
  • 136 pictureName = DirAndTime.CreatePicturePath() +'\\'+DirAndTime.getCurrentTime() + '.png'
  • 137 try:
  • 138 driver.get_screenshot_as_file(pictureName)
  • 139 except Exception as e:
  • 140 raise e
  • 141 else:
  • 142 return pictureName
  • 143
  • 144 def waitPresenceOfElementLocated(by, locator):
  • 145 '''
  • 146 显示等待页面元素出现在DOM中,单并不一定可见
  • 147 :param by:
  • 148 :param locator:
  • 149 :return:
  • 150 '''
  • 151 waitUtil.presenceOfElementLocated(by, locator)
  • 152
  • 153 def waitFrameToBeAvailableAndSwitchToIt(by, locator):
  • 154 '''
  • 155 检查frame是否存在,存在就切换到frame中
  • 156 :param by:
  • 157 :param locator:
  • 158 :return:
  • 159 '''
  • 160 waitUtil.frameToBeAvailableAndSwtichToIt(by, locator)
  • 161
  • 162 def waitVisibiltyOfElementLocated(by, locator):
  • 163 '''
  • 164 显示等待页面元素出现在DOM中,并且可见
  • 165 :param by:
  • 166 :param locator:
  • 167 :return:
  • 168 '''
  • 169 waitUtil.visibiltyOfElementLocated(by, locator)
  • 170
  • 171 # 关闭浏览器
  • 172 def quitBroswer():
  • 173 try:
  • 174 driver.quit()
  • 175 except Exception as e:
  • 176 raise e
  • 177 if __name__=='__main__':
  • 178 openBrowser('firefox')
  • 179 loadUrl('http://www.baidu.com')
  • 180 # inputValue('id', 'kw','python')
  • 181 # clear('id', 'kw')
  • 182 # inputValue('id', 'kw', 'python')
  • 183 # clickBtn('id', 'su')
  • 184 # sleep(3)
  • 185 # title = getTitle()
  • 186 # print(title)
  • 187 # assertTitle('python')
  • 188 # assert_string_in_page_source('python')
  • 189 ctrlV('python')
项目数据文件设计

我们既然要实现关键字驱动的测试,无疑是通过关键字数据文件来控制代码的执行

新建testData文件夹,并新建126mailSend.xlsx文件。文件内容包括3个sheet页,分别为测试用例,登录,发送邮件

测试用例页

登录页

发送邮件页

注意:表格中的关键字 需要和PageAction.py中的方法名字保持一致

项目配置模块

新建config目录,并新建VarConfig.py文件记录全局的目录及excel文件部分信息

    • 1 # 存储全局的变量
  • 2 import os
  • 3
  • 4 # 项目根目录
  • 5 projectPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  • 6 # 截图目录
  • 7 exceptionPath = projectPath +r'\exceptionpictures'
  • 8
  • 9 # 驱动存放路径, 需要自己根据自己电脑的驱动为止修改
  • 10 iePath = ''
  • 11 chromePath = ''
  • 12 fireFox = ''
  • 13
  • 14 # excel文件存放路径
  • 15 excelPath = projectPath + r'\testData\126mailSend.xlsx'
  • 16 # loh文件存放路径
  • 17 logPath = projectPath + '\\log\\'
  • 18 # 测试用例部分列对应的列号
  • 19 testCase_testCaseName = 2
  • 20 testCase_testStepName = 4
  • 21 testCase_testIsExecute = 5
  • 22 testCase_testRunEndTime = 6
  • 23 testCase_testResult = 7
  • 24
  • 25 # 用例步骤对应的列号
  • 26 testStep_testNum = 1
  • 27 testStep_testStepDescribe = 2
  • 28 testStep_keyWord = 3
  • 29 testStep_elementBy = 4
  • 30 testStep_elementLocator = 5
  • 31 testStep_operateValue = 6
  • 32 testStep_testRunTime = 7
  • 33 testStep_testResult = 8
  • 34 testStep_testErrorInfo = 9
  • 35 testStep_testErrorPic = 10
  • 36
  • 37
  • 38 if __name__=='__main__':
  • 39
  • 40 print(projectPath)
  • 41 print(exceptionPath)
测试用例编写

前期所有的准备都已经完成,接下来我们开始编写测试用例

新建testCases文件夹,并新建Test126SendMailWithAttachment.py编写用例

  1. 1 from util.ParseExcel import ParseExcel
  2. 2 from config.VarConfig import *
  3. 3 from action.PageAction import *
  4. 4 import traceback
  5. 5 from util.log import Logger
  6. 6 import logging
  7. 7
  8. 8 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
  9. 9 p = ParseExcel()
  10. 10 sheetName = p.wb.sheetnames# 获取到excel的所有sheet名称
  11. 11
  12. 12 def Test126MailSendWithAtt():
  13. 13 try:
  14. 14 testCasePassNum = 0
  15. 15
  16. 16 requiredCase = 0
  17. 17 isExecuteColumnValues = p.getColumnValue(sheetName[0], testCase_testIsExecute)
  18. 18 # print(columnValues)
  19. 19 for index, value in enumerate(isExecuteColumnValues):
  20. 20 # print(index, value)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  1. 11
  2. 12 def Test126MailSendWithAtt():
  3. 13 try:
  4. 14 testCasePassNum = 0
  5. 15
  6. 16 requiredCase = 0
  7. 17 isExecuteColumnValues = p.getColumnValue(sheetName[0], testCase_testIsExecute)
  8. 18 # print(columnValues)
  9. 19 for index, value in enumerate(isExecuteColumnValues):
  10. 20 # print(index, value)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
[外链图片转存中…(img-SajZvA5Q-1713224681397)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值