创建了一个测试群,大家相互总结资料分享最新得技术,目前群里面云集大量得大厂测开,问题基本都能解决 ,加我好友加入哦

总结得资料分为面经与技术文档总结

面试总结包含:linux、mysql、python、算法、测试基础、操作系统、Docker、Redis、RF、pytest、selenium等等

技术文档总结包含:linux、python基础与进阶、pytest、接口自动化、ui自动化、go、git、docker、算法数据结构等等



框架介绍

python-web自动化测试框架 框架:python3.6 + selenium3 + PageObject + Excel + unittest(基础测试框架)使用PageObject自动化设计模式---将页面定位和业务操作分离,将测试对象(元素),测试脚本(测试案例脚本)两者分离,便于脚本的维护, 如本文中日志页面封装成一个对象类(bolg_page.py),在封装一个测试脚本(test_blog.py)使用Excel文档管理元素数据和测试数据和关键字,拆分测试用例步骤,每个步骤对应一个关键字 格式如 测试步骤:点击新建日志按钮,关键字:click_element,操作元素定位方式:link_text,操作元素定位表达式:新建日志 测试数据: 当页面元素属性如id发生变化时,不需要去修改代码,直接更新Excel即可,提高案例的可维护性框架设计思路 框架层:提供基础公用模块,支持整个流程执行以及功能扩展 log.py(记录项目运行,方便快速定位问题)、config(存放配置数据,如项目地址,邮箱信息等)、read_ini.py(读取配置文件),read_excel(读取页面元素数据和测试用例数据) driver.py(封装chorme、ie、firefox等浏览器驱动)、report.py(用例驱动报告)、myunit.py(执行测试类文件和测试案例的前置和后置动作)业务层:页面业务流程的方法包(bolg_page.py),一个页面封装成一个测试类文件(继承基础类)用例层:测试用例集,测试用例 (对页面功能进行构造模拟执行测试)基础层:查找封装、操作封装,基础封装 目录结构介绍: config config.ini:项目路径 conf :配置文件路径 :测试用例存放路径 :测试报告存放路径 :日志文件存放路径 :测试数据存放路径 data: test_data.xlsx:元素数据、测试数据等 log: log:项目运行过程中生成的日志文件 page: base_page.py:元素定位、元素操作封装 XXX_page.py:页面业务流程方法包 test_case test_xxx_page.py:某个页面功能模拟执行案例 ................

一.前言

1.1项目框架

项目如何使用框架: 本项目采用unitest框架
设计模式是如何应用:本项目采用pageobject设计模式
UI对象库思想
项目设计一个模块(被测项目的页面)对应一个py文件及一个测试类(测试文件)
每一个测试页面(系统的页面)中存储页面元素及此页面中涉及到的功能
每一个用例组合在一个测试类里面生成一个py文件项目目标
我们在写自动化测试项目的时候一定要想好你的脚本都要哪些功能,页面元素平凡改动的时候是否需要大批量的修改脚本,及测试不同数据时是否也要修改脚本,那么能想到这些我们的初始目标差不多就有了
1. 生成测试用例执行结果报告
2.生成测试用例执行日志
3.用例执行失败或者执行完成后自动发送邮件报告
4. 用例执行失败或者成功时截取图片
5.数据驱动(读取测试数据,减少脚本维护成本)更多资料

1.2项目目录结构

Retail_TestProDocs# 存放项目的相关文档        01测试计划02测试大纲03测试用例04测试报告05测试进度06技术文档07测试申请Package# 存放第三方插件HTMLTestRunner.pyRetailConfig__init__.pyConf.py# 读配置文件获取项目跟目录路径 并获取所有欲使用的目录文件的路径Config.ini# 存放项目跟目录的路径DataTestData__init__.pyelementDate.xlsx# 存放项目中所有的元素信息及测试数据Email_receiver.txt# 存放邮件的接受者信息Report# 测试报告ImageFail# 存放用例执行失败时的截图Pass# 存放用例执行成功时的截图Log# 存放用例执行过程中的log信息TestReport# 存放测试用例执行完成后生成的测试报告Test_case# 测试用例信息Models # 存放一些公共方法Doconfini.py# 读配置文件Doexcel.py# 读excel文件Driver.py# 存放driverLog.py# 生成logMyunit.py# 继承unittest.TestcaseSendmail.py# 发送邮件Strhandle.py# 字符串处理Tcinfo.py# 测试用例基本信息Testreport.py# 测试报告Page_obj# 测试模块Activerule_page.pyBase_page.pyCompany_page.pyCreaterule_page.pyMemberquery_page.pyModifypw_page.pyPointquery_page.pyActiveRuleTc.pyCompanyQueryTc.pyCreateRuleTc.pyLoginTc.pyMemberQueryTc.pyModifyPwTc.pyPointQueryTc.pyrunTc.py# 执行测试用例

代码目录

二.项目代码

1.config.ini (存放项目跟路径)

[project]
project_path = D:\Petrochina_Retail_Test_Project

2.conf.py

'''Code description:read config.ini, get pathCreate time:Developer:'''import osimport sysfrom retail.test_case.models.doconfIni import DoConfIni# 获取当前路径currPath= \os.path.split(os.path.realpath(__file__))[0]# 读配置文件获取项目路径readConfig = \DoConfIni()proPath = \readConfig.getConfValue(os.path.join(currPath,'config.ini'),'project','project_path')# 获取日志路径logPath= \os.path.join(proPath,'retail','report','Log')# 测试用例路径tcPath = \os.path.join(proPath,'retail','test_case')# 获取报告路径reportPath= \os.path.join(proPath,'retail','report','TestReport')# 获取测试数据路径dataPath= \os.path.join(proPath,'retail','data','TestData')# 保存截图路径# 错误截图failImagePath = os.path.join(proPath, 'retail', 'report', 'image','fail')# 成功截图passImagePath = os.path.join(proPath, 'retail', 'report', 'image','pass')# 被调函数名称funcName = sys._getframe().f_code.co_name# 被调函数所在行号funcNo = sys._getframe().f_back.f_lineno# 被调函数所在文件名称funcFile= sys._getframe().f_code.co_filename

3.elementData.xlsx(json与yaml替换)

存放测试数据

4.公共方法models下面的文件

