先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新软件测试全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024b (备注软件测试)
正文
2 import win32con
3
4 class KeyBoardKeys(object):
5 '''
6 模拟键盘
7 '''
8 # 键盘编码
9 vk_code ={
10 'enter':0x0D,
11 'tab' : 0x09,
12 'ctrl':0x11,
13 'v':0x56
14 }
15 @staticmethod
16 def keyDown(keyName):
17 '''
18 模拟按下键
19 :param keyName:
20 :return:
21 '''
22 try:
23 win32api.keybd_event(KeyBoardKeys.vk_code[keyName],0,0,0)
24 except Exception as e:
25 raise e
26 @staticmethod
27 def keyUp(keyName):
28 '''
29 释放键
30 :param keyName:
31 :return:
32 '''
33 try:
34 win32api.keybd_event(KeyBoardKeys.vk_code[keyName],0,win32con.KEYEVENTF_KEYUP,0)
35 except Exception as e:
36 raise e
37 @staticmethod
38 def oneKey(key):
39 '''
40 模拟当个按键
41 :param key:
42 :return:
43 '''
44 try:
45 KeyBoardKeys.keyDown(key)
46 KeyBoardKeys.keyUp(key)
47 except Exception as e:
48 raise e
49
50 @staticmethod
51 def twoKeys(key1, key2):
52 '''
53 模拟组合按键
54 :param key1:
55 :param key2:
56 :return:
57 '''
58 try:
59 KeyBoardKeys.keyDown(key1)
60 KeyBoardKeys.keyDown(key2)
61 KeyBoardKeys.keyUp(key1)
62 KeyBoardKeys.keyUp(key2)
63 except Exception as e:
64 raise e
65
66 if __name__=='__main__':
67 from selenium import webdriver
68
69 driver = webdriver.Firefox()
70 driver.get('http://www.baidu.com')
71 driver.find_element_by_id('kw').send_keys('python')
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 from util.ParseExcel import ParseExcel
2 from config.VarConfig import *
3 from action.PageAction import *
4 import traceback
5 from util.log import Logger
6 import logging
7
8 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
9 p = ParseExcel()
10 sheetName = p.wb.sheetnames# 获取到excel的所有sheet名称
11
12 def Test126MailSendWithAtt():
13 try:
14 testCasePassNum = 0
15
16 requiredCase = 0
17 isExecuteColumnValues = p.getColumnValue(sheetName[0], testCase_testIsExecute)
18 # print(columnValues)
19 for index, value in enumerate(isExecuteColumnValues):
20 # print(index, value)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
11
12 def Test126MailSendWithAtt():
13 try:
14 testCasePassNum = 0
15
16 requiredCase = 0
17 isExecuteColumnValues = p.getColumnValue(sheetName[0], testCase_testIsExecute)
18 # print(columnValues)
19 for index, value in enumerate(isExecuteColumnValues):
20 # print(index, value)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
[外链图片转存中…(img-SajZvA5Q-1713224681397)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!