自我介绍:
话不要多,也不要少,过多会出错,过少不尊重。
模板一: (1)面试官早上好(下午好),我叫XXXundefined(2)我今年xx岁,来自XX地方,毕业于XX学校,具有XX年的软件测试经验undefined(3)我毕业的第一家公司叫XX,项目名称XX 第二家公司交XX,项目名称XX ... (4)在这几年实际用到XX技能 (5)我大致介绍到这边,面试官您看您还有什么要问的吗 模板一详解: 第(1)步,算是给自己的一个暖场的开始,也算给面试官一个相应的尊重 第(2)步,多大,什么地方,什么学校,多少年的经验,说出来面试官会根据地区年龄以及经验进行判断是否符合公司一些需求,另外学历有的公司是硬性条件,若是看到面试官不是很感兴趣的情况,那下面的回答你可以搪塞一下,尽快离开去下一场面试 第(3)步,告诉面试官什么公司什么项目,面试官会自己查看简历对比具体 第(4)步,重之中重,这边的技能熟练熟悉的在前,弱项在后.或者话术说一下,这几年工作当中用到了什么什么技能.面试官会想到有的技能你会用,但是不常用,这也符合工作状态。这边用到的技能会让面试官自己内心进行评估,方便后面针对性的问问题,所以自己的弱项少说。 第(5)步,自己的介绍结束,把反问的权利抛给面试官,等待面试官根据项目或技能进行提问 通过以上的自我介绍,面试官也会看你个人的沟通能力以及语言是否表达清晰,以及你一些其他的品质。 另外简历不要使用市场上常有的模板(比如培训班出来的),别搞的花里胡哨的 模板一是小编自己经常面试的话术,以后会统计一些其他高级测试自我介绍的话术。
功能测试:
- 请写出你知道的黑盒测试方法
答: 边界值 、等价类 、错误推测法 、场景法 、因果图法、判定表组成法、正交实验设计
- 测试结束的标准是什么
答: 测试用例已经全部覆盖,缺陷全部覆盖,其他指标达到发版标准
- 请你简述一下三次握手和四次挥手
答: 按照你大概的理解意思说给面试官就行了. 一、建立TCP连接:三次握手协议 客户端:我要对你讲话,你能听到吗; 服务端:我能听到;而且我也要对你讲话,你能听到吗; 客户端:我也能听到。 ……. 互相开始通话 ……..undefined二:关闭TCP连接:四次握手协议 客户端:我说完了,我要闭嘴了; 服务端:我收到请求,我要闭耳朵了; (客户端收到这个确认,于是安心地闭嘴了。) ……. 服务端还没倾诉完自己的故事,于是继续唠唠叨叨向客户端说了半天,直到说完为止 ……. 服务端:我说完了,我也要闭嘴了; 客户端:我收到请求,我要闭耳朵了;(事实上,客户端为了保证这个确认包成功送达,等待了两个最大报文生命周期后,才闭上耳朵。) (服务端收到这个确认,于是安心地闭嘴了。)
- 测试计划或者测试方案你们公司谁写
答: 一般由测试经理写,若没有测试经理则由组长写
- 你平时用的什么测试方法比较多
答: 因公司而异,一般用到的测试方法有边界值 、等价类 、错误推测法 、场景法
- 测试计划都包含了什么,你能简述一些重点吗
答: (1)测试目标:对测试目标进行简要的描述。 (2)测试概要:摘要说明所需测试的软件、名词解释、以及提及所参考的相关文档。 (3) 测试范围:测试计划所包含的测试软件需测试的范围和优先级,哪些需要重点测试、哪些无需测试或无法测试或推迟测试。 (4)重点事项:列出需要测试的软件的所有的主要功能和测试重点,这部分应该能和测试案例设计相对应和互相检查。 (5) 质量目标:制定测试软件的产品质量目标和软件测试目标。 (6) 资源需求:进行测试所需要的软硬件、测试工具、必要的技术资源、培训、文档等。 (7)人员组织:需要多少人进行测试,各自的角色和责任,他们是否需要进行相关的学习和培训,什么时候他们需要开始,并将持续多长时间。 (8) 测试策略:制定测试整体策略、所使用的测试技术和方法。 (9) 发布提交:在按照测试计划进行测试发布后需要交付的软件产品、测试案例、测试数据及相关文档。 (10)测试进度和任务人员安排:将测试的计划合理的分配到不同的测试人员,并注意先后顺序.如果开发的Release不确定,可以给出测试的时间段.对于长期大型的测试计划,可以使用里程碑来表示进度的变化。 (11) 测试开始/完成/延迟/继续的标准:制定测试开始和完成的标准;某些时候,测试计划会因某种原因(过多阻塞性的Bug)而导致延迟,问题解决后测试继续。 (12) 风险分析:需要考虑测试计划中可能的风险和解决方法。
一般的测试计划目录,仅供参考,以公司实际情况为准
- 验收测试都包含了什么方面
答: 验收测试在功能测试和系统测试之后进行,所以验收测试进行的前提条件是系统或软件产品已通过了系统测试,而且要求软件系统必须在真实的环境下运行。 a、测试内容 验收测试用来验证系统是否达到了用户需求规格说明书(可能包括项目或产品验收准则)中的要求,测试希望尽可能地发现软件中存留的缺陷,从而为软件进一步改善提供帮助,并保证系统或软件产品最终被用户接受。其主要包括易用性测试、兼容性测试、安装测试、文档(如用户手册、操作手册等)测试等几个方面的内容。 b、测试步骤 (1)测试计划在需求分析阶段建立,主要了解软件功能和性能要求、软硬件环境要求等,并特别要了解软件的质量要求和验收要求。根据软件需求和验收要求编制测试计划,制定需测试的测试项,制定测试策略及验收通过准则,并经过客户参与的计划评审。 (2)建立测试环境。根据验收测试计划、项目或产品验收准则完成测试用例的设计,并经过评审。 (3)准备测试数据、执行测试用例,记录测试结果。 (4)分析测试结果。根据验收通过准则分析测试结果,作出验收是否通过及测试评价。通常会有四种情况: ● 测试项目通过。 ● 测试项目没有通过,并且不存在变通方法,需要作很大的修改。 ● 测试项目没有通过,但存在变通方法,在维护后期或下一个版本改进。 ● 测试项目无法评估或者无法给出完整的评估。此时必须给出原因。如果是因为该测试项目没有说清楚,应该修改测试计划。 (5)提交测试报告。根据产品设计说明书、详细设计说明书、验收测试结果和发现和错误讯息,评价系统的设计与实现,最终通过验收测试报告和缺陷报告等体现出来。 c、验收测试完成标准 ● 完全执行了验收测试计划中的每个测试用例。 ● 在验收测试中发现的错误已经得到修改并且通过了测试。 ● 完成软件验收测试报告。 d、注意事项 ● 必须编写正式的、单独的验收测试计划。 ● 验收测试必须在实际的用户运行环境中运行。 ● 由用户和测试部门共同执行比较好。如果是公司自我开发的产品,由测试人员和产品设计部门、市场部门等共同进行,可能还包括技术支持、产品培训部门。
- 软件缺陷等级是怎么划分的
答: (1)致命错误:造成系统崩溃、死机、死循环,导致数据库数据丢失,与数据库连接错误,主要功能丧失,基本模块缺失等问题。 (2)严重错误:系统主要功能部分丧失,数据库保存调用错误,用户数据丢失,以及功能菜单不能使用但是不影响其他功能的测试。功能设计与需求严重不符,模块无法启动或调用,程序重启,自动退出,关联程序间调用冲突,安全问题、稳定性等。 (3)一般错误:功能没有完全实现但不影响使用,功能菜单存在缺陷但不影响系统稳定性。 (4)建议问题:界面,性能缺陷,建议类问题,不影响操作功能的执行,可以优化性能的方案等。如:错别字、界面格式不规范,页面显示重叠、不该显示的要隐藏,描述不清楚,提示语丢失,文字排列不整齐,光标位置不正确,用户体验感受不好,可以优化性能的方案等。
- 请简述一下软件测试中的白盒与黑盒、静态测试、动态测试、α测试、β测试
答: (1)白盒测试根据软件内部的逻辑结构分析来进行测试,是基于代码的测试,测试人员通过阅读程序代码或者通过使用开发工具中的单步调试来判断软件的质量,一般黑盒测试由项目经理在程序员开发中来实现。 (2)黑盒测试一般用来确认软件功能的正确性和可操作性,目的是检测软件的各个功能是否能得以实现,把被测试的程序当作一个黑盒,不考虑其内部结构,在知道该程序的输入和输出之间的关系或程序功能的情况下,依靠软件规格说明书来确定测试用例和推断测试结果的正确性。 (3)静态测试是不运行程序本身而寻找程序代码中可能存在的错误或评估程序代码的过程。undefined(4)动态测试是实际运行被测程序,输入相应的测试实例,检查运行结果与预期结果的差异,判定执行结果是否符合要求,从而检验程序的正确性、可靠性和有效性,并分析系统运行效率和健壮性等性能。 (5)α测试是由一个用户在开发环境下进行的测试,也可以是公司内部的用户在模拟实际操作环境下进行的受控测试,Alpha测试不能由程序员或测试员完成。 (6)β测试是软件的多个用户在一个或多个用户的实际使用环境下进行的测试。开发者通常不在测试现场,Beta测试不能由程序员或测试员完成。
- 什么是回归测试,回归测试分为两类,你知道是哪两类吗
答: 分为两类:用例回归和错误回归;用例回归是过一段时间以后再回头对以前使用过的用例在重新进行测试,看看会重新发现问题。错误回归,就是在新版本中,对以前版本中出现并修复的缺陷进行再次验证,并以缺陷为核心,对相关修改的部分进行测试的方法。
- 测试报告主要内容有什么,说个大概就行
答: 一般包含:概述、测试过程、功能实现清单、测试统计、测试总结及测试风险。
- 你工具中用过哪些bug管理工具,说个一二三
答: 大部分的公司都是使用禅道、JIRA,个别会使用QC、ONES project
- 测试用例的基本要素是什么
答: 用例编号、测试模块、用例标题、测试级别、预置条件、测试步骤、预期结果、实际结果。 正规的大型公司用例标准为: 接口测试、功能测试、性能测试、兼容性测试四个用例,在一般的要素情况下还要增加回归测试、兼容性测试(手机型号、浏览器)、测试截图、负责测试模块的对应测试人员、数据埋点抓取手机型号、回归测试截图等
- 软件测试流程是什么,大概说一下
答: 需求分析阶段、测试计划阶段、编写用例阶段、用例执行阶段、测试报告阶段(因公司而异)
- TCP与UDP的区别
答: (1)连接方面区别 TCP面向连接(如打电话要先拨号建立连接)。 UDP是无连接的,即发送数据之前不需要建立连接。 (2)安全方面的区别 TCP提供可靠的服务,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达。 UDP尽最大努力交付,即不保证可靠交付。
(3)传输效率的区别 TCP传输效率相对较低。 UDP传输效率高,适用于对高速传输和实时性有较高的通信或广播通信。 (4)连接对象数量的区别 TCP连接只能是点到点、一对一的。 UDP支持一对一,一对多,多对一和多对多的交互通信。
- 烟雾测试与理智测试分别是什么
答: 烟雾测试是在软件构建之后执行的一种软件测试,以确定程序的关键功能正常工作。它在“之前”执行,在软件构建上执行任何详细的功能或回归测试。目的是拒绝严重破坏的应用程序,以便QA团队不会浪费时间安装和测试软件应用程序。也称为冒烟测试。 在Smoke Testing中,所选的测试用例涵盖了系统中最重要的功能或组件。目标不是进行详尽的测试,而是要验证系统的关键功能是否正常工作。 例如,典型的冒烟测试是 - 验证应用程序是否成功启动,检查GUI是否响应......等等。 理智测试是在接收软件构建后执行的一种软件测试,在代码或功能方面进行微小更改,以确定错误已得到修复,并且由于这些更改不会引入其他问题。目标是确定所提议的功能大致按预期工作。如果完整性测试失败,则会拒绝构建以节省更严格测试所涉及的时间和成本。 目标是“不”彻底验证新功能,而是确定开发人员在生成软件时应用了一些合理性(健全性)。例如,如果您的科学计算器给出2 2 = 5的结果!然后,没有必要测试像sin 30 cos 50这样的高级功能。
烟雾测试 | 理智测试 |
---|---|
执行烟雾测试以确定程序的关键功能正常工作 | 进行完整性测试以检查新功能/错误是否已修复 |
此测试的目的是验证系统的“稳定性”,以便进行更严格的测试 | 测试的目的是验证系统的“合理性”,以便进行更严格的测试 |
此测试由开发人员或测试人员执行 | 完整性测试通常由测试人员执行 |
烟雾测试通常记录在案或编写脚本 | 通常不会记录完整性测试并且没有脚本 |
烟雾测试是验收测试的一个子集 | 理智测试是回归测试的一个子集 |
烟雾测试从头到尾练习整个系统 | 完整性测试仅执行整个系统的特定组件 |
烟雾测试就像一般健康检查 | 健康测试就像专业的健康检查一样 |
接口测试:
- 你用过什么接口测试工具?具体有哪些
答: postman、RESTClient、jmeter、loadrunner、SoapUI(常用postman与Jmeter)
- 平时你是怎么测试接口
答: 主要从6个维度去考虑接口测试,入参、接口逻辑、出参、接口兼容、超时处理、接口安全(Https 4大机制【sign签名机制】、【时间戳超时机制】、【Token授权机制】、【验证码机制】)
- 在没有接口文档的情况下你是怎么开展接口测试
答: 明确自己想要测试接口测试、当前接口需要的请求头参数、当前接口需要提交的参数以及运行接口后台返回的数据如何判断 (1).使用抓包工具获取接口以及相关数据 (2)根据抓取的数据填入Postman中 (3)header、body数据信息填入postman(请求头可以咨询开发) (4)根据抓包工具获取的返回数据信息与postman执行做比较,查看接口返回数据是否正确 其他的可以按照接口测试思维进行测试。
- 当一个接口出现异常,你是怎么分析怎么定位
答: (1)使用fiddler抓包工具,或者浏览器中常用的F12键,APP的话可以使用fiddler设置代理(同一网络下),去查看请求报文与返回报文 (2)putty或Xshell连接服务器,查看日志文件(tail -f 日志文件名)
- 如何分析一个BUG是前端还是后端
答: 前端BUG特点: 1.界面 2.布局 3.兼容性 后端BUG特点: 1.业务逻辑 2. 性能 3.数据 4.安全性 定位前后端BUG: (1)经验法: 测试同一类型的项目多了,自然会对功能的实现过程有了解,也就会迅速的区分BUG;打个比方:网页上的某个图片分辨率不对,图片一般是根据某个地方去服务器获取图片,数据库一般只会保存图片地址,如果图片能够正常显示,说明后端的基本功能能够满足需求;分辨率有问题,则是前端显示的过程出错。 (2)查日志: 当我们发现一个BUG并不确定是否属于前端或后端时,我们可以通过查看后端服务器的日志,当我们复现BUG时,直接查看日志有无相关报错信息; 若是没有日志输出,有可能这个功能与后端并无交互,也就不存在后端的问题;反之,若是有日志输出,可以进一步查看错误日志信息,后端出错的概率性很大。 (3)查接口:使用抓包工具或浏览器F12查看请求报文,对着接口文档,查看请求报文有没有问题,若是有问题,则提交给前端;若是请求报文没有问题,那么就看返回报文,返回报文出错,就是后端开发的问题。 若是请求数据与接口文档不一致,则前端问题 若是请求数据与接口文档一致,响应数据与接口文档一致,则是前端的问题 若是请求数据与接口文档一致,响应数据与接口文档不一致,则是后端的问题
- 弱网测试你是怎么模拟的呢
答: 弱网环境测试主要依赖于弱网环境的模拟。环境搭建方式一般有两种:软件方式和硬件方式。 (1)SIM卡的网络切换 a.手机—设置—移动网络设置—网络类型选择 (2)弱网实际场景有 地铁、电梯、楼梯间、地下室、卫生间或含有金属很多的房间 (3)硬件方式: a.无线网卡 360免费WIFI软件 a1.电脑插入无线网卡 a2.打开360免费WIFI软件 a3.手机连接360免费WIFI网络 a4.电脑上修改360免费WIFI的上行速度与下行速度 b.路由器修改上行与下行速度 b1.路由器通过网线要与电脑连接在同一网络下 b2.手机连接路由器网络 b3.进入路由器管理页面,进入左侧模块网络设置中,修改网络速度 (4)软件方式: a.iphone手机自带Network Link Conditioner a1.开启开发者模式,iphone手机联系Xcode或PP助手打开实时桌面 a2.进入开发者模式,设置—开发者模式—Network Link Conditioner a3.可以选择已经设置好的网络条件,也可自定义 配置参数: In Bandwidth:下行带宽,即下行网络速度 In packet loss:下行丢包率 In delay:下行延迟,单位ms Out bandwidth :上行带宽 Out packet loss :上行丢包率 Out delay :上行延迟 DNS delay DNS:解析延迟 Protocol :支持Any,IPV4、IPV6 Interface :支持Any,WI-Fi,cellular(蜂窝网)
b.**fiddler**中设置上行或下行速度 b1.进入fiddler脚本Customize Rules b2.在OnBeforeRequest中修改上行和下行速度
c.**Charles**中设置上行或下行速度 c1.Proxy—Throttle Settings c2.配置需要测试的参数 配置参数: Bandwidth:带宽,即上行、下行数据传输速度 Utilisation :带宽可用率,大部分modern是100% Round-trip latency :第一个请求的时延,单位是ms MTU :最大传输单元,即TCP包的最大size,可以更真实模拟TCP 层,每次传输的分包情况 Releability :指连接的可靠性。这里指的是10kb的可靠率。用于模拟网络不稳定 Stability :连接稳定性,也会影响带宽可用性。用于模拟移动网络,移动网络连接一般不可靠 Only for selected hosts:可以指定域名拦截
(具体网络设置参考)
- 你用过的抓包工具都有哪些
答: fiddler: 客户端和服务端的http代理,客户端所有的请求都要先经过fiddler,到响应的服务端,然后端返回的所有数据也都要经过fiddler。 Charles: 和fiddler差不多,请求接口和返回数据的显示方式不一样,Charles是树状结构比较清晰,fiddler是按照时间倒叙排的。 Firebug: Firebug抓包工具是浏览器firefox浏览器自带插件,支持很多种浏览器,直接按f12,就可以打开,用起来比较方便。 httpwatch: 是强大的网页数据分析工具,安装简单,不需要设置代理和证书,但只能看不能修改,,集成在Internet Explorer工具栏 Wireshark: 可以捕捉网络中的数据,并为用户提供关于网络和上层协议的各种信息。但是如果只是抓取http和https的话,还是用fiddler和Charles比较简洁一点。 SmartSniff :是一款方便小巧的 TCP/IP 数据包捕获软件,网络监视实用程序。
- 当依赖第三方数据接口时,你是如何进行测试的
答: mock 当前端开发在开发页面的时候,需要服务端提供API接口 此时服务端没开发完成,或者说没搭建测试环境,这个时候前端开发会自己mock一个api服务端,自己给自己提供调用接口的返回数据。后续见面试题12
- 什么是接口测试?重点是什么?意义是什么
答: 通常所说的接口指的都是 API 软件接口,即
Application Programming Interface
,应用程序接口,简称 API。 能够把某个硬件或软件模块封装起来供外部使用,都可以称之为接口,可以存在于所有的软硬件设备之间。比如插座,供外部插头插入,也可以称为接口。 意义是: (1)更早的发现问题 (2)缩短产品周期 (3)发现更底层的问题
- get请求与post请求区别是什么
答: 我们通俗的先理解一下,TCP就好比汽车,我们用TCP来运输数据,它很可靠,从来不会发生丢件少件的现象。但当路上开着的全是看起来一模一样的汽车,那这个世界看起来是一团混乱,送急件的汽车可能被前面满载货物的汽车拦堵在路上,整个交通系统一定会瘫痪。为了避免这种情况发生,交通规则HTTP诞生了。HTTP给汽车运输设定了好几个服务类别,有GET, POST, PUT, DELETE等。HTTP规定,当执行GET请求的时候,要给汽车贴上GET的标签(设置method为GET),而且要求把传送的数据放在车顶上(url中)以方便记录。如果是POST请求,就要在车上贴上POST的标签,并把货物放在车厢里。当然,你也可以在GET请求的时候往车厢内偷偷藏点货物,但是这是很不光彩;也可以在POST的时候在车顶上也放一些数据,让人觉得傻乎乎的。HTTP只是个行为准则,而TCP才是GET和POST怎么实现的基本。 还有另一个重要的角色:运输公司。不同的浏览器(发起http请求)和服务器(接受http请求)就是不同的运输公司。 虽然理论上,你可以在车顶上无限的堆货物(url中无限加参数)。但是运输公司可不傻,装货和卸货也是有很大成本的,他们会限制单次运输量来控制风险,数据量太大对浏览器和服务器都是很大负担。业界不成文的规定是,(大多数)浏览器通常都会限制url长度在2K个字节,而(大多数)服务器最多处理64K大小的url。超过的部分,恕不处理。如果你用GET请求时,在request body偷偷藏了数据,不同服务器的处理方式也是不同的,有些服务器会帮你卸货,读出数据,有些服务器直接忽略,所以,虽然GET可以带request body,也不能保证一定能被接收到哦。 好了,现在你知道,GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。 GET和POST还有一个重大区别,简单的说: GET产生一个TCP数据包;POST产生两个TCP数据包。 对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。 也就是说,GET只需要汽车跑一趟就把货送到了,而POST得跑两趟,第一趟,先去和服务器打个招呼“嗨,我等下要送一批货来,你们打开门迎接我”,然后再回头把货送过去。 因为POST需要两步,时间上消耗的要多一点,看起来GET比POST更有效。因此Yahoo团队有推荐用GET替换POST来优化网站性能。但这是一个坑!跳入需谨慎。为什么? 1. GET与POST都有自己的语义,不能随便混用。 2. 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。 3. 并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。 一般我们回答如下,基本上面试官不会再次刁难. Get:提交信息都会在地址栏中看到,不安全,提交的数据会少. Post:所有提交信息都会放在http请求的请求体中,是看不到的,很安全,但是是以表单形式提交,数据会较大. 数据查询用get,增删改的话用post
- Http接口请求参数类型有哪些
答: (1)区别于http请求的类型 get、post、put、delete (2)类型: a.查询字符串参数(Query String Parameters参数) 一般用于GET请求,会以url string的形式进行传递 b.请求体参数(Request Body) 一般用于POST请求,可以使用Content-Type来指定不同参数类型
- 如何把上一个接口获取的响应数据传递到下一个接口入参
答: 看面试官问以下哪一种. (1)jmeter a.首先新建一个http请求,同时添加好接口相应的请求参数 b.查看http请求结果 c.使用正则表达式提取器或json提取器来提取返回你想要的接口参数(将提取结果赋值给一个变量) d.再次新建一个http请求,在请求参数里面添加刚刚提取到的返回参数(添加刚刚设置好的变量) (2)postman a.设置接口全局变量(我们拿返回值里的token来说),第一步执行token接口,并把接口返回值里面的token值赋值给全局变量。赋值操作写在postman中的Tests中,内容如下: var jsonData = JSON.parse(responseBody); pm.globals.set("token", jsonData.token); b.获取刚刚设置的全局变量的值,作为入参参数。获取实现是写到Pre-request Scripts 里面实现的,内容如下: pm.globals.get("token"); 同时,要设置接口的 Params,新增一个 Key,Key 的名称为参数的名称,Key 的内容为全局变量名,比如{{token}}。 c.顺序执行接口调用 需要先调用token接口,然后执行第二步b的操作 (3)java 把不同的接口封装成不同的函数或方法,需要的数据return出来,设置一个变量a, 让a去获取这个数据, 后面的接口使用时直接传a就可以了 (这算是接口自动化的问题了)
- 接口测试用例要点是有哪些
答: (1)通过性验证 (2)参数组合 (3)接口安全 (4)异常验证 (5)业务逻辑设计 附送接口用例模板:
- 接口测试流程
答: (1)需求评审 (2)场景设计 (3)数据准备 (4)用例设计 a.功能: 功能是否正常,供能否按照接口文档实现 b.业务逻辑 : 是否有依赖业务 c.异常 c1.参数异常: 关键字参数,参数为空、多、少参数,错误参数 c2.数据异常: 关键字数据,数据未空、长、短参数,错误数据 d.安全 d1.Cookie: 删掉cookie,再次执行接口,看服务器是否返回数据 d2.Header: 删掉header,再次执行接口 d3.唯一识别码 (5)执行
- Cookie与Session的区别
答: 不要混淆 session 和 session 实现。 本来 session 是一个抽象概念,开发者为了实现中断和继续等操作,将 user agent 和 server 之间一对一的交互,抽象为“会话”,进而衍生出“会话状态”,也就是 session 的概念。 而 cookie 是一个实际存在的东西,http 协议中定义在 header 中的字段。可以认为是 session 的一种后端无状态实现。 而我们今天常说的 “session”,是为了绕开 cookie 的各种限制,通常借助 cookie 本身和后端存储实现的,一种更高级的会话状态实现。 所以 cookie 和 session,你可以认为是同一层次的概念,也可以认为是不同层次的概念。具体到实现,session 因为 session id 的存在,通常要借助 cookie 实现,但这并非必要,只能说是通用性较好的一种实现方案。 以下为另一种通俗易懂的方式: (1)session 在服务器端,cookie 在客户端(浏览器) (2)session 默认被存在在服务器的一个文件里(不是内存) (3)session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id) (4)session 可以放在 文件、数据库、或内存中都可以。 (5)用户验证这种场合一般会用 session 因此,维持一个会话的核心就是客户端的唯一标识,即 session id
- 请求接口常见的状态返回码有哪些,具体是什么含义
答: 不要啪啪啪的记一大堆状态码,测试需要知道那么详细吗?不需要知道那么多.200成功就不说了,300 可能是重定向了,404是前端的错,可能是路径错误等,500以上是服务端或者服务器的错误。
- 接口(API)文档包含哪些部分
答: 一个规范的接口文档,包含以下信息: (1)基本信息(接口名称、请求方法、请求路径、接口字段描述) (2)请求参数(请求头、请求体) (3)返回数据(不同情况的响应状态码、响应数据)
- 现在给你一个localhost:8080接口,name(账号test)、password(123456),你怎么进行测试
答: localhost是开发本地环境,没法测试,这摆明了挖坑。我就见过我公司的一个测试跑过来问我,localhost接口怎么压测,瞬间不想搭理他,不知道是怎么招进来的。如果开发给你localhost接口,麻烦请您怼回去,让他们自己调试。或者让他给测试环境接口,不要给测试丢脸。
- 你平时在工作中使用Fiddler都做了哪些工作
答: 上文都有解释,这边不做详细描述,若有缺少,请自行百度了解 (1)定位前后端 bug (2)篡改数据(断点篡改请求数据、断点篡改响应数据、AutoResponder修改响应) (3)弱网模拟测试 (4)获取前端性能数据
- 什么是关联,在Jmeter中如何实现关联
答: 关联有以下三种方式 (1)正则表达式 设置变量为全局变量,赋值为一个a,关联的请求下右键点击添加-后置处理器-正则表达式提取器,在请求中添加该变量a即可。 (2)边界提取器 (3)Json Extractor提取器 关联请求右键点击添加—后置处理器—JSON Extractor,跟添加变量a类似。
- 能列举一下API测试中常用的一下协议吗
答: (1)基于http协议的接口 http协议又叫超文本传输协议,主要用于浏览器与服务器之间的交互数据,这种接口常用get与post两个请求方法,基于这种协议开发的接口目前是市面上最多的!一般使用的工具为postman与Jmeter。 (2)基于WebService协议的接口 WebService是基于Soap的通信协议,请求和返回报文一般都为xml格式,一般使用的测试工具有SoapUI。 (3)基于Dubbo协议的接口 a.Dubbo缺省协议,采用单一长连接和NIO异步通讯,适合小数据量大并发的服务调用,以及服务消费者机器数大于服务提供者机器数的情况 b.不适合传送大数据量的服务,比如传文件、传视频等,除非请求量很低。 c.基于Dubbo协议的接口一般也是使用SoapUI工具进行测试。
- API与Web服务之间的区别
答: (1) a.所有Web服务都是API,但并非所有的API都是Web Service b.所有的Web服务都需要通过Web(http)公开 c.Web服务只有三种使用方式: Soap、Rest、Xml-Rpc进行通信 d.Web Service 可以被http (get、post)进行替代 (2)
- Soap与Rest的区别是什么
答: SOAP(Simple Object Access Protocol - 简单对象访问协议)定义了一种强类型的消息传递框架,该框架高度依赖XML和schemas。 REST(Representation State Transfer - 表示状态转移)是一种架构样式风格,它利用了当下被广泛采用的技术(特别是HTTP),本身却不创建任何新的标准。REST可以将数据结构序列化为XML,YAML或任何其他机器可读格式,但通常首选JSON。区别如下: (1)底层协议 SOAP本身便是基于HTTP而发展的协议。 REST与HTTP几乎一样,REST规范没有强制的要求。 (2)数据格式 SOAP只依靠XML来提供消息传递服务。在某些情况下,消息传递服务可能变得极其复杂。例如,通过javascript访问Web服务, REST可以语言自由的选择易解析的数据格式。例如,CSV、JSON、XML、YAML等等。 (3)有状态 SOAP Web服务是无状态的,但是可以通过修改服务器上的代码轻松变为有状态的。 RESTful Web服务是完全无状态的。对话状态的管理完全由客户端进行控制。服务端不保留任何状态信息。也就是我们通常所说的,客户端的每次请求必须携带所有可能用到的信息。 (4)HTTP的方法使用 SOAP可以对HTTP协议进行绑定。当绑定HTTP协议时,所有的SOAP请求都通过HTTP POST发送。 REST主要使用HTTP协议。通过HTTP GET、POST、PUT、DELETE和PATCH方法进行CRUD操作。 (5)缓存 SOAP可以使用HTTP传输机制,但是都转换为HTTP POST方法。而POST是非幂等的,所以无法在HTTP级别进行缓存。因此SOAP的响应需要通过 Response Caching Optimization Module给的信息进行缓存。 REST可以发送HTTP GET请求,GET是幂等的,因此REST可以使用HTTP提供的缓存机制,使响应数据可以标记为可缓存或不可缓存。 (6)安全 SOAP通过WS-SECURITY对安全进行了很好的标准化。 REST主要使用HTTP协议,HTTP本身是非常不安全的,但通过TLS它可以支持基础的身份认证和通信加密,即HTTPS。此外,在服务器上还可以进一步实施安全措施。 (7)异步处理 创建和更新通常非常消耗资源,有时会需要异步请求处理。 SOAP 1.2提供了额外的标准,可保证应用的可靠性和安全性。例如:WSRM – WS-Reliable Messaging。 REST我们通常返回HTTP状态码202(Accepted)和队列位置,该位置上,任务的完成状态将会被定期更新(当然,我们也可以将完成状态信息存在数据库中,并定期新增状态信息,供客户端查询)。 REST更易于开发,因为它利用了已经存在的Web,并且自由度受到限制(做出的选择更少,因此更简单)。SOAP提供了多种选择,并且开发难度也稍大一些,但是提供了更多的选择。
- API测试具有什么优势
答: (1)接口比较稳定,维护成本最低 (2)与UI相比,稳定、执行速度快,反馈迅速 (3)比单元测试更贴近业务场景 (4)接口测试可以做到更多的覆盖场景 (5)接口测试可以更快的发现服务端问题
- 列出你在以往公司中常用的API文档模板工具是什么
答: 适当的了解一下。 (1)MinDoc: 是一款针对IT团队开发的简单好用的文档管理系统。MinDoc 的前身是 SmartWiki 文档系统。SmartWiki 是基于 PHP 框架 laravel 开发的一款文档管理系统。因 PHP 的部署对普通用户来说太复杂,所以改用 Golang 开发。可以方便用户部署和实用,同时增加Markdown和HTML两种编辑器。其功能和界面源于 kancloud 。 (2)RAML: 官方提供 atom 插件,支持语法智能提示及校验,编写快速简单。 (3)Swagger: 通过固定格式的注释生成文档. 省时省力,不过有点学习成本。 (4)APIJSON:客户端可以定义任何JSON结构去向服务端发起请求,服务端就会返回对应结构的JSON字符串,所求即所得。
- API测试与单元测试之间的区别
答: API测试和单元测试不是一回事,尽管它们是相似的。单元测试由开发团队完成,以确保特定的软件单元按要求运行; 由于它不是黑盒测试,因此无法准确反映该领域的软件使用情况。坦率地说,开发人员对他们的软件了如指掌,所以他们可能会错过一些对于不熟悉软件内部工作的测试人员而言可能非常明显的事情。 API测试人员的工作是测试软件只知道用户可能知道什么。API测试还测试单元作为系统的一部分,而单元测试通常测试单元与系统其余部分的相对隔离。 真正的Web API测试需要Internet连接,因为与Web API的通信是通过Web完成的。单元测试在本地计算机上完成,无需Internet连接。 单元测试: (1)开发人员执行它 (2)小型设备单独进行测试 (3) 开发人员可以访问源代码 (4)旨在找到程序员错误和代码覆盖率 (5) 范围有限 (6)通常在办理登机手续之前运行 API测试: (1)测试人员执行它 (2)是一种端到端测试方法 (3)测试人员将API视为黑盒子 (4)可以检查多种功能 (5) 也可以进行性能测试 (6)所有功能问题都经过测试 (7) 范围更广 (8)在构建之后创建
- 执行API测试的时候,我们将会面临哪些BUG类型
答: (1)特殊值处理不当导致程序异常退出或者崩溃 (2)类型边界溢出,导致数据读出和写入不一致 (3)取值边界外值未返回正确的错误信息 (4)参数 为null或空字符串“”等 (5)权限未处理,可以访问其他用户的信息 (6)逻辑校验不完善,可利用漏洞获取非正当利益 (7)状态处理不当,导致逻辑出现错误(可能程序员123都搞懵了) (8)数组类型item个数为0或者item重复时程序异常退出 (9)超时问题,超时后处理 (10)潜在性能问题(后台提交处理或者把性能风险提前提出)
- 接口产生的垃圾数据如何清理
答: 接口自动化问题。 (1)测试用例前后,可以用setUp和tearDown来做测试环境的初始化和清理,也可以用装饰器@pytest.fixture和@pytest.mark.usefixtures来实现; (2)造数据的数据清理,需用python连接数据库,做增删改查操作;
29.postman测试流程?Jmeter测试流程?大致说一下
答:
(1)postman使用流程: a.选择接口请求类型填入请求URL地址 b.填写接口参数信息(比如填写Body等) c.点击Send,查看响应 d.若是需要可以在tests中添加响应断言、脚本,看看是否符合预期结果 (2)Jmeter使用流程: a.首先我们要新建一个线程组,线程组的作用模拟多个访问对象,对系统可以进行压力测试 b.添加“HTTP Cookie管理器”, c.添加“Http请求默认值”组件,当被测系统有唯一的访问域名和端口时, d.在“HTTP 请求默认值”组件配置页面,填写被测系统的域名和端口,http请求的实现包版本以及具体协议类型,线程组里的所有“HTTP Sampler”可默认使用此设置。 e.在“线程组”里添加“HTTP 请求”的Sampler f.在HTTP请求设置页面,录入被测接口的详细信息,包括请求路径,对应的请求方法,以及随请求一起发送的参数列表 g.设置检查点:在被测接口对应的“HTTP 请求”上,添加“响应断言” h.在设置页面上添加对相应结果的正则表达式存在性判断即可: i.添加监听器:方便查看运行后的结果 复杂测试案例均在此基础上扩展完成。使用Jmeter工具开发的接口测试案例,一个子系统建议放在同一个 “测试计划”中,流程测试可以通过“线程组”来区分,这样也便于设定不同的测试数据个数。比较独立的接口,可以统一放在一个线程组内,顺序完成测试。 流程性接口的测试:如果要测试的接口可以组成一个流程,只需要顺序添加多个“HTTP 请求”的Sampler,各请求之间可以提取需要在上下文传递的数据作为参数,以保证流程中数据的一致性。
30.公司用到第三方服务,出问题,沟通第三方,第三方不承认,这时候日志不显示错误,应怎么处理
答: (1)单独调用第三方服务,查看返回结果; (2)引入mock机制,假如正常返回的情况下,测试我们的系统是否存在问题; (3)建议开发增加日志,详细记录调用第三方接口的过程,记录调用前接口入参,返参等信息;
31.post请求的四种参数形式是什么
答: 四种参数形式如下:
Plain Text
application/x-www-form-urlencoded
multipart/form-data
application/json
text/xml
数据库:
- 在数据库测试中,我们需要正常检查内容是什么
答: (1)约束检查 (2)验证字段大小 (3)存储过程 (4)将应用程序字段大小与数据库匹配 (5)基于绩效的问题的索引
- 什么是数据驱动测试
答: 在数据表中,为了测试多个数据,使用数据驱动的测试,通过使用它,它可以很容易的从不同位置同时替换参数。
- 什么是连接并提及不同类型的连接
答: (1)Join用于显示两个或两个以上的表,连接类型为: 自然加入 内部联接 外加入 交叉加入 (2)外部联接又分为两部分: 左外连接 右外连接
- 什么是索引并提及不同类型的索引?
答: 索引是数据库对象,它们是在列上创建的。为了快速获取数据,经常访问它们。不同类型的索引是: B树索引 位图索引 聚集索引 覆盖指数 非唯一索引 独特的指数
- 在存储过程中,测试需要使用哪些步骤
答: 测试人员将检查存储过程的标准格式,并检查字段是否正确,如存储过程中提到的更新,连接,索引,删除。
- 如何做到数据库测试是否触发了触发器
答: 在查询公共审计日志时,您会知道是否触发了触发器。它位于审计日志中,您可以在其中查看触发的触发器。
- 在数据库测试中,测试数据加载的步骤是什么
答: 以下步骤需要遵循测试数据加载: 应该知道源数据 目标数据应该是已知的 应检查源和目标的兼容性 在SQL Enterprise管理器中,打开相应的DTS包后运行DTS包 必须比较目标和数据源的列 应检查目标和源的行数 更新源中的数据后,检查更改是否显示在目标中。 检查NULL和垃圾字符
- 什么是DBMS
答: DBMS代表数据库管理系统,有不同类型的DBMS: 网络模型 分层模型 关系模型
- 触发器的作用是什么
答: 触发器是一种用来保障参照完整性的特殊的存储过程,它维护不同表中数据间关系的有关规则。当对指定的表进行某种特定操作(如:Insert,Delete或Update)时,触发器产生作用。触发器可以调用存储过程。
- 什么是存储过程?用什么来调用?优缺点是什么
答: 存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。可以用一个命令对象来调用存储过程。 优点: 存储过程是预编译过的,执行效率高。 存储过程的代码直接存放于数据库中,通过存储过程名直接调用,减少网络通讯。 安全性高,执行存储过程需要有一定权限的用户。 存储过程可以重复使用,可减少数据库开发人员的工作量。 缺点: 移植性差
- 什么样的字段适合创建索引
答: (1)表的主键、外键必须有bai索引; (2)数据量超过300的表应该有索引; (3)经常与其他表进行连接的表,在连接字段上应该建立索引; (4)经常出现在Where子句中的字段,特别是大表的字段,应该建立索引; (5)索引应该建在选择性高的字段上; (6)索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引; (7)复合索引的建立需要进行仔细分析;尽量考虑用单字段索引代替: A、正确选择复合索引中的主列字段,一般是选择性较好的字段; B、复合索引的几个字段是否经常同时以AND方式出现在Where子句中?单字段查询是否极少甚至没有?如果是,则可以建立复合索引;否则考虑单字段索引; C、如果复合索引中包含的字段经常单独出现在Where子句中,则分解为多个单字段索引; D、如果复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减少复合的字段; E、如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引; (8)频繁进行数据操作的表,不要建立太多的索引; (9)删除无用的索引,避免对执行计划造成负面影响; 以上是一些普遍的建立索引时的判断依据。一言以蔽之,索引的建立必须慎重,对每个索引的必要性都应该经过仔细分析,要有建立的依据。因为太多的索引与不充分、不正确的索引对性能都毫无益处:在表上建立的每个索引都会增加存储开销,索引对于插入、删除、更新操作也会增加处理上的开销。另外,过多的复合索引,在有单字段索引的情况下,一般都是没有存在价值的;相反,还会降低数据增加删除时的性能,特别是对频繁更新的表来说,负面影响更大。
- 比如现在表中数据10万,有资产20000以上8万人, 查询出小于20000并大于1000资产的SQL,你怎么判断这个SQL性能?哪个条件放在前哪个条件在后?
答: 先查出小于20000的,SQL性能会更快;小于20000在前,大于1000在后
- 索引类型有哪些?
答: 根据数据库的功能,可以在数据库设计器中创建四种索引:唯一索引、非唯一索引、主键索引和聚集索引。 尽管唯一索引有助于定位信息,但为获得最佳性能结果,建议改用主键或唯一约束。undefined(1)唯一索引:undefined唯一索引是不允许其中任何两行具有相同索引值的索引。 当现有数据中存在重复的键值时,大多数数据库不允许将新创建的唯一索引与表一起保存。数据库还可能防止添加将在表中创建重复键值的新数据。例如,如果在 employee 表中职员的姓 (lname) 上创建了唯一索引,则任何两个员工都不能同姓。undefined(2)非唯一索引:undefined非唯一索引是相对唯一索引,允许其中任何两行具有相同索引值的索引。 当现有数据中存在重复的键值时,数据库是允许将新创建的索引与表一起保存。这时数据库不能防止添加将在表中创建重复键值的新数据。undefined(3)主键索引:undefined数据库表经常有一列或列组合,其值唯一标识表中的每一行。该列称为表的主键。 在数据库关系图中为表定义主键将自动创建主键索引,主键索引是唯一索引的特定类型。该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。 (4)聚集索引(也叫聚簇索引): 在聚集索引中,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。 如果某索引不是聚集索引,则表中行的物理顺序与键值的逻辑顺序不匹配。与非聚集索引相比,聚集索引通常提供更快的数据访问速度。
- 什么是视图、触发器、事务、锁,能说说吗
答: 视图: 是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。 视图的特点: (1)视图的列可以来自不同的表,是表的抽象和逻辑意义上建立的新关系; (2)视图是由基本表(实表)产生的表(虚表); (3)视图的建立和删除不影响基本表; (4)对视图内容的更新(添加、删除和修改)直接影响基本表; (5)当视图来自多个基本表时,不允许添加和删除数据。 触发器: 监视某种情况,并触发某种操作;对某个表进行【增/删/改】操作的前后如果希望触发某个特定的行为时,可以使用触发器,触发器用于定制用户对表的行进行【增/删/改】前后的行为。 触发器创建语法四要素: (1)监视地点(table) (2)监视事件(insert/update/delete) (3)触发时间(after/before) (4)触发事件(insert/update/delete) 事务: 一组sql语句批量执行,要么全部执行成功,要么全部执行失败。 现在的很多软件都是多用户,多程序,多线程的,对同一个表可能同时有很多人在用,为保持数据的一致性,所以提出了事务的概念。 举个例子:A 给 B 转账,A 的账户 -1000元,B 的账户就要 1000元,这两个update 语句必须作为一个整体来执行,不然 A 扣钱了,B 没有加钱这种情况很难处理。 事物的特性: (1)原子性:对于其数据修改,要么全都执行,要么全都不执行; (2)一致性:数据库原来有什么样的约束,事务执行之后还需要存在这样的约束,所有规则都必须应用于事务的修改,以保持所有数据的完整性; (3)隔离性:一个事务不能知道另外一个事务的执行情况(中间状态); (4)持久性:即使出现致命的系统故障也将一直保持。不要告诉我系统说commit成功了,回头电话告诉我,服务器机房断电了,我的事务涉及到的数据修改可能没有进入数据库。 PS: 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务; 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行; 事务用来管理 insert,update,delete 语句。 锁: 当并发事务同时访问一个资源时,有可能导致数据不一致,因此需要一种机制来将数据访问顺序化,以保证数据库数据的一致性。 锁的基本类型: 多个事务同时读取一个对象的时候,是不会有冲突的。同时读和写,或者同时写才会产生冲突。 因此为了提高数据库的并发性能,通常会定义两种锁:共享锁和排它锁。 (1)共享锁(Shared Lock,也叫S锁)共享锁表示对数据进行读操作。因此多个事务可以同时为一个对象加共享锁。(如果试衣间的门还没被锁上,顾客都能够同时进去参观) (2)排他锁(Exclusive Lock,也叫X锁)排他锁表示对数据进行写操作。如果一个事务对对象加了排他锁,其他事务就不能再给它加任何锁了。(某个顾客把试衣间的门从里面反锁了,其他顾客想要使用这个试衣间,就只有等待锁从里面给打开) 实际开发中常见的两种锁: (1)悲观锁:顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会 block(阻塞),当自己拿完数据的时候就能让别人操作了。传统的关系型数据库里边就用到了很多这种锁机制。 注意:要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。关闭自动提交命令为:set autocommit=0; 设置完autocommit后,就可以执行正常业务了。 注意1.1:在使用悲观锁时(一定要给表指定主键),如果表中没有指定主键,则会进行锁表操作; 注意1.2: 悲观锁的确保了数据的安全性,在数据被操作的时候锁定数据不被访问,但是这样会带来很大的性能问题。因此悲观锁在实际开发中使用是相对比较少的。 (2)乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。 使用乐观锁的两种方式: (1)使用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。 何谓数据版本?即为数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的"version"字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加1。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据。 (2)乐观锁定的第二种实现方式和第一种差不多,同样是在需要乐观锁控制的table中增加一个字段,名称无所谓,字段类型使用时间戳(datatime),和上面的version类似,也是在更新提交的时候检查当前数据库中数据的时间戳和自己更新前取到的时间戳进行对比,如果一致则OK,否则就是版本冲突。 悲观锁与乐观锁的优缺点: 两种锁各有其优点缺点,不能单纯的讲哪个更好; 乐观锁适用于写入比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量; 但如果经常产生冲突,上层应用会不断的进行重试操作,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。
- 列出几种表的连接方式与区别
答: 内连接、自连接、外连接(左、右、全)、交叉连接 : (1)内连接:只有两个元素表相匹配的才能在结果集中显示。 (2)外连接: 左外连接:左边为驱动表,驱动表的数据全部显示,匹配表的不匹配的不会显示。 (3)右外连接:右边为驱动表,驱动表的数据全部显示,匹配表的不匹配的不会显示。 (4)全外连接:连接的表中不匹配的数据全部会显示出来。 (5)交叉连接: 笛卡尔效应,显示的结果是链接表数的乘积。
- 主键与外键的区别
答: (1)主键是能确定一条记录的唯一标识,比如,一条记录包括身份正号,姓名,年龄。 身份证号是唯一能确定你这个人的,其他都可能有重复,所以,身份证号是主键。 (2)外键用于与另一张表的关联。是能确定另一张表记录的字段,用于保持数据的一致性。
- SQL查询语句速度很慢时,如何优化
答: (1)建索引 提高查询检索的性能 创建唯一索引 创建主键 归类 (2)减少表之间的关联 (3)优化sql,尽量让sql很快定位数据,不要让sql做全表查询,应该走索引,把数据量大的表排在前面 (4)简化查询字段,没用的字段不要,已经对返回结果的控制,尽量返回少量数据
- 数据库三范式是什么
答:
范式:
数据库设计对数据的存储性能,还有开发人员对数据的操作都有莫大的关系。所以建立科学的,规范的的数据库是需要满足一些规范的来优化数据数据存储方式。在关系型数据库中这些规范就可以称为范式。 第一范式(1NF):强调的是列的原子性,即列不能够再分成其他几列。 第二范式(2NF):首先是 1NF,另外包含两部分内容,一是表必须有一个主键;二是没有包含在主键中的列必须完全依 赖于主键,而不能只依赖于主键的一部分。 第三范式(3NF):首先是 2NF,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列 A 依赖 于非主键列 B,非主键列 B 依赖于主键的情况。 注:关系实质上是一张二维表,其中每一行是一个元组,每一列是一个属性 如何理解三大范式? 第一范式(1NF): (1)、每一列属性都是不可再分的属性值,确保每一列的原子性 (2)、两列的属性相近或相似或一样,尽量合并属性一样的列,确保不产生冗余数据 如果需求说要按哪个省哪个市分类,那么显然第一个表格是不容易满足需求的,也不符合第一范式。 第二范式(2NF): 每一行的数据只能与其中一列相关,即一行数据只做一件事。只要数据列中出现数据重复,就要把表拆分开来。 一个人同时买几件商品,就会出来一个订单号多条数据,这样子客户都是重复的,就会造成数据冗余。我们应该把他拆开来。 这样这张表就不会产生数据冗余了。 第三范式(3NF): 数据不能存在传递关系,即没个属性都跟主键有直接关系而不是间接关系。像:a-->b-->c 属性之间含有这样的关系,是不符合第三范式的。 考虑一个订单表T_ORDER(OrderNO,PRODUCTNO,CUSTOMERID,CUSTOMERNAME,CUSTOMERPHONE,CUSTOMERCARDID)主键是(ORDERNO)。 其中PRODUCTNO,CUSTOMERID,CUSTOMERNAME,CUSTOMERPHONE,CUSTOMERCARDID等非主键列都完全依赖于主键(ORDERNO),所以符合 2NF. 不过问题是CUSTOMERNAME,CUSTOMERPHONE,CUSTOMERCARDID 直接依赖的是 CUSTOMERID(非主键列),而不是直接依赖于主键,它是通过传递才依赖于主键,所以不符合 3NF。 通过拆分T_ORDER为(OrderNO,PRODUCTNO,CUSTOMERID)和T_CUSTOMER(CUSTOMERID,CUSTOMERNAME,CUSTOMERPHONE,CUSTOMERCARDID)从而达到 3NF。 结论 三大范式只是一般设计数据库的基本理念,可以建立冗余较小、结构合理的数据库。如果有特殊情况,当然要特殊对待,数据库设计最重要的是看需求跟性能,需求>性能>表结构。所以不能一味的去追求范式建立数据库。
- order by 与 group by分别作用是什么
答: (1)Order by 从英文里理解就是行的排序方式,默认的为升序。 order by 后面必须列出排序的字段名,可以是多个字段名。 (2)Group by 从英文里理解就是分组。必须有“聚合函数”来配合才能使用,使用时至少需要一个分组标志字段。 注意:聚合函数是---sum()、count()、avg()等都是“聚合函数”
Linux:
注: 关于LINUX部分就不详细编写,见<软件测试复习版>
- 查看当前进程? 执行退出?怎么查看当前路径
答: 查看当前进程: ps 执行退出: exit 查看当前路径: pwd
- 怎么执行睡眠
答: 休眠: sudo pm-hibernate
- 怎么查看当前用户ID
答: whoami && id
- LS命令执行什么功能,具体带有哪些参数?有什么区别
答: 功能: 列出指定目录中的目录,以及文件哪些参数 区别: a 所有文件 l 详细信息,包括大小字节数,可读可写可执行的权限等
- 查看日志
答: (1)tail tail -f 日志文件 (常用) tail -n 100 日志文件 (查询日志尾部最后100的日志) tail -n 100 日志文件 (查询100行之后的所有日志) tail -fn 100 日志文件 (循环实时查询最后100行记录) 配合grep使用: tail -fn 100 catalina.out | grep -- '关键字' (2)head head -n 100 日志文件 (打印日志文件中的头100行日志) head -n 100 日志文件 (打印出100行后所有的日志) (3)cat cat 日志文件 (显示所有日志文件) cat filename| head -n 3000 | tail -n 1000 (打印出第1000行至3000行的日志) (4)set sed -n '8,12p' 日志文件 (打印出第8行至第12行日志文件) sed -n '/2019-01-17 10:07:10/,/2019-02-14 16:54:01/p' (打印出2019-01-17 10:07:10/,/2019-02-14 16:54:01时间段的日志文件) 还有一些其它查看日志命令就不写了,常用就有Tail -f
- 目录创建
答: mkdir 目录名称
- 怎么查看文件权限
答: ls -l
- 终端是在哪个文件夹下的哪个文件,黑洞文件是在哪个文件夹下的哪个命令?
答: 终端 /dev/tty 黑洞文件 /dev/null
- 用什么命令能够对一个文件内容进行统计
答: wc 命令 - c 统计字节数 - l 统计行数 - w 统计字数
- 发布代码流程
答: 使用传输工具ssh或者xftp6连接服务器(ip 账号密码),并且打开项目下的项目代码文件位置(可以咨询开发),让开发打个jar包发给你,使用传输工具传输替换. 先杀进程在输入以下命令: lsof -i | grep 10089 ----比如10089为线上端口号,先查出 Kill -9 进程号 ----杀掉该端口号的进程 nohup java -jar ops tab键 & ----使用nohup命令运行jar文件(也就是启动项目) Tail -f nohup.out
UI自动化:
- 如何搭建UI自动化框架
答: 搭建UI自动化框架时,使用的是PO设计模式,也就是把每一个页面所需要操作的元素和步骤封装在一个页面类中。然后使用Selenium unitest搭建四层框架实现数据、脚本、业务逻辑分离(关键字驱动)。其中四层框架包括基础层、业务逻辑层、数据层、测试用例层。 (1)基础层(BasePage): 设计一个基本的Page类,所有页面皆继承该类。提供一个页面需要实现的基本功能及公共方法。 (2)业务逻辑层(Pages): 按照PO设计模式,将每个页面抽象为一个类,放在Pages包里面,每个页面继承Basepage,可调用Data层数据,包括页面所有的操作对象属性和实现的功能 (3)数据层(Data): 该层存放相关数据,例如:用户数据和密码。在测试用例可通过调用数层的数据来进行操作。 (4)测试用例层(Testcases): 每一个测试用例testcase都对应Pages里面的一个页面,继承unnitest.TestCase类 通过调用对应页面类的方法,数据层的数据、增加断言(assert)来验证功能的正确性。此外通过Jenkins自动执行测试、代码质量检测和部署到测试服务器、部署到生产服务器上
- UI自动化定位方式有哪些,你在工作中常用的有哪些
答: By id By class name By tag name By name By link text By partial link textzhi By Css seletor By Xpath
- UI自动化时间等待有哪些?区别是什么
答: sleep()强制等待,设置固定休眠时间,执行sleep( )后线程休眠 而另外两种线程不休眠 隐式等待,是设置的全局等待 显示等待,是针对于某个特定的元素设置的等待时间
- WebDriver原理是什么
答: 由于客户端脚本(java, python, ruby)不能直接与浏览器通信,这时候可以把Webdriver 当做一个翻译器,它可以把客户端代码翻译成浏览器可以识别的代码(比如js).客户端(也就是测试脚本)创建 1 个 session,在该 session 中通过 http 请求向Webdriver 发送请求,Webdriver 翻译成浏览器懂得脚本传给浏览器,浏览器把执行的结果返回给 Webdriver,Webdriver 把返回的结果做了一些封装(一般都是 json 格式),然后返回给客户端,根据返回值就能判断对浏览器的操作是不是执行成功。
- Selenium中的Hidden或Display=none元素能否定位
答: 不能
- 如何提高Selenium脚本执行速度
答: (1)减少操作步骤,减少脚本用例不必要的步骤 (2)设置等待时间的时候,可以 sleep 固定的时间,也可以检测某个元素出现后中断等待也可 以提高速度 (3)实现多线程。在编写测试用例的时候,一定要实现松耦合,然后在服务器允许的情况下,尽量设置多线程运行,提高执行速度。
- 如何实现多线程
答: 先写一个run的函数 保证for循环能跑的通- 在run函数上加个装饰器 @threads(n),n是线程数
- 说一下XPath定位原理
答: 基于html的文档目录结构进行定位元素
- Selenium工作过程是什么
答: (1)selenium client(python等语言编写的自动化测试脚本)初始化一个service服务,通过webdriver启动浏览器驱动程序chromedriver.exe (2)通过RemoteWebDriver向浏览器驱动程序发送HTTP请求,浏览器驱动程序解析请求,打开浏览器,并获得sessionid,如果再对浏览器操作需携带此id (3)打开浏览器后,所有的selenium的操作(访问地址,查找元素)均通过RemoteConection链接到remote server,然后使用execute方法调用request方法通过urlib3向remote server请求 (4)浏览器通过请求的内容执行对应动作 (5)浏览器再把执行的动作结果通过浏览器驱动程序返回给测试脚本 补充Selenium原理: 我们使用Selenium实现自动化测试,主要需要3个东西 (1)测试脚本,可以是python,java编写的脚本程序(也可以叫做client端) (2)浏览器驱动,这个驱动是根据不同的浏览器开发的,不同的浏览器使用不同的webdriver驱动程序且需要对应相应的浏览器版本 (3)浏览器,目前selenium支持市面上大多数浏览器,不同的浏览器使用不同的webdriver驱动程序且需要对应的浏览器版本
- Selenium能否读取excel文件的库
答: 没有,这里需要用到第三方工具。例如Apache POI插件。
- Selenium有哪些组件
答: 最早的有Selenium IDE,IDE只支持安装在fiefox上一个插件,支持录制自动化脚本。还有 remote RC,和Grid 和webdriver。我们一般最重要的就是使用webdriver。
- Selenium能否支持Windows桌面应用软件的自动化测试
答: Selenium不支持桌面软件的自动化测试,Selenium是根据网页元素的属性才定位元素,而其他桌面软件自动化测试工具是根据桌面元素的位置来定位元素,当然现在也有根据桌面元素的属性来定位的。
- 你在原来公司工作中写的测试脚本能在不同浏览器中运行吗?能支持跨浏览器平台吗
答: 是的,我写的测试用例能在IE,火狐和谷歌这三种浏览器上运行。主要是在windows平台上运行脚本,所以mac的safari浏览器暂时没有写过。主要实现这个跨浏览器的思想就是,把浏览器类型写到配置文件,代码里写if语句去判断配置文件的浏览器的类型,来决定用什么浏览器去执行测试用例。
- 你在自动化工作中,遇到了什么问题
答: 主要有以下几点: 频繁地变更UI,经常要修改页面对象里面代码 运行用例报错和处理,例如元素不可见,元素找不到这样异常 测试脚本复用,尽可能多代码复用 一些新框架产生的页面元素定位问题,例如ck编辑器,动态表格等
- 举例说一下你在Selenium执行脚本过程中遇到哪些异常
答: ElementNotSelectableException :元素不能选择异常 ElementNotVisibleException :元素不可见异常 NoSuchAttributeException :没有这样属性异常 NoSuchElementException:没有该元素异常 NoSuchFrameException :没有该frame异常 TimeoutException : 超时异常 Element not visible at this point :在当前点元素不可见
- 如何处理Alert弹窗
答: 常见的alert弹窗有两种:基于windows弹窗和基于web页面弹窗 我们知道,webdriver是能够处理alert弹窗的,Selenium提供了Alert这个接口。相关操作代码如下: // 切换到Alert Alert alert = driver.switchTo().alert(); // 点击弹窗上确定按钮 alert.accept(); // 点击弹窗的取消按钮 alert.dismiss() // 获取弹窗上线上的文本文字内容 alert.getText(); // 有些弹窗还支持文本输入,这个可以把要输入字符通过sendkeys方法输入 alert.sendkeys();
- 在Selenium中如何处理多窗口
答: 需要用到swithTo方法。获取当前浏览器多窗口句柄,然后根据判断跳转新句柄还是旧句柄。
- 如何处理下拉菜单
答: 通常我们也可以通过Click方法来点击下拉菜单里面的元素,还有一种方法,在Selenium中有一个类叫Select,支持这种下拉菜单交互的操作。 基本使用语法是这样的: Select Se=new Select(element); Se.selectByIndex(index); Se.selectByvalue(value); Se.selectByVisibleText(text);
- 你定位的元素有在F12中的控制台,怎么验证定位对不对的呢?用的什么语法
答: 涉及到前端知识,只需要了解即可,ID用"#",其他的用"." document.querySelectorAll('# ')”;undefineddocument.querySelectorAll('. ')”; 当然还有其他的方法验证,可以咨询前端开发
- quit与close的区别是什么
答: 简单来说,两个都可以实现退出浏览器session功能,close是关闭你当前运行的tab页面,而quit是关闭全部的tab页面,并退出浏览器session。知道这两个区别,我们就知道quit一般用在结束测试之前的操作,close用在执行用例过程中关闭某一个页面的操作。
- 什么是页面加载超时
答: Selenium中有一个 Page Load wait的方法,有时候,我们执行脚本的速度太快,但是网页程序还有一部分页面没有完全加载出来,就会遇到元素不可见或者元素找不到的异常。为了解决问题,让脚本流畅的运行,我们可以通过设置页面加载超时时间。具体代码是这个:driver.manage().timeouts().pageLoadTimeout(10,TimeUnit.SECONDS); 这行作用就是,如果页面加载超过10秒还没有完成,就抛出页面加载超时的异常。
- JavaScript Executor是什么,你什么时候用到
答:
JavaScript Executor是一个接口,给driver对象提供一个执行javaScript并访问和修改前端元素属性和值。 还是有比较多的场景,我们可能或者需要借助javaScript来实现: 1.元素通过现有定位表达式不能够实现点击 2.前端页面试用了ck-editor这个插件 3.处理时间日期插件(可能) 4.生成一个alert弹窗 5.拖拽滚动条 基本语法: JavascriptExecutor js =(JavascriptExecutor) driver; js.executeScript(Script,Arguments);
- Selenium中执行用例失败截图你是怎么实现的
答: 在Selenium中提供了一个TakeScreenShot这么一个接口,这个接口提供了一个getScreenshotAs()方法可以实现全屏截图。然后我们通过java中的FileUtils来实现把这个截图拷贝到保存截图的路径。 代码举例: File src=((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); try { // 拷贝到我们实际保存图片的路径 FileUtils.copyFile(src,new File("C:/selenium/error.png")); } catch (IOException e) { System.out.println(e.getMessage()); } 如果要实现执行用例发现失败就自动截图,那么我们需要把这个截图方法进行封装。然后在测试代码中的catch代码块去调用这个截图方法。这个我们在POM的框架中一般是把截图方法封装到BasePage这个文件中。
- Selenium中如何实现拖拽滚动条
答: 在Selenium中通过元素定位会自动帮你拖拽到对应位置,所以是没有自带的scoll方法。但是这个是有限制,例如当前页面高度太长,默认是页上半部分,你定位的元素在页尾,这个时候可能就会报元素不可见的异常。我们就需要利用javaScript来实现拖拽页面滚动条。 我们一般可以两个方法去拖拽,一个是根据拖拽的坐标(像素单位),另外一个是根据拖拽到一个参考元素附件。 代码举例(根据元素坐标拖拽): JavascriptExecutor jse= (JavascriptExecutor)driver; jse.executeScript("window.scrollBy(0,250)", "");
- 如何处理不受信任的证书问题
答:
(1)火狐: / 创建firefoxprofile FirefoxProfile profile=new FirefoxProfile(); // 点击继续浏览不安全的网站 profile.setAcceptUntrustedCertificates(true); // 使用带条件的profile去创建一个driver对象 WebDriver driver=new FirefoxDriver(profile); (2)谷歌: // 创建类DesiredCapabilities的对象 DesiredCapabilities cap=DesiredCapabilities.chrome(); // 设置ACCEPT_SSL_CERTS 变量值为true cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true); // 新建一个带capability的chromedriver对象 WebDriver driver=new ChromeDriver(cap);
- 如果登录过程中遇到手机号码或者验证码你是怎么绕过的呢, 或说一下是怎么处理
答: (1)去掉验证码(测试环境) 这是最简单的方法,对于开发人员来说,只是把验证码的相关代码注释掉即可,线上环境取消注释验证码模块。如果是在测试环境,这样做可省去了测试人员不少麻烦,线上环境若是去掉验证码的话一般是不可取的,线上环境可选择下面的方案二。 (2)设置万能验证码(应该是最佳选择,但是需要开发人员的支持) 去掉验证码的主要是安全问题,为了应对在线系统的安全性威胁,可以在修改程序时不取消验证码,而是程序中留一个“后门”——设置一个“万能验证码” ,只要用户输入这个“万能验证码” ,程序就认为验证通过,否则按照原先的验证方式进行验证。 (3)验证码识别技术 例如可以通过 Python-tesseract等技术来识别图片验证码,Python-tesseract 是光学字符识别 Tesseract OCR 引擎的 Python 封装类。能够读取任何常规的图片文件(JPG, GIF ,PNG , TIFF 等)。不过,目前市面上的验证码形式繁多,目前任何一种验证码识别技术,识别率都不是 100% 。 目前有很多专门做验证码识别技术的,毕竟术业有专攻,也是不错之选,毕竟自己造轮子不大可取。 (4)记录 cookie 通过向浏览器中添加 cookie 可以绕过登录的验证码,这是比较有意思的一种解决方案。 我们可以在用户登录之前,手动登陆,获取cookie,通过 add_cookie()方法将用户名密码写入浏览器 cookie ,再次访问系统登录链接将自动登录。 但是有的Cookie有一个过期时间,一旦再次运行代码时就需要重新获取cookie,也造成一些麻烦。 (5)绕过验证码实例
- 自动化报告生成你用的什么插件
答: 一般用TestNG原生的测试报告,也有第三方叫reportNG的插件
- Selenium如何判断元素是否存在
答: Presense_of_element_located
- 你自动化用例执行的执行策略是什么
答: 1.自动化测试用例是用来监控的。集成到jenkins,创建定时任务定时执行; 2.有些用例在产品上线前必须回归。jenkins上将任务绑定到开发的build任务上,触发执行; 3.有些用例不需要经常执行。jenkins创建一个任务,需要执行的时候人工构建即可。
- Selenium需要连接数据库进行数据校验吗
答: UI自动化不需要 接口测试会需要
- 如何定位动态变化的元素,假设一个网站每次登陆元素都会变化,你是怎么处理的呢,用什么方法
答: 先去找该元素不变的属性,要是都变,那就找不变的父元素,用层级定位(以不变应万变) 属性动态变化也就是指该元素没有固定的属性值,可以通过:JS实现。通过相对位置来定位。
- 什么是断言和验证
答: 断言(assert):测试将会在检查失败时停止,并不运行后续的检查 优点:可以直截了当的看到检查是否通过 缺点:检查失败后,后续检查不会执行,无法收集那些检查结果状态 验证(vertify):将不会终止测试 缺点:你必须做更多的工作来检查测试结果:查看日志——>耗时多,所以更偏向于断言。 检查一个条件,如果它为真,就不做任何事,用例通过。如果它为假,则会抛出 AssertError 并且包含错误信息。
- 自动化测试用例从哪里来的
答: 从手工测试用例中抽取
- 你觉得自动化最大的缺陷是什么?你们平时工作中是怎么利用自动化的呢?如何不是纯搞自动化测试的情况下
答: 不稳定 可靠性不强 不易维护 成本与收益 平时工作中,我们是先测试部会议讨论哪些业务流程或者需求不经常迭代,在比较稳定的情况下,针对这些需求或业务流程从手工测试用例中抽取部分用例进行脚本编写,这样省去很多时间。
- 什么是分层测试
答: (1)数据层 (2)接口层 (3)UI层
- WebDriver可以用来做接口测试吗
答: 不可以,WebDriver是专门用来做Web的UI自动化参数的
- 如果在用例执行过程中出现不稳定的情况下,比如这次运行成功,第二次运行失败,你是怎么处理的
答: 1.在经常检测失败的元素前尽量加上显式等待时间,等要操作的元素出现之后再执行下面的操作; 2.多线程的时候,减少测试用例耦合度,因为多线程的执行顺序是不受控制的; 3.多用 try 捕捉,处理异常; 4.尽量使用测试专用环境,避免其他类型的测试同时进行,对数据造成干扰。
- 写个冒泡排序
答: 代码如下: public static void bubbleSort(int[] array) { int temp; int size = array.length; for (int i = 0; i < size - 1; i ) { for (int j = 0; j < size - 1 - i; j ) { if (arrayj < arrayj 1) { temp = arrayj; arrayj = arrayj 1; arrayj 1 = temp; } } } } 测试代码: public static void main(String[] args) { int[] array = {1, 2, 6, 9, 10}; bubbleSort(array); System.out.println(Arrays.toString(array)); } 输出结果: 10,9,6,2,1
- 在Selenium自动化测试中,你一般完成什么类型的测试
答: 主要是冒烟测试和回归测试。回归测试主要写一些功能稳定,容易实现的场景,通过自动化手段去实现,节约测试时间。
- 自动化测试脚本编写规范
答: (1)基本信息 在每个脚本模块的最上面,必须写上脚本运行的软件和硬件环境(如IE版本、QTP版本、数据库版本等)、外包项目名称、脚本编写人(使用英文名或中文拼音缩写)、脚本创建时间、脚本修改时间、修改说明、输入参数、输出参数、脚本描述等。 (2)常量命名规范 常量的命名应该全部用大写,使用"_"作为单词间的分隔符,单词尽量使用全名称,如,Public Const MSG_EMPTY_ROW As String = "有空行存在"。 使用Public而不是早期版本的global来声明变量。 另外,对常量的声明必须带上类型,如前面的As String。 (3)变量命名规范 变量命名应该简单,应尽量使用缩写。如果是一般的值类型(如integer string),则直接使用变量用途命名。尽量使用全名,例如,Dim name As String;如果是一般的临时性变量定义,应该尽可能地简单,例如,Dim i As Integer;如果名称由多个单词组成,则取每个单词的首字母,如EntityManager缩写为em,ProcedureManager缩写为pm;如果名称由一个单词组成,则对单词进行分段取首字母,如Entity缩写为et。缩写应该控制在3个字母以内,且尽量清晰。 (4)参数命名规范 参数命名的原则是全部用小写,如果参数包括两个或两个以上的单词时,首单词字母小写,其他单词首字母大写,如stepName、stepDescription。 (5)函数命名规范 此处函数包括sub和function,函数表示的是一个动作,所以它的结构应该是动词 名词,动词必须小写,后面的名称首字母大写,如getMaterialCode。函数命名尽量不要使用缩写,而且它的名称应该使人一目了然,能够从名称就知道这个函数的功能,不要使用无意义的函数名称。当函数名称不足以表达其功能时,应使用在函数头部加上让调用者足够明白的注释。 (6)代码注释规范 注释务必做到准确简洁,能够充分表达代码实现的功能。 (7)空行 空行是区分代码块与块的间隔,在函数之间必须加上空行;而在函数内部,变量声明块和实现块(实现块指除变量声明外的其他代码)要使用空行来间隔,实现块的内部,通过空行来标识一个功能段。 (8)缩进 必须严格执行缩进,变量声明块不缩进,实现块必须保证全部缩进(不可能有实现块是行首对齐的);对于基本的控制结构来说,必须要有缩进,如IF、DO、WITH、FOR、WHILE块。 (9)续行 对于过长的语句来说,必须使用续行,续行位置要有明显意义,例如,sql ="SELECT code,name FROM Person"_&"WHERE code LIKE'001%'"。 另外,还要通过管理对象库来提高代码的可读性,通过修改命名来达到更加易读的效果。对于使用比较频繁的代码块来说,最好将其写成函数,并尽量将功能复杂的大函数拆分成小函数。 注意:在任何地方,不要写ElseIf语句,最好转换成If…Else…Endif结构。 以下个人见解: (1) 测试脚本的编写规范,包括: 1.1) 文件名、函数、变量、常量等的命名,要易理解、唯一,具有项目、组件、测试目的等特征,具有良好的可读性; 1.2) 脚本编写的一致性、清晰,有足够的注释等。 (2) 自动化测试环境的部署、使用和维护的标准。例如,如何确定测试环境是符合测试设计要求的、谁负责测试环境的维护、谁具有更改环境设置的权限、什么时候更新被测软件包和测试脚本等。 (3)测试脚本的配置管理,包括检入(check-in)、检出(check-out)的要求,以及如何控制脚本的更新、新版本创建、版本的合并等。 (4) 测试脚本的评审方法,可以参照产品源代码的评审方法。 (5) 如何评估自动化测试的结果、如何判断自动化测试是否成功、由谁参与评估等问题。
- PO设计模式原理?哪些地方可以改善
答: PO模式全称page object,页面对象模型,将页面的元素定位和元素行为封装成一个page类,实现页面对象和测试用例分离。 改善的话可以对其中对象库层、逻辑层、业务层进行一系列的封装
- Unittest框架有什么缺点
答: (1)不够灵活,比如进行UI自动化设计时,会多次打开浏览器,增加脚本运行时间 (2)测试报告不够全面,没有pytest的allure测试报告清晰美观
- UI自动化测试有哪些缺点?如何改进
答: 不稳定,页面经常变,不好定位,不适合业务复杂和频繁变动的项目 改进:在项目中尽量使用显示等待
- 如何设计出高质量的自动化测试脚本
答: (1)使用四层结构实现业务逻辑、脚本、数据分离。 (2)使用PO设计模式,将一个页面用到的元素和操作步骤封装在一个页面类中。如果一个元素定位发生了改变,我们只用修改这个页面的元素属性 (3)对于页面类的方法,我们尽量从客户的正向逻辑去分析,方法中是一个独立场景 (4)测试用例设计中,减少测试用例之间的耦合度。
- 什么是持续集成
答: 频繁的将代码集成到主干,持续性的进行项目的构架,以便能能够快速发现错误,防止分支大幅度偏离主干。
- Webdriver协议是什么
答: WebDrive协议本身是http协议,数据传输使用json
- 在日历web表单你是如何处理的
答: 首先要分析当前网页试用日历插件的前端代码,看看能不能通过元素定位,点击日期实现,如果不能,可能需要借助javascript。还有些日历控件一个文本输入框,可以直接sendKeys()方法来实现传入一个时间的数据。
- 如何实现上传文件
答: 在web页面实现文件上传过程中,可以直接把文件在磁盘完整路径,通过sendKeys方法实现上传。如果这种方法不能实现上传,我们就可能需要借助第三方工具,我用过一个第三方工具叫AutoIT.
- findElement 和 FindElements有什么区别?
答: 两个都是查找元素,都支持八大元素定位方法。findElement()得到的只有一个元素,如果根据提供的元素定位方式找不到,会报noSuchElement异常。 findElements()返回的是一组元素,所以我们需要根据能够找到一组元素的表达式去定位,返回一组元素我们可以放在集合里,这样我们就可以使用集合里面的迭代方法去遍历元素,拿到元素去做其他操作。
- 查找元素遇到过在Frame里面吗?你是如何处理Frame里面元素定位的
答: 有时候我们知道元素定位表达式没有问题,但是还是提示no such element,那么我们就需要考虑这个元素是否在frame中。如果在,我们就需要从topwindow,通过swithcTo.Frame()方法来切换到目标frame中,可以通过frame的name和id和索引三种方法来定位frame。
- 什么时候自动化测试
答: 在以下情况下首选自动化: 重复性任务 烟雾和理智测试 使用多个数据集进行测试 回归测试用例 通常,决定基于ROI(投资回报率)
- 执行自动化测试脚本标准是什么
答: 统一命名约定。 每10行代码3行注释 足够的缩进。 强大的错误处理和恢复方案 尽可能使用框架
- Selenium与Sikuil区别是什么
答: Selenium: 它不能自动化视频播放器,音频播放器等闪存对象。 它有复杂的API 它没有视觉匹配 它只能自动化Web应用程序 Sikuli: 它为自动化Flash对象提供了广泛的支持 它有简单的API 它使用视觉匹配来查找屏幕上的元素。因此,我们可以自动化我们在屏幕上看到的任何内容 它可以自动化Web和Windows应用程序
- 如何保证脚本的有效性
答: 保证定位有效性,封装处理异常, 保证流程有效性,封装独立方法 保证数据有效性,数据备份与恢复
- 什么是进程、线程、协程
答: 进程:独立数据空间,进程间不共享数据,系统调度。 线程:执行程序的最小单元,进程内线程间共享资源,系统调度。 协程:程序员调度,分解一个线程成为多个"微线程"。
- 如何判断一个页面上元素是否存在
答: 这个可以说是被问烂的题了,判断元素存在方法有三种: 方法一,用try...except...
Plain Text
def is_element_exsist(driver, locator):
代码语言:txt复制'''
代码语言:txt复制判断元素是否存在,存在返回True,不存返回False
代码语言:txt复制:param locator: locator为元组类型,如("id", "yoyo")
代码语言:txt复制:return: bool值,True or False
代码语言:txt复制'''
代码语言:txt复制try:
代码语言:txt复制 driver.find_element(*locator)
代码语言:txt复制 return True
代码语言:txt复制except Exception as msg:
代码语言:txt复制 print("元素%s找不到:%s" % (locator, msg))
代码语言:txt复制 return False
if __name__ == '__main__':
代码语言:txt复制loc1 = ("id", "yoyo") # 元素1
代码语言:txt复制print(is_element_exsist(driver, loc1))
方法二:用elements定义一组元素方法
Plain Text
def is_element_exsist1(driver, locator):
代码语言:txt复制'''
代码语言:txt复制判断元素是否存在,存在返回True,不存返回False
代码语言:txt复制:param locator: locator为元组类型,如("id", "yoyo")
代码语言:txt复制:return: bool值,True or False
代码语言:txt复制'''
代码语言:txt复制eles = driver.find_elements(*locator)
代码语言:txt复制if len(eles) < 1:
代码语言:txt复制 return False
代码语言:txt复制else:
代码语言:txt复制 return True
if __name__ == '__main__':
代码语言:txt复制loc1 = ("id", "yoyo") # 元素1
代码语言:txt复制print(is_element_exsist1(driver, loc1))
(强烈推荐!)方法三:结合WebDriverWait和expected_conditions判断
Plain Text
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
def is_element_exsist2(driver, locator):
代码语言:txt复制'''
代码语言:txt复制结合WebDriverWait和expected_conditions判断元素是否存在,
代码语言:txt复制每间隔1秒判断一次,30s超时,存在返回True,不存返回False
代码语言:txt复制:param locator: locator为元组类型,如("id", "yoyo")
代码语言:txt复制:return: bool值,True or False
代码语言:txt复制'''
代码语言:txt复制try:
代码语言:txt复制 WebDriverWait(driver, 30, 1).until(EC.presence_of_element_located(locator))
代码语言:txt复制 return True
代码语言:txt复制except:
代码语言:txt复制 return False
if __name__ == '__main__':
代码语言:txt复制loc1 = ("id", "yoyo") # 元素1
代码语言:txt复制print(is_element_exsist2(driver, loc1))
- 一个元素明明定位到了,点击无效也没有报错,你怎么解决
答: 使用js点击,selenium有时候点击元素是会失效
Plain Text
js点击
js = 'document.getElementById("baidu").click()'
driver.execute_script(js)
- Selenium中隐藏元素如何定位
答: 网上写的文章都是一堆废话,给面试者看不到重点。 如果单纯的定位的话,隐藏元素和普通不隐藏元素定位没啥区别,用正常定位方法就行了。 元素的属性隐藏和显示,主要是 type=“hidden” 和 style=“display: none;” 属性来控制的,接下来在元素属性里面让它隐藏,隐藏元素可以正常定位到,只是不能操作,操作元素是 click,clear,send_keys 这些方法; JS 操作隐藏元素;
- UI自动化中,如何做集群
答: Selenium Grid,分布式执行用例 Appium 使用 STF 管理多设备 Docker K8S 管理集群
- 怎么对含有验证码的功能进行自动化测试
答: 让开发写个万能验证码方法,JS语法调用一下 让开发直接把测试环境验证码注释掉,屏蔽 其他操作不推荐
接口自动化:
- 接口自动化测试基本流程是什么
答: 一般在接口功能测试完成以后进行接口自动化测试,每个公司的流程不一,以下仅供参考: (1)抽取接口功能测试用例并将其转化成自动化用例 (2)搭建接口自动化测试环境 (3)搭建项目结构(基于代码) (4)编写脚本用例、数据准备(若是开发使用swagger和thrift,可以自动生成部分测试代码) (5)执行用例 (6)输出测试报告 (7)若公司有Jenkins,可以部署集成。(看贵方需求) (8)优化测试框架 注意点: (1)尽量争取开发提供完整正规的API接口文档 (2)熟悉一款报文工具(fiddler或Charles等都可以) (3)熟悉一门脚本语言(java、Python) (4)熟悉使用requests模块,处理http以及https协议接口非常方便,功能强大 (5)会使用接口工具(postman、jmeter或者其他的工具),这两款工具也可以做到自动化持续集成,在不会写代码的前提下可以使用这些
- 测试数据你放在哪(数据与脚本分离)
答: 测试数据到底该怎么放,这个是面试官最喜欢问的一个题了,似乎仁者见仁智者见智,没有标准的答案,有的人说放excel,也有的说放.py脚本,也有的说放ini配置文件, 还有放到json,yaml文件,txt文件,甚至有的放数据库,五花八门,一百个做自动化的小伙伴有100个放的地方。 这里总结下测试的数据到底该怎么放? 首先测试的数据是分很多种的,有登录的账户数据,也有注册的账户数据,还有接口的参数,还有邮箱配置的数据等等等等,所以这个题不能一概而论给答死了。要不然就是给自己挖坑。 以下两个大忌不能回答: (1)测试的数据是不能写死到代码里面的,这个是原则问题,也是写代码的大忌(你要是回答写在代码里面,估计就是回去等通知了) (2)测试数据放到.py的开头,这种其实很方便,对于少量的,固定不变的数据其实是可以放的,但是面试时候,千万不能这样说,面试官喜欢装逼的方法 测试数据存放总结: (1)对于账号密码,这种管全局的参数,可以用命令行参数,单独抽出来,写的配置文件里(如ini) (2)对于一些一次性消耗的数据,比如注册,每次注册不一样的数,可以用随机函数生成 (3)对于一个接口有多组测试的参数,可以参数化,数据放yaml,text,json,excel都可以 (5)对于可以反复使用的数据,比如订单的各种状态需要造数据的情况,可以放到数据库,每次数据初始化,用完后再清理 (6)对于邮箱配置的一些参数,可以用ini配置文件 (7)对于全部是独立的接口项目,可以用数据驱动方式,用excel/csv管理测试的接口数据 (8)对于少量的静态数据,比如一个接口的测试数据,也就2-3组,可以写到py脚本的开头,十年八年都不会变更的,总之不同的测试数据,可以用不同的文件管理。
- 什么是数据驱动,如何参数化
答: 参数化,就是把测试过程中的数据提取出来,通过参数传递不同的数据来驱动用例运行。其实也就是数据驱动的概念。 在 Unittest 中,我们讲过使用 ddt 库配合 unittest 实现数据驱动。在 Pytest 中并不需要额外的库,通过 pytest.mark.parametrize()即可实现参数化。 通俗点说就是参数化的思想是代码用例写好了后,不需要改代码,只需维护测试数据就可以了,并且根据不同的测试数据生成多个用例。
Plain Text
方法:
代码语言:txt复制 parametrize(argnames, argvalues, indirect=False, ids=None, scope=None)
常用参数:
代码语言:txt复制 argnames:参数名
代码语言:txt复制 argvalues:参数对应值,类型必须为list或元组
代码语言:txt复制 当参数为一个时格式:[value]
代码语言:txt复制 当参数个数大于一个时,格式为:[(param_value1,param_value2.....),(param_value1,param_value2.....)]
代码语言:txt复制 ids:使用的数据组别名,类型必须为list或元组,与argvalues一一对应,用于使用的数据组的展示
使用方法:
代码语言:txt复制 @pytest.mark.parametrize(argnames,argvalues)
代码语言:txt复制 ️ 参数值为N个,测试方法就会运行N次
在进行自动化测试的时候,一般需要对数据进行一个统筹规划实现以用例数据驱动框架进行测试。常见的有: (1)excel存放 优点: 便于维护,框架成型之后维护用例的人员没有学习成本。 缺点: 执行效率低,且用例量级大的时候易卡顿。 (2)yaml存放 优点: 便于维护,轻便 缺点: 学习成本,用例编写设置不够直观 (3)json存放 优点: 便于维护,轻便 缺点: 学习成本,用例编写设置不够直观 (4)类属性存放 优点: 调用便利 缺点: 学习成本
- 如何连接数据库进行操作
答: (1)Python(java差不多) a.启动dos窗口,输入命令:pip install pymysql b.import pymsql 创建连接,配置连接信息 conn = pymysql.Connect(host="127.0.0.1", port=3306,undefined database="books", user="root", password="root", charset="utf8") 创建数据操作载体对象_ cursor 游标 cursor = conn.cursor() 按照需求,编写并执行 sql 语句首先, 声明 SQL 语句sql = "select * from t_book" 然后,通过 cursor 对象将 SQL 语句发送到数据库 cursor.execute(sql) 最后,通过 cursor 对象获取响应结果 print("行数:",cursor.rowcount)#获取行数 print("第一条:",cursor.fetchone())# 获取单条数据 最后释放资源 cursor.close() conn.close() (2)Jmeter a.Test Plan中添加mysql-connector-java-5.1.25-bin.jar包;
b.Test Plan下添加线程组,在线程下添加配置元件-JDBC Connection Configuration,进行数据库的连接配置;
**c.**Test Plan下添加线程组,在线程下添加取样器-JDBC Request,Query区域编写sql脚本; **c1.****Variable Name for created pool:**创建的变量名(JDBC Request可调用) **c2.****Database URL:**格式为jdbc:mysql:// 数据库IP地址:数据库端口/数据库名称 **c3.****JDBC Driver class:**下拉选项形式,这里选择com.mysql.jdbc.Driver **c4.****Username:**需要连接数据库的用户名 **c5.****Password:**需要连接数据库的密码
**d.**线程组下添加监听器-查看结果树,运行后查看实际结果。
(3)Postman a.安装nodejs 下载地址 b.安装xmysql 命令安装xmysql: npm install xmysql-g c.连接数据库 连接数据库的命令:xmysql -h localhost -u mysqlUser -p mysqlPassword -d databaseName d.获取数据库相关信息的API 调用localhost:3000获取数据库相关信息
- Json与字典dict的区别
答: 首先python里面的基础数据类型有:int、str、 float、list、bool、tuple、dict、set这几种类型,里面没json这种数据类型。 JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。 由于你的代码是python写的(也有可能是php,java,c,ruby等语言),但是后端接口是java写的(也有可能是其它语言),不同的语言数据类型是不一样的(就好比中国的语言和美国的语言数据类型也不一样,中国的一般说一只羊,一头牛,美国都是 a /an这种单位),所以就导致你提交的数据,别的开发语言无法识别,这就需要规范传输的数据(传输的数据都是一个字符串),大家都遵循一个规范,按一个标准的格式去传输,于是就有就json这种国际化规范的数据类型。 json本质上还是字符串,只是按key:value这种键值对的格式来的字符串。
Plain Text
import json
a是字典dict
a = {"a": 1, "b": 2, "c": True}
b是json
b = '{"a": 1, "b": 2, "c": true}'
print(type(a))
print(json.dumps(a)) # a转json
运行结果:
Plain Text
<class 'dict'>
{"a": 1, "b": 2, "c": true}
<class 'str'>
{'a': 1, 'b': 2, 'c': True}
字典是一种数据结构,而json是一种数据格式, 格式就会有一些形式上的限制,比如json的格式要求必须且只能使用双引号作为key或者值的边界符号(值如果是数字可以不用加双引号),不能使用单引号,用单引号或者不用引号会导致读取数据错误,而且“key”必须使用边界符(双引号),但字典就无所谓了,可以使用单引号,也可以使用双引号。 总结: json的特点 1. 字符串外边有单引号 2. json是类字典的形式,里面的键-值对规定必须使用双引号,值如果是数字可以不加双引号, 但是键必须是双引号引起来的字符串, json的值可以是普通变量,数组,json对象 缺点: json只有null、布尔、数字、字符串、数组和对象这几种数据类型,JSON没有日期类型 users = { "admin": { 'username': 'admin', "password": 123, "nickname": "老王" } } import json 以下两个函数用于json数据类型的转换 json.dumps() 字典 -> json json.loads() json -> 字典 以下两个函数用于json数据类型转换的同时操作文件 json.dump() json.load()1. 数据类型的转换其他类型转换为json字符串 json_str = json.dumps(users) print(json_str, type(json_str))读取json字符串,还原为原来的数据类型 json_obj = json.loads(json_str) print(json_obj, type(json_obj))# 2. 类型转换的同时操作文件json.dump(users, open("d2.txt", "w"))data = json.load(open("d2.txt"))print(data)
- 依赖登录的接口如何处理 (token和session管理)
答: 登录接口依赖token的,可以先登录后,token存到一个yaml或者json,或者ini的配置文件里面,后面所有的请求去拿这个数据就可以全局使用了。 如果是cookies的参数,可以用session自动关联 s=requests.session() 后面请求用s.get()和s.post()就可以自动关联cookies了
- 接口自动化中的关联怎么处理
答: 将请求返回的结果反射到类属性中,使用setattr()函数,下个请求调用这个类就行了。
- 接口自动化根据什么来做断言
答: 基本的断言方法提供了测试结果是True还是False。所有的断言方法都有一个msg参数,如果指定msg参数的值,则将该信息作为失败的错误信息返回。
序号 | 断言方法 | 断言描述 |
---|---|---|
1 | assertEqual(arg1, arg2, msg=None) | 验证arg1=arg2,不等则fail |
2 | assertNotEqual(arg1, arg2, msg=None) | 验证arg1 != arg2, 相等则fail |
3 | assertTrue(expr, msg=None) | 验证expr是true,如果为false,则fail |
4 | assertFalse(expr,msg=None) | 验证expr是false,如果为true,则fail |
5 | assertIs(arg1, arg2, msg=None) | 验证arg1、arg2是同一个对象,不是则fail |
6 | assertIsNot(arg1, arg2, msg=None) | 验证arg1、arg2不是同一个对象,是则fail |
7 | assertIsNone(expr, msg=None) | 验证expr是None,不是则fail |
8 | assertIsNotNone(expr, msg=None) | 验证expr不是None,是则fail |
9 | assertIn(arg1, arg2, msg=None) | 验证arg1是arg2的子串,不是则fail |
10 | assertNotIn(arg1, arg2, msg=None) | 验证arg1不是arg2的子串,是则fail |
11 | assertIsInstance(obj, cls, msg=None) | 验证obj是cls的实例,不是则fail |
12 | assertNotIsInstance(obj, cls, msg=None) | 验证obj不是cls的实例,是则fail |
也可以这么回复:根据状态码、实际接口返回的字段值,和数据库或redis进行比对。 更详细一点: 协议状态码: 200,404,503 2、业务状态码:status:0 3、业务数据
- 接口自动化框架是怎么做的,实现了什么功能,用了多久
答: (1)前期先进行调研:测试数据、功能模块都有哪些、报告是什么形式的 (2)介绍模块:一共分成四个模块 common:公共方法,封装了confighttp(封装了get、post方法)、封装了readconfig(读取配置)、封装了configEmail(配置邮件属性、发送邮件)、封装了readExcel(读取存放数据的表格)、封装了writeExcel(复制excel数据,写入数据) testdata:测试数据,用excel维护,数据方便维护,如果公司选择数据库维护,也可以做 testcase:测试用例,采用ddt测试框架,减少代码编写量,通过一个方法实现了全部测试用例,提高了测试代码的复用率,同时可以提高测试脚本的编写效率 report:测试报告,html (3)框架搭建多长时间:3周,边业务测试边搭建
- 在设计框架时,都遇到了哪些问题,都怎么解决的呢
答: 1、遇到了哪些问题:每次执行用例的时候都会产生很多报告,占用地方,采用循环来清理之前的报告 2、之前写的普通框架,一个用例一个case,用ddt框架实现减少case执行多条用例,缺点:依赖excel强,不能实现定制化
- 你认为你的框架有哪些优缺点,还有优化的地方吗
答: 优点:采用ddt框架,数据驱动方式,把数据写在excel表格中,代码做封装,用数据驱动测试,两部分相互独立,代码简单好维护,调试方便。 缺点优化:用例量大,效率低,建议后期优化,采用多线程,报告需要手动清理,优化后可以定时清理,增加日志log
- 什么是接口穿透测试
答: 接口穿透测试是将几个接口组合成为一个接口业务场景来进行测试。
- 在接口自动化测试中都用到了哪些包呢
答: pymysql:连接数据库 ddt: requests: urllib: xlrd: xlwt: xlutils:
- super 是干嘛用的?在 Python2 和 Python3 使用,有什么区别?为什么要使用 super?
答: super 用于继承父类的方法、属性。super 是新式类中才有的,所以 Python2 中使用时,要在类名的参数中写 Object。Python3 默认是新式类,不用写,直接可用。使用 super 可以提高代码的复用性、可维护性。修改代码时,只需修改一处。 父类: class Car(): def __init__(self,make,model,year): self.make=make self.model=model self.year=year def ..... class ElectricCar(Car): def __init__(self,make,model,year): --------初始化父类的属性 super().__init__(make,model,year): def .... 子类就可以使用父类的属性
- L = 1, 2, 3, 11, 2, 5, 3, 2, 5, 3,用一行代码得出 11, 1, 2, 3, 5
答: list(set(L))
- L = 1, 2, 3, 4, 5,L10:的结果是?
答: 空列表
- list= 1, 2, 3, 4,如何得出 '1234'?
答:
Plain Text
list=1,2,3,4
list2=''
for i in list:
代码语言:txt复制list2=list2 str(i)
print(list2)