4.1doconfini.py

 '''Code description:read conf fileCreate time:Developer:'''import loggingimport configparserfrom retail.config.conf import *from retail.test_case.models.log import Loggerlog = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)class DoConfIni(object):def __init__(self):""":param filename:"""self.cf = configparser.ConfigParser()# 从ini文件中读数据def getConfValue(self,filename,section,name):""":param config::param name::return:"""try:self.cf.read(filename)value = self.cf.get(section,name)except Exception as e:log.logger.exception('read file [%s] for [%s] failed , did not get the value' %(filename,section))raise eelse:log.logger.info('read excel value [%s] successed! ' %value)return value# 向ini文件中写数据def writeConfValue(self,filename, section, name, value):""":param section: section:param name: value name:param value:  value:return: none"""try:self.cf.add_section(section)self.cf.set(section, name, value)self.cf.write(open(filename, 'w'))except Exception :log.logger.exception('section %s has been exist!' %section)raise configparser.DuplicateSectionError(section)else:log.logger.info('write section'+section+'with value '+value+' successed!')if __name__ == '__main__':file_path = currPathprint(file_path)read_config = DoConfIni()value = read_config.getConfValue(os.path.join(currPath,'config.ini'),'project','project_path')print(value)read_config.writeConfValue(os.path.join(currPath,'config.ini'),'tesesection', 'name', 'hello word')

4.2doexcel.py

'''Code description:read excel.xlsx, get valuesCreate time:Developer:'''import xlrdimport osimport loggingfrom retail.config import conffrom retail.test_case.models.log import Loggerlog = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)class ReadExcel(object):def __init__(self,fileName='elementDate.xlsx',sheetName='elementsInfo'):""":param fileName::param sheetName:"""try:self.dataFile = os.path.join(conf.dataPath, fileName)self.workBook = xlrd.open_workbook(self.dataFile)self.sheetName = self.workBook.sheet_by_name(sheetName)except Exception:log.logger.exception('init class ReadExcel fail', exc_info=True)raiseelse:log.logger.info('initing class ReadExcel')# 读excel中的数据def readExcel(self,rownum,colnum):""":param rownum::param colnum::return:"""try:value = self.sheetName.cell(rownum,colnum).valueexcept Exception:log.logger.exception('read value from excel file fail', exc_info=True)raiseelse:log.logger.info('reading value [%s] from excel file [%s] completed' %(value, self.dataFile))return valueif __name__ == '__main__':cellValue = ReadExcel().readExcel(1,3)print((cellValue))

4.3log.py

'''Code description:log infoCreate time:Developer:'''import loggingimport timeclass Logger(object):def __init__(self, logger, CmdLevel=logging.INFO, FileLevel=logging.INFO):""":param logger::param CmdLevel::param FileLevel:"""self.logger = logging.getLogger(logger)self.logger.setLevel(logging.DEBUG)  # 设置日志输出的默认级别# 日志输出格式fmt = logging.Formatter('%(asctime)s - %(filename)s:[%(lineno)s] - [%(levelname)s] - %(message)s')# 日志文件名称# self.LogFileName = os.path.join(conf.log_path, "{0}.log".format(time.strftime("%Y-%m-%d")))# %H_%M_%ScurrTime = time.strftime("%Y-%m-%d")self.LogFileName = r'D:\Petrochina_Retail_Test_Project\retail\report\Log\log'+currTime+'.log'# 设置控制台输出# sh = logging.StreamHandler()# sh.setFormatter(fmt)# sh.setLevel(CmdLevel)# 日志级别# 设置文件输出fh = logging.FileHandler(self.LogFileName)fh.setFormatter(fmt)fh.setLevel(FileLevel)# 日志级别# self.logger.addHandler(sh)self.logger.addHandler(fh)# def debug(self, message):#     """##     :param message:#     :return:#     """#     self.logger.debug(message)## def info(self,message):#     """##     :param message:#     :return:#     """#     self.logger.info(message)## def warn(self,message):#     """##     :param message:#     :return:#     """#     self.logger.warning(message)## def error(self,message):#     """##     :param message:#     :return:#     """#     self.logger.error(message)## def criti(self,message):#     """##     :param message:#     :return:#     """#     self.logger.critical(message)if __name__ == '__main__':logger = Logger("fox",CmdLevel=logging.DEBUG, FileLevel=logging.DEBUG)logger.logger.debug("debug")logger.logger.log(logging.ERROR,'%(module)s %(info)s',{'module':'log日志','info':'error'}) #ERROR,log日志 error

4.4sendmail.py

'''Code description:send emailCreate time:Developer:'''import smtplibfrom email.mime.text import MIMETextfrom email.header import Headerimport osfrom retail.config import conffrom retail.test_case.models.log import Loggerlog = Logger(__name__)#   邮件发送接口class SendMail(object):'''邮件配置信息'''def __init__(self,receiver,subject='Retail 系统测试报告',server='smtp.qq.com',fromuser='281754043@qq.com',frompassword='gifhhsbgqyovbhhc',sender='281754043@qq.com'):""":param receiver::param subject::param server::param fromuser::param frompassword::param sender:"""self._server = serverself._fromuser = fromuserself._frompassword = frompasswordself._sender = senderself._receiver = receiverself._subject = subjectdef sendEmail(self, fileName):""":param filename::return:"""#   打开报告文件读取文件内容try:f = open(os.path.join(conf.reportPath, fileName), 'rb')fileMsg = f.read()except Exception:log.logger.exception('open or read file [%s] failed,No such file or directory: %s' %(fileName, conf.reportPath))log.logger.info('open and read file [%s] successed!' %fileName)else:f.close()#   邮件主题subject = 'Python test report' ##   邮件设置msg = MIMEText(fileMsg, 'html', 'utf-8')msg['subject'] = Header(subject, 'utf-8')msg['from'] = self._sender#   连接服务器,登录服务器,发送邮件try:smtp = smtplib.SMTP()smtp.connect(self._server)smtp.login(self._fromuser, self._frompassword)except Exception:log.logger.exception('connect [%s] server failed or username and password incorrect!' %smtp)else:log.logger.info('email server [%s] login success!' %smtp)try:smtp.sendmail(self._sender, self._receiver, msg.as_string())except Exception:log.logger.exception('send email failed!')else:log.logger.info('send email successed!')#   从文件中读取邮件接收人信息def getReceiverInfo(fileName):''':param filename: 读取接收邮件人信息:return: 接收邮件人信息'''try:openFile = open(os.path.join(conf.dataPath, fileName))except Exception:log.logger.exception('open or read file [%s] failed,No such file or directory: %s' %(fileName, conf.dataPath))else:log.logger.info('open file [%s] successed!' %fileName)for line in openFile:msg = [i.strip() for i in line.split(',')]log.logger.info('reading [%s] and got receiver value is [%s]' %(fileName, msg))return msgif __name__ == '__main__':readMsg=getReceiverInfo('mail_receiver.txt')sendmail = SendMail(readMsg)sendmail.sendEmail('2021-04-21 17_44_04.html')

4.5strhandle.py

'''Code description: string handleCreate time:Developer:'''import loggingfrom retail.test_case.models.log import Loggerlog = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)def strhandle(str):""":param str::return:"""#初始化字符、数字、空格、特殊字符的计数try:lowerCase = 0upperCase = 0number = 0other = 0for stritem in str:#如果在字符串中有小写字母,那么小写字母的数量+1if stritem.islower():lowerCase += 1#如果在字符串中有数字,那么数字的数量+1elif stritem.isdigit():number += 1elif stritem.isupper():# 大写字母upperCase +=1#如果在字符串中有空格,那么空格的数量+1else:other += 1return lowerCase, upperCase, number, otherexcept Exception as e:log.logger.exception('string handle error , please check!', exc_info=True)raise eif __name__=='__main__':list = ['qwert','erwer']lowercase, uppercase, number, other = strhandle(list[0])print ("该字符串中的小写字母有:%d" %lowercase)print ("该字符串中的大写写字母有:%d" %uppercase)print ("该字符串中的数字有:%d" %number)print ("该字符串中的特殊字符有:%d" %other)

4.6testreport.py

'''Code description:test reportCreate time:Developer:'''import timeimport loggingimport unittestfrom BeautifulReport import BeautifulReportimport HTMLTestRunnerfrom retail.config import conffrom retail.test_case.models.log import Loggerlog = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)# 用HTMLTestRunner 实现的测试报告def testreport():""":return:"""currTime = time.strftime('%Y-%m-%d %H_%M_%S')fileName = conf.reportPath + r'\report' + currTime + '.html'try:fp = open(fileName, 'wb')except Exception :log.logger.exception('[%s] open error cause Failed to generate test report' %fileName)else:runner = HTMLTestRunner.HTMLTestRunner\(stream=fp, title='Retail sys测试报告',description='处理器:Intel(R) Core(TM) ''i5-6200U CPU @ 2030GHz 2.40 GHz ''内存:8G 系统类型: 64位 版本: windows 10 家庭中文版')log.logger.info('successed to generate test report [%s]' %fileName)return runner, fp, fileName#def addTc(TCpath = conf.tcPath, rule = '*TC.py'):""":param TCpath: 测试用例存放路径:param rule: 匹配的测试用例文件:return:  测试套件"""discover = unittest.defaultTestLoader.discover(TCpath, rule)return discover# 用BeautifulReport模块实现测试报告def runTc(discover):""":param discover: 测试套件:return:"""currTime = time.strftime('%Y-%m-%d %H_%M_%S')fileName = currTime+'.html'try:result = BeautifulReport(discover)result.report(filename=fileName, description='测试报告', log_path=conf.reportPath)except Exception:log.logger.exception('Failed to generate test report', exc_info=True)else:log.logger.info('successed to generate test report [%s]' % fileName)return fileNameif __name__ == '__main__':testreport()suite = addTc(rule = '*TC.py')runTc(suite)

4.7driver.py

'''Code description:save all driver infoCreate time:Developer:'''from selenium import webdriverimport loggingimport sysfrom retail.test_case.models.log import Loggerlog = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)class WDriver(object):# Firefox driverdef fireFoxDriver(self):""":return:"""try:self.driver = webdriver.Firefox()except Exception as e:log.logger.exception('FireFoxDriverServer.exe executable needs to be in PATH. Please download!', exc_info=True)raise eelse:log.logger.info('%s:found the Firefox driver [%s] successed !' %(sys._getframe().f_code.co_name,self.driver))return self.driver# chrom driverdef chromeDriver(self):""":return:"""try:# option = webdriver.ChromeOptions()# 实现不打开浏览器 执行web自动化测试脚本# option.add_argument('headless')## self.driver = webdriver.Chrome(chrome_options=option)self.driver = webdriver.Chrome()except Exception as e:log.logger.exception('ChromeDriverServer.exe executable needs to be in PATH. Please download!',exc_info=True)raise eelse:log.logger.info('%s:found the chrome driver [%s] successed !' % (sys._getframe().f_code.co_name, self.driver))return self.driver# Ie driverdef ieDriver(self):""":return:"""try:self.driver = webdriver.Ie()except Exception as e:log.logger.exception('IEDriverServer.exe executable needs to be in PATH. Please download!',exc_info=True)raise eelse:log.logger.info('%s:found the IE driver [%s] successed !' % (sys._getframe().f_code.co_name, self.driver))return self.driverif __name__ == '__main__':WDrive=WDriver()WDrive.fireFoxDriver()

4.8myunittest.py

'''Code description:unittest framworkCreate time:Developer:'''from retail.test_case.models.driver import WDriverimport loggingimport unittestfrom retail.test_case.page_obj.login_page import LoginPagefrom retail.test_case.models.log import Loggerfrom selenium import webdriverlog = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)class MyunitTest(unittest.TestCase):""""""# add by xuechao at 2018.09.19@classmethoddef setUpClass(cls): # 一个测试类(文件)执行一次打开浏览器, 节约每个用例打开一次浏览器的时间#cls.driver = WDriver().fireFoxDriver()cls.driver = WDriver().chromeDriver()cls.driver.maximize_window()log.logger.info('opened the browser successed!')# ----------------------------def setUp(self):""":return:"""self.login = LoginPage(self.driver)self.login.open()log.logger.info('************************starting run test cases************************')def tearDown(self):""":return:"""self.driver.refresh()log.logger.info('************************test case run completed************************')# add by linuxchao at 2018.09.19@classmethoddef tearDownClass(cls):cls.driver.quit()log.logger.info('quit the browser success!')#----------------------------if __name__ == '__main__':unittest.main()

4.9结束语

目前为止,我需要的所有的公共方法都编写完了, 后期再需要别的方法可以加,下面我们就开始编写我们的测试用例,由于我们使用的是PageObject模式,那么我们需要设计一个basepage页面,所有的页面或者说模块全部继承这个basepage,basepage主要编写所有页面的公共方法

5.base_page.py

 '''Code description: base page 封装一些公共方法Create time:Developer:'''from selenium.webdriver.support.wait import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.by import Byimport osimport loggingimport sysfrom retail.test_case.models.log import Loggerfrom retail.config import conffrom retail.test_case.models.doexcel import ReadExceleleData = ReadExcel() # 存储系统所有的元素数据testLoginData = ReadExcel('elementDate.xlsx', 'userNamePw') # 登录模块测试数据modifyPwData = ReadExcel('elementDate.xlsx', 'modifyPw') # 修改密码模块测试数据queryData = ReadExcel('elementDate.xlsx', 'queryData')log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)class BasePage(object):"""主菜单"""menuList = \[(By.LINK_TEXT, eleData.readExcel(7, 3)), # 权限管理(By.LINK_TEXT, eleData.readExcel(8, 3)), # 会员档案(By.LINK_TEXT, eleData.readExcel(9, 3)), # 积分消费查询(By.LINK_TEXT, eleData.readExcel(10, 3)), # 功能演示(By.LINK_TEXT, eleData.readExcel(11, 3)), # 待办工作(By.LINK_TEXT, eleData.readExcel(12, 3)), # 报表(By.LINK_TEXT, eleData.readExcel(13, 3)), # 积分规则/活动查询(By.LINK_TEXT, eleData.readExcel(14, 3))] # 积分规则/活动申请def __init__(self, driver,url='http://11.11.164.134:9081/rmms/modules/ep.rmms.portal/login/login.jsp'):""":param driver::param url:"""self.driver = driverself.base_url = urldef _open(self,url):""":param url::return:"""try:self.driver.get(url)self.driver.implicitly_wait(10)except Exception as e:log.logger.exception(e, exc_info=True)raise ValueError('%s address access error, please check!' %url)else:log.logger.info('%s is accessing address %s at line[46]' %(sys._getframe().f_code.co_name,url))def open(self):""":return:"""self._open(self.base_url)log.logger.info('%s loading successed!' %self.base_url)return self.base_url# *loc 代表任意数量的位置参数def findElement(self, *loc):"""查找单一元素:param loc::return:"""try:WebDriverWait(self.driver,10).until(EC.visibility_of_element_located(loc))# log.logger.info('The page of %s had already find the element %s'%(self,loc))# return self.driver.find_element(*loc)except Exception as e:log.logger.exception('finding element timeout!, details' ,exc_info=True)raise eelse:log.logger.info('The page of %s had already find the element %s' % (self, loc))return self.driver.find_element(*loc)def findElements(self, *loc):"""查找一组元素:param loc::return:"""try:WebDriverWait(self.driver,10).until(EC.visibility_of_element_located(loc))# log.logger.info('The page of %s had already find the element %s' % (self, loc))# return self.driver.find_elements(*loc)except Exception as e:log.logger.exception('finding element timeout!, details', exc_info=True)raise eelse:log.logger.info('The page of %s had already find the element %s' % (self, loc))return self.driver.find_elements(*loc)def inputValue(self, inputBox, value):"""后期修改其他页面直接调用这个函数:param inputBox::param value::return:"""inputB = self.findElement(*inputBox)try:inputB.clear()inputB.send_keys(value)except Exception as e:log.logger.exception('typing value error!', exc_info=True)raise eelse:log.logger.info('inputValue:[%s] is receiveing value [%s]' % (inputBox, value))# 获取元素数据def getValue(self, *loc):""":param loc::return:"""element = self.findElement(*loc)try:value = element.text#return valueexcept Exception:#element = self.find_element_re(*loc) # 2018.09.21 for logvalue = element.get_attribute('value')log.logger.info('reading the element [%s] value [%s]' % (loc, value))return valueexcept:log.logger.exception('read value failed', exc_info=True)raise Exceptionelse:log.logger.info('reading the element [%s] value [%s]' % (loc,value))return valuedef getValues(self, *loc):""":param loc::return:"""value_list = []try:for element in self.findElements(*loc):value = element.textvalue_list.append(value)except Exception as e:log.logger.exception('read value failed', exc_info=True)raise eelse:log.logger.info('reading the element [%s] value [%s]'% (loc,value_list))return value_list# 执行js脚本def jScript(self,src):""":param src::return:"""try:self.driver.excute_script(src)except Exception as e:log.logger.exception('execute js script [%s] failed ' %src)raise eelse:log.logger.info('execute js script [%s] successed ' %src)# 判断元素是否存在def isElementExist(self, element):""":param element::return:"""try:WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(element))except:# log.logger.exception('The element [%s] not exist', exc_info=True)return Falseelse:# log.logger.info('The element [%s] have existed!' %element)return True# 截图def saveScreenShot(self, filename):""":param filename::return:"""list_value = []list = filename.split('.')for value in list:list_value.append(value)if list_value[1] == 'png' or list_value[1] == 'jpg' or list_value[1] == 'PNG' or list_value[1] == 'JPG':if 'fail' in list_value[0].split('_'):try:self.driver.save_screenshot(os.path.join(conf.failImagePath, filename))except Exception:log.logger.exception('save screenshot failed !', exc_info=True)else:log.logger.info('the file [%s]  save screenshot successed under [%s]' % (filename, conf.failImagePath))elif 'pass' in list_value[0]:try:self.driver.save_screenshot(os.path.join(conf.passImagePath, filename))except Exception:log.logger.exception('save screenshot failed !', exc_info=True)else:log.logger.info('the file [%s]  save screenshot successed under [%s]' % (filename, conf.passImagePath))else:log.logger.info('save screenshot failed due to [%s] format incorrect' %filename)else:log.logger.info('the file name of [%s] format incorrect cause save screenshot failed, please check!' % filename)# 接受错误提示框def accept(self, *loc):""":return:"""self.findElement(*loc).click()log.logger.info('closed the error information fram successed!')if __name__ == '__main__':pass

6.login_page.py(登陆页面)

'''Code description: login pageCreate time:Developer:'''from selenium.webdriver.common.by import Byimport loggingimport sysfrom retail.test_case.page_obj.base_page import BasePage, eleData, testLoginDatafrom retail.test_case.models.log import Loggerlog = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)class LoginPage(BasePage):"""用户名,密码,登录按钮,保存信息,错误提示"""userNameEle = (By.ID, eleData.readExcel(1, 3))passWordEle = (By.ID, eleData.readExcel(2, 3))loginBtnEle = (By.ID, eleData.readExcel(3, 3))saveInfoEle = (By.NAME, eleData.readExcel(4, 3))errorMessage = (By.ID, eleData.readExcel(5, 3))quitBtn = (By.ID, eleData.readExcel(6, 3))# 用户名和密码unpwData = \[[testLoginData.readExcel(1, 0), testLoginData.readExcel(1, 1)],# 正确的用户名和正确的密码[testLoginData.readExcel(2, 0), testLoginData.readExcel(2, 1)],# 错误的用户名和正确的密码[testLoginData.readExcel(3, 0), testLoginData.readExcel(3, 1)],# 空的用户名和正确的密码[testLoginData.readExcel(4, 0), testLoginData.readExcel(4, 1)],# 错误的用户名和错误的密码[testLoginData.readExcel(5, 0), testLoginData.readExcel(5, 1)],# 正确的用户名和空密码[testLoginData.readExcel(6, 0), testLoginData.readExcel(6, 1)],# 正确的用户名和错误的密码[testLoginData.readExcel(7, 0), testLoginData.readExcel(7, 1)]]# 空用户名和空密码# 登录按钮def clickLoginBtn(self):""":return:"""element = self.findElement(*self.loginBtnEle)element.click()log.logger.info('%s ,logining....!' % sys._getframe().f_code.co_name)# 登录失败时提示def getFailedText(self):""":return:"""info = self.findElement(*self.errorMessage).textlog.logger.info('login failed : %s' %info)return info# 登录失败时弹出的alertdef handleAlert(self):""":return:"""try:alert = self.driver.switch_to_alert()text = alert.textalert.accept()except Exception:log.logger.exception('handle alert failed, please check the details' ,exc_info=True)raiseelse:log.logger.info('login failed ,%s handle alert successed alert info: %s!' %(sys._getframe().f_code.co_name, text))return text# 统一登录函数def loginFunc(self, username='rmln', password='qwert1234!@#'):""":param username::param password::return:"""self.inputValue(self.userNameEle, username)self.inputValue(self.passWordEle, password)self.clickLoginBtn()# 清空输入框数据def clearValue(self, element):empty = self.findElement(*element)empty.clear()log.logger.info('emptying value.......')# 推出def quit(self):self.findElement(*self.quitBtn).click()log.logger.info('quit')if __name__ == '__main__':pass

7.LoginTC.py(登陆测试用例)

 """Code description:login testcaseCreate time:Developer:"""import unittestimport timeimport loggingimport sysfrom retail.test_case.models.myunit import MyunitTestfrom retail.test_case.models.log import Loggerlog = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)class Login_TC(MyunitTest):"""登录模块测试用例"""def test_login_success_correct_username_password(self):"""用户名正确,密码正确,登录成功"""self.login.loginFunc()currUrl = self.driver.current_url # 获取当前的url地址try:self.assertIn('main', currUrl, 'main not in current url!')except Exception:self.login.saveScreenShot('correct_username_password_fail.png')raiseelse:self.login.saveScreenShot('correct_username_password_pass.png')log.logger.info('%s->run completed! please check the test report' % (sys._getframe().f_code.co_name))def test_login_failed_incorrect_username(self):"""用户名错误,密码正确,登录失败"""self.login.loginFunc(self.login.unpwData[1][0], self.login.unpwData[1][1])failText = self.login.getFailedText()self.assertEqual('输入的用户名或密码错误,请重新输入!', failText, '提示信息错误')log.logger.info('%s->run completed! please check the test report' % (sys._getframe().f_code.co_name))def test_login_failed_incorrect_password(self):"""用户名正确,密码错误,登录失败"""self.login.loginFunc(self.login.unpwData[5][0], self.login.unpwData[5][1])failText = self.login.getFailedText()self.assertEqual('输入的用户名或密码错误,请重新输入!', failText, '提示信息错误')log.logger.info('%s->run completed! please check the test report' % (sys._getframe().f_code.co_name))def test_login_failed_username_password_blank(self):"""用户名为空,密码为空,登录失败"""self.login.loginFunc(self.login.unpwData[6][0], self.login.unpwData[6][1])failText = self.login.handleAlert() # 获取alert的提示信息self.assertEqual('请填写用户名', failText, '提示信息错误')log.logger.info('%s->run completed! please check the test report' % (sys._getframe().f_code.co_name))def test_login_failed_password_blank(self):"""用户名正确,密码为空,登录失败"""self.login.loginFunc(self.login.unpwData[4][0], self.login.unpwData[4][1])failText = self.login.handleAlert() # 获取alert的提示信息self.assertEqual('请填写用户密码', failText, '提示信息错误')log.logger.info('%s->run completed! please check the test report' % (sys._getframe().f_code.co_name))def test_login_failed_unpw_incorrect(self):"""用户名错误,密码错误,登录失败"""# try:self.login.loginFunc(self.login.unpwData[3][0], self.login.unpwData[4][0])failText = self.login.getFailedText()self.assertEqual ('输入的用户名或密码错误,请重新输入!', failText, 'failed')log.logger.info('%s->run completed! please check the test report' % (sys._getframe().f_code.co_name))def test_login(self):"""循环测试登录功能"""for listitem in self.login.unpwData:self.login.inputValue(self.login.userNameEle,listitem[0])time.sleep(2)self.login.inputValue(self.login.passWordEle,listitem[1])time.sleep(2)self.login.clickLoginBtn()time.sleep(2)if listitem[0] =='rmln' and listitem[1] == 'qwert1234!@#':currUrl = self.driver.current_urlself.assertIn ('main' , currUrl)self.login.quit()elif listitem[0] == 'rmln' and listitem[1] != 'qwert1234!@#':if listitem[1] == '':failText = self.login.handleAlert()  # 获取alert的提示信息self.assertEqual('请填写用户密码', failText, '提示信息错误')else:failText = self.login.getFailedText()self.assertEqual('输入的用户名或密码错误,请重新输入!', failText, '提示信息错误')elif listitem[0] != 'rmln' and listitem[1] == 'qwert1234!@#':if listitem[0]=='':failText = self.login.handleAlert()  # 获取alert的提示信息self.assertEqual('请填写用户名', failText, '提示信息错误')else:failText = self.login.getFailedText()self.assertEqual('输入的用户名或密码错误,请重新输入!', failText, '提示信息错误')elif listitem[0] == listitem[1] == '':failText = self.login.handleAlert()  # 获取alert的提示信息self.assertEqual('请填写用户名', failText, '提示信息错误')else:failText = self.login.getFailedText()self.assertEqual('输入的用户名或密码错误,请重新输入!', failText, '提示信息错误')log.logger.info('%s->run completed! please check the test report' % (sys._getframe().f_code.co_name))if __name__ == '__main__':unittest.main()

8.modifypw_page.py(修改密码页面)

'''Code description:modify password pageCreate time:Developer:'''import loggingimport timefrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsfrom retail.test_case.page_obj.base_page import BasePage, eleData, modifyPwDatafrom retail.test_case.models.log import Loggerlog = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)class PrimaryMenu(BasePage):"""密码数据"""pwdList = \[[modifyPwData.readExcel(1, 0), modifyPwData.readExcel(1, 1), modifyPwData.readExcel(1, 2)],[modifyPwData.readExcel(2, 0), modifyPwData.readExcel(2, 1), modifyPwData.readExcel(2, 2)],[modifyPwData.readExcel(3, 0), modifyPwData.readExcel(3, 1), modifyPwData.readExcel(3, 2)],[modifyPwData.readExcel(4, 0), modifyPwData.readExcel(4, 1), modifyPwData.readExcel(4, 2)],[modifyPwData.readExcel(5, 0), modifyPwData.readExcel(5, 1), modifyPwData.readExcel(5, 2)]]"""权限管理下拉菜单"""menuPersonal = (By.LINK_TEXT, eleData.readExcel(15, 3))menuModifyPwd = (By.LINK_TEXT, eleData.readExcel(16, 3))"""密码修改"""oldPwd = (By.ID, eleData.readExcel(17, 3))newPwd = (By.ID, eleData.readExcel(18, 3))commitPwd = (By.ID, eleData.readExcel(19, 3))"""错误提示框及确定"""errMessage = (By.XPATH, eleData.readExcel(20, 3))closeBtn = (By.CSS_SELECTOR, eleData.readExcel(21, 3))"""密码说明"""readMe = (By.ID, eleData.readExcel(22, 3))"""保存"""saveBtn = (By.XPATH, eleData.readExcel(23, 3))#   主菜单def findMenu(self,*menuList):""":param menu_list::return:"""return self.findElement(*menuList)#   旧密码输入框def inputOldPw(self, oldPwd=''):""""""try:self.findElement(*self.oldPwd).clear()self.findElement(*self.oldPwd).send_keys(oldPwd)except Exception:log.logger.exception('input Pw [%s] for oldPw [%s] fail' %(oldPwd, self.oldPwd))raiseelse:log.logger.info('inputing Pw [%s] for oldPw [%s] ' % (oldPwd, self.oldPwd))#   新密码输入框def inputNewPw(self, newPwd=''):""":param newPwd::return:"""try:self.findElement(*self.newPwd).clear()self.findElement(*self.newPwd).send_keys(newPwd)except Exception:log.logger.exception('input Pw [%s] for newPw [%s] fail' % (newPwd, self.newPwd))raiseelse:log.logger.info('inputing Pw [%s] for newPw [%s] ' % (newPwd, self.newPwd))#   确认密码输入框def inputConfirmPw(self, confirmPwd=''):""":param confirmPwd::return:"""try:self.findElement(*self.commitPwd).clear()self.findElement(*self.commitPwd).send_keys(confirmPwd)except Exception:log.logger.exception('input Pw [%s] for commitPw [%s] fail' %(confirmPwd, self.commitPwd))raiseelse:log.logger.info('inputing Pw [%s] for commitPw [%s] ' %(confirmPwd, self.commitPwd))#   保存def saveButton(self):""":return:"""try:self.driver.implicitly_wait(5)clickbutton = self.findElement(*self.saveBtn)time.sleep(1)clickbutton.click()except Exception:log.logger.exception('click save button fail')raiseelse:log.logger.info('clciking the button')#   修改密码功能菜单def modifyPwMenu(self):""":return:"""try:self.findElement(*self.menuList[0]).click()self.findElement(*self.menuPersonal).click()self.findElement(*self.menuModifyPwd).click()except Exception:log.logger.exception('not found menu [%s]-[%s]-[%s]' %(self.menuList[0], self.menuPersonal, self.menuModifyPwd))raiseelse:log.logger.info('finding menu [%s]-[%s]-[%s]' %(self.menuList[0], self.menuPersonal, self.menuModifyPwd))self.driver.implicitly_wait(2)#   修改密码def modifyPw(self, list):""":param list::return:"""try:self.inputOldPw(list[0])self.inputNewPw(list[1])self.inputConfirmPw(list[2])self.saveButton()except Exception:log.logger.exception('input oldpw/newpw/commitpw [%s]/[%s]/[%s] fail' %(list[0], list[1], list[2]))raiseelse:log.logger.info('modifing pw [%s]/[%s]/[%s]' %(list[0], list[1], list[2]))#   错误提示框def errorDialog(self, commit_btn = (By.ID,'unieap_form_Button_1_unieap_input')):""":type commit_btn: 元祖"""try:messages_frame = self.findElement(*self.errMessage)text = messages_frame.textelement = self.findElement(*commit_btn)time.sleep(2)action = ActionChains(self.driver)action.move_to_element(element).perform()time.sleep(2)element.click()action.reset_actions() # 释放鼠标except Exception:log.logger.exception('close errMsgFram [%s] or get text [%s]fail' %(self.errMessage))raiseelse:log.logger.info('close errMsgFram [%s] and get text [%s] success' %(self.errMessage, text))return text# 关闭提示框def closeErrMsg(self, element):try:ele = self.findElement(*element)action = ActionChains(self.driver)action.move_to_element(ele).perform()time.sleep(2)ele.click()action.reset_actions()except Exception:log.logger.exception('close the err msg ifram fail', exc_info=True)raiseelse:log.logger.info('closing the err msg ifram success!')if __name__ == '__main__':pass

9.ModifyPw.py(修改密码测试用例)

'''Code description:权限管理/个人设置/密码修改 testcaseCreate time:Developer:'''import timefrom retail.test_case.models.myunit import MyunitTestfrom retail.test_case.page_obj.modifypw_page import PrimaryMenufrom retail.test_case.models.strhandle import strhandleclass ModifyPw_TC(MyunitTest):"""权限管理/个人设置/密码修改模块测试用例"""def test_menu_is_display(self):"""主菜单校验"""self.login.loginFunc()menu = PrimaryMenu(self.driver)time.sleep(4)num = 0for menu_item in menu.menuList: # 循环遍历并断言菜单是否正确self.assertEqual(menu.menuList[num][1],(menu.findMenu(*menu_item).text),'菜单不存在')num=num+1def test_modify_password_len(self):"""旧密码非空,新密码长度小于4位,确认密码非空,修改密码失败,弹窗提示"""self.login.loginFunc()menu = PrimaryMenu(self.driver)menu.modifyPwMenu() # 查找修改密码页面menu.modifyPw(menu.pwdList[0]) # 修改密码text = menu.errorDialog(menu.closeBtn)self.assertIn('密码长度至少 4 位!', text, '提示信息错误') # 密码长度不满足时断言提示信息def test_modify_password_strebgth(self):"""旧密码非空,新密码长度大于4且强度不够,确认密码非空,修改密码失败,弹窗提示"""self.login.loginFunc()menu = PrimaryMenu(self.driver)menu.modifyPwMenu() # 查找修改密码页面menu.modifyPw(menu.pwdList[1]) # 修改密码text = menu.errorDialog(menu.closeBtn)self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!') # 密码强度不满足时断言提示信息def test_modify_password_incorrect(self):"""旧密码不正确非空,新密码等于确认密码且满足条件,修改密码失败,弹窗提示"""self.login.loginFunc()menu = PrimaryMenu(self.driver)menu.modifyPwMenu() # 查找修改密码页面menu.modifyPw(menu.pwdList[2]) # 修改密码text = menu.errorDialog(menu.closeBtn)self.assertIn('旧密码输入错误!', text, '旧密码输入错误!') # 新密码和确认码不同时断言提示信息def test_modify_password_difference(self):"""旧密码非空,新密码不等于确认密码且新密码满足条件,修改密码失败,弹窗提示"""self.login.loginFunc()menu = PrimaryMenu(self.driver)menu.modifyPwMenu() # 查找修改密码页面menu.modifyPw(menu.pwdList[3]) # 修改密码text = menu.errorDialog(menu.closeBtn)self.assertIn('两次输入的新密码不同!', text, '两次输入的新密码不同!') # 新密码和确认码不同时断言提示信息def test_modify_password_all_blank(self):"""旧密码,新密码,确认密码任意为空,修改密码失败,弹窗提示"""self.login.loginFunc()menu = PrimaryMenu(self.driver)menu.modifyPwMenu() # 查找修改密码页面menu.modifyPw(menu.pwdList[4]) # 修改密码text = menu.errorDialog(menu.closeBtn)self.assertIn('该输入项的值不能为空!', text, ' 该输入项的值不能为空!') # 所有密码均为空时断言提示信息def test_modify_password(self):"""循环校验提示信息"""self.login.loginFunc()menu = PrimaryMenu(self.driver)menu.modifyPwMenu() # 查找修改密码页面error_list = []for list in range(len(menu.pwdList)):menu.modifyPw(menu.pwdList[list])if menu.isElementExist(menu.errMessage):text = menu.errorDialog(menu.closeBtn) # 这里只判断是否有提示框弹出,如有说明修改失败,没有或者其他提示框默认为修改成功error_list.append(text)else:self.assertTrue(menu.isElementExist(*menu.errMessage), 'error fram not exist, please open bug')self.assertEqual('密码长度至少 4 位!',error_list[0],'log infomation error!')self.assertEqual('密码强度不够,请重新输入密码!', error_list[1], 'log infomation error!')self.assertEqual('旧密码输入错误!', error_list[2], 'log infomation error!')self.assertEqual('两次输入的新密码不同!', error_list[3], 'log infomation error!')self.assertEqual('该输入项的值不能为空!', error_list[4], 'log infomation error!')def test_modifypw(self):"""循环测试修改密码功能"""self.login.loginFunc()# 登录menu = PrimaryMenu(self.driver)menu.modifyPwMenu()  # 查找修改密码页面for item in menu.pwdList:menu.modifyPw(item)if menu.isElementExist(menu.errMessage):  # 如果存在提示框 再断言提示信息是否正确if item[0] != '' and len(item[1]) < 4  and item[2] !='': # 新密码长度校验text = menu.errorDialog(menu.closeBtn)try:self.assertEqual('密码长度至少 4 位!',text,'the message incorrect!')except Exception:menu.saveScreenShot('fail_密码长度.png')raiseelif item[0] != '' and len(item[1]) >= 4 and item[2] !='': # 新密码强度校验 ['a', 'qwert', 'qwert'],lowercase, uppercase, number, other=strhandle(item[1])if lowercase > 0 and uppercase > 0 and number == 0 and other == 0: # 小写 大写text = menu.errorDialog(menu.closeBtn)self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')elif uppercase > 0 and other > 0 and number == 0 and lowercase == 0: # 大写 特殊字符text = menu.errorDialog(menu.closeBtn)self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')elif lowercase >0 and other > 0 and number == 0 and uppercase == 0: # 小写 特殊字符text = menu.errorDialog(menu.closeBtn)self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')elif lowercase == 0 and other == 0 and number > 0 and uppercase > 0:  # 大写 数字text = menu.errorDialog(menu.closeBtn)self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')elif lowercase > 0 and other == 0 and number > 0 and uppercase == 0:  # 小写 数字text = menu.errorDialog(menu.closeBtn)self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')elif lowercase > 0 and other == 0 and number == 0 and uppercase == 0:text = menu.errorDialog(menu.closeBtn)self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')elif lowercase == 0 and other > 0 and number == 0 and uppercase == 0:text = menu.errorDialog(menu.closeBtn)self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')elif lowercase == 0 and other == 0 and number > 0 and uppercase == 0:text = menu.errorDialog(menu.closeBtn)self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')elif lowercase == 0 and other == 0 and number == 0 and uppercase > 0:text = menu.errorDialog(menu.closeBtn)self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')elif item[0] != 'qwert1234!@#' and item[1] == item[2]:# >= 4lowercase, uppercase, number, other = strhandle(item[1])if (lowercase > 0 and uppercase > 0 and number > 0) or (lowercase > 0 and uppercase > 0 and other > 0) or (number > 0 and other > 0 and lowercase > 0) or (number > 0 and other > 0 and uppercase > 0):text = menu.errorDialog(menu.closeBtn)self.assertIn('旧密码输入错误!', text, '旧密码输入错误!')  # 新密码和确认码不同时断言提示信息elif item[0] == 'qwert1234!@#$' and item[1] != item[2]:# and item[1] >= 4:lowercase, uppercase, number, other = strhandle(item[1])if (lowercase > 0 and uppercase > 0 and number > 0) or (lowercase > 0 and uppercase > 0 and other > 0) or (number > 0 and other > 0 and lowercase > 0) or (number > 0 and other > 0 and uppercase > 0):text = menu.errorDialog(menu.closeBtn)self.assertIn('两次输入的新密码不同!', text, ' 两次输入的新密码不同!')else:print('test value incorrect! please check it')elif item[0] == '' or item[1] =='' or item[2] =='': # 输入项为空校验text = menu.errorDialog(menu.closeBtn)self.assertIn('该输入项的值不能为空!', text, ' 该输入项的值不能为空!')  # 所有密码均为空时断言提示信息else:self.assertTrue(menu.isElementExist(menu.errMessage), 'error fram not exist, please check the test value or file bug')if __name__=='__main__':pass

10.RunTc.py(执行测试用例)

 #! user/bin/python'''Code description:auto run test caseCreate time:Developer:'''import unittestimport timefrom BeautifulReport import BeautifulReportfrom retail.config.conf import *from retail.test_case.models.testreport import testreport# TODO : will be use jenkins continuous intergration teachnology manage the auto projectif __name__ == '__main__':# currTime = time.strftime('%Y-%m-%d %H_%M_%S')# filename = currTime + '.html'# # 第一种测试报告# test_suite = unittest.defaultTestLoader.discover(tcPath, pattern='*Tc.py')# result = BeautifulReport(test_suite)# result.report(filename= filename, description='test report', log_path=reportPath)# # 第二种测试报告runner, fp, fileName = testreport()test_suite = unittest.defaultTestLoader.discover(tcPath, pattern='LoginTc.py')runner.run(test_suite)fp.close()

11.备注

from BeautifulReport import BeautifulReport 这个报告需要自己网上找一下(很多类似的测试报告源码,不一定非使用本案例中的报告模板)

12.输出结果展示

1.创建规则失败时截图

2.登录成功截图

3.用例执行日志

4.测试报告

selenium UI自动化实战相关推荐

  1. python ui自动化配置文件,python UI自动化实战记录八:添加配置

    添加配置文件写入测试地址等,当环境切换时只需修改配置文件即可. 1 在项目目录下添加文件 config.ini 写入: [Domain] domain = http://test.domain.cn ...

  2. python selenium UI自动化解决验证码的4种方法

    测试环境 windows7+ firefox50+ geckodriver # firefox浏览器驱动 python3 selenium3 selenium UI自动化解决验证码的4种方法:去掉验证 ...

  3. Selenium UI 自动化获取接口数据

    Selenium UI 自动化获取接口数据 1.前端向接口的传参: 2.捕获到接口返回的内容后,判断前端是否有按照接口返回的内容进行展示 针对第一点,我上家公司是做旅游的,旅客预订完人数.房间数后前端 ...

  4. Python+Selenium UI自动化 - 调用JS代码

    当webdriver遇到无法完成的操作时候,这个时候可以使用javascript来完成,webdriver提供了execute_script()接口来调用js代码. 执行js有两种场景: 1.在页面上 ...

  5. Python Selenium UI自动化:滚动条滑动

    文章目录 问题 滑动至固定位置 Window 对象方法 - scrollTo js&python:滑动至固定位置 滑动至元素 元素对象方法 js&python:滑动至元素 问题 在UI ...

  6. Python Selenium UI自动化 ⽂件上传

      UI自动化进行文件上传,其实本质就是将所需上传的文件路径,传递给后端服务即可,至于读取文件的过程,其实开发人员已经在后端服务中完成了.所以我们要做的就是:拿到文件路径 -> 传出去.那么这里 ...

  7. Selenium UI自动化验证码:识别+输入

    思路:使用UI+接口的方式来查找验证码图片和获取验证码元素进行参数输入(用截图方式)(非图片类型验证码无法实现) 我们以访问当当网的注册界面来演示 1.通过selenium定位查找验证码并截图保留 1 ...

  8. python数据接口获取数据_python UI自动化实战记录二:请求接口数据并提取数据

    该部分记录如何获取预期结果-接口响应数据,分成两步: 1 获取数据源接口数据 2 提取后续页面对比中要用到的数据 并且为了便于后续调用,将接口相关的都封装到ProjectApi类中. 新建python ...

  9. Python+Selenium UI自动化 - alert/confirm/prompt窗口处理方法

    WebDriver中处理原生JS的alert.confirm以及prompt非常方便,三种弹出窗口均无法直接通过页面元素定位,不关闭窗口无法在页面上做其他操作 语法:         text:返回a ...

最新文章

  1. MPB:林科院袁志林组-​内生镰刀菌基因组染色体级别组装和注释
  2. 82. Leetcode 23. 合并K个升序链表 (排序)
  3. 绘制HTML5的Logo
  4. c语言期末作业自己设计个小程序,帮看一个小程序吧,c语言期末考…求求各位大神了...
  5. eclipse配置本地连接 hadoop
  6. #UnityTips# 2017.11.14
  7. ArcGIS10.2不能打开10.6版本创建的镶嵌数据集
  8. 【语音识别】基于matlab GUI声纹识别(带面板)【含Matlab源码 537期】
  9. css实训内容,实训五DivCSS布局基本.doc
  10. 腾讯翻译君在线翻译怎么翻译整个文件_腾讯文档:在线多人协作文档工具
  11. word表格删除空白行java_Java批量删除Word中的空白段落
  12. Hive-获取本月的第一天,本月的最后一天,本月的天数
  13. 横版过关游戏开发-游戏流程
  14. 观察 | 经济学诺奖的启示:金融科技的核心任务是什么?
  15. 带有图片的Excel信息导入
  16. 慕课嵌入式开发及应用(第二章.嵌入式硬件构件与底层驱动构件基本规范)
  17. 16位浮点数(FP16)
  18. 如何在服务器上部署静态网页,让所有人都能访看到?
  19. 将Vue通过nginx部署到阿里云服务器上
  20. 基于win10 和python3.6激活虚拟环境成功!

热门文章

  1. 测试人员如何突破自我的瓶颈?
  2. Python Web开发(六):前后端分离的架构
  3. 微信小程序引用Echarts绘图显示模糊解决办法
  4. 有哪些网站用爬虫爬取能得到很有价值的数据
  5. 阿里云平台产品功能实战详解
  6. HTML学生个人网站作业设计:电影网站设计——迪士尼影视电影(6页) HTML+CSS+JavaScript 简单DIV布局个人介绍网页模板代码 DW学生个人网站制作成品下载
  7. springboot项目报错:ERROR 9112 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] 的解决办法
  8. MYsql的enum字段报错row,SQLSTATE[01000]: Warning: 1265 Data truncated for column at row 1错误代码解决方法
  9. 新版火狐 拖 功能_Firefox 28的新功能
  10. 【MAPBOX基础功能】26、mapbox地图基础工具 -定位到指定的位置