(ROOT)测开常见题

important

测试开发备战秋招面试4_开发人员应该检验在用户提交的数据放到页面中,返回浏览器之前,是否进行了验证或者-CSDN博客

测开面试题_nuist__NJUPT的博客-CSDN博客

 网络

面试题

(SUB)测开网络-CSDN博客

3次握手4次挥手

http(发生在传输层(4)):

(sub)三次握手四次挥手-CSDN博客

https(追加ssl握手发生在会话层(5),表示层(6)):

一起学习SSL协议原理_ssl协议的原理-CSDN博客

网络模型及协议

网络模型详解_3389 time_wait-CSDN博客

 OSI七层模型各层有哪些协议

OSI模型共7层,每个层次都有其特定的功能和协议。

物理层:负责在物理媒介上传输比特流,如以太网、Wi-Fi、蓝牙等。常见的协议包括:IEEE 802.3、IEEE 802.11、Bluetooth等。

数据链路层:负责将比特流转换为数据帧进行传输,并管理物理层上的设备,如网卡、交换机等。常见的协议包括:以太网协议、ARP协议、PPP协议等。

网络层:控制分组在网络中的传输,负责寻址、路由选择、流量控制等。常见的协议包括:IP协议、ICMP协议、ARP协议等。

传输层:负责端到端的可靠传输,提供错误恢复和流量控制,如TCP和UDP。常见的协议包括:TCP协议、UDP协议等。

会话层:负责建立、管理和终止会话,提供会话控制和同步服务,如RPC(远程过程调用)。常见的协议包括:NetBIOS、NFS等。

表示层:负责数据格式转换、加密解密、压缩解压等,使得不同系统之间可以相互通信。常见的协议包括:JPEG、ASCII码等。

应用层:为用户提供网络服务和应用程序,如Web浏览器、电子邮件、文件传输协议等。常见的协议包括:HTTP协议、SMTP协议、FTP协议等。

总之,七层模型将网络通信划分为不同的层次,并在每个层次上定义了相应的功能和协议,使得网络通信变得更加可靠和高效。

常见应用层端口号

一些常见的应用层协议和传输层协议之间的关系。

HTTP默认使用TCP的80端口标识

FTP默认使用TCP的21端口标识

SMTP默认使用TCP的25端口标识

POP3默认使用TCP的110端口

HTTPS默认使用TCP的443端口

DNS使用UDP的53端口

远程桌面协议(RDP)默认使用TCP的3389端口

Telnet使用TCP的23端口

Windows访问共享资源使用TCP的445端口

常见状态码

HTTP错误码_http 417-CSDN博客

1xx: 信息性状态码,表示服务器已经接收到请求,正在处理中。

100 Continue:服务器已成功接收到消息体,并发送了一个临时响应。
101 Switching Protocols:客户端要求服务器切换协议。
2xx: 成功状态码,表示服务器已经成功处理了请求。

200 OK:请求已成功。
201 Created:请求已被成功处理,并创建了一个新的资源。
204 No Content:服务器成功处理了请求,但没有任何内容返回。
3xx: 重定向状态码,表示需要客户端进行附加操作才能完成请求。

301 Moved Permanently:请求的资源已被永久移动到新位置。
302 Found:请求的资源已被临时移动到新位置。
304 Not Modified:客户端使用缓存数据执行了条件请求。
4xx: 客户端错误状态码,表示客户端发生了错误,例如请求无效或无权访问某些资源。

400 Bad Request:请求无效,服务器无法理解该请求。
401 Unauthorized:未授权,客户端缺少凭据。
403 Forbidden:请求被拒绝,客户端没有权限访问请求的资源。
404 Not Found:请求的资源不存在。
5xx: 服务器错误状态码,表示服务器发生了错误。

500 Internal Server Error:服务器内部错误。
502 Bad Gateway:错误网关。
503 Service Unavailable:服务不可用,通常是由于服务器过载或维护。
504 Gateway Timeout:网关超时,在规定时间内未能从上游服务器接收到响应。

 测试思维

(SUB)测试思维案例-CSDN博客

测试情景

(SUB)测开情景问题-CSDN博客

 软件分类

 hash碰撞解决方法

(1)开放定址法,也称为线性探测法,就是从发生冲突的那个位置开始,按照一定的次序从hash表中找到一个空闲的位置,然后把发生冲突的元素存入到这个空闲位置中。ThreadLocal就用到了线性探测法来解决hash冲突的。python的dict

(2)链式寻址法,即拉链法,这是一种非常常见的方法,简单理解就是把存在hash冲突的key,以单向链表的方式来存储,比如HashMap就是采用链式寻址法来实现的。

(3)再hash法,就是当通过某个hash函数计算的key存在冲突时,再用另外一个hash函数对这个key做hash,一直运算直到不再产生冲突。这种方式会增加计算时间,性能影响较大。(布谷鸟过滤器

(4)建立公共溢出区, 就是把hash表分为基本表和溢出表两个部分,凡事存在冲突的元素,一律放入到溢出表中。
 

测试

测试规范化

(SUB)测试规范化-CSDN博客

测试流程

软件测试的流程一般包括以下几个阶段:

需求分析阶段:
对需求进行评审,确保需求的可测试性和完整性;确保开发产品测试对需求理解一致
测试计划阶段:
确定测试目标、测试范围和测试策略;
制定测试计划,并安排测试资源和工作进度。
设计测试阶段:

编写测试用例和测试文档,准备测试数据。
根据测试用例设计测试方案,编写测试脚本;
准备测试环境和测试工具,进行测试前的准备工作。
执行测试阶段:
根据测试计划和测试方案,执行测试用例;
记录测试结果和缺陷信息,进行缺陷管理和跟踪。
缺陷修复阶段:
开发人员根据测试结果修复缺陷,重新构建软件版本;
测试人员对修复后的软件版本再次进行测试。
测试报告阶段:
汇总测试结果和缺陷信息,生成测试报告;
向项目组和客户提供测试报告,并提出改进意见和建议。
测试闭环阶段:
对测试过程进行回顾和总结,收集测试经验;
不断优化测试过程,提高测试效率和质量。

软件测试主要包括以下步骤:

  1. 确认需求:确认并理解业务需求,明确所需要达到的软件目标和功能。
  2. 编写测试计划:根据需求编写测试计划,并定义测试策略、测试用例和测试点。
  3. 进行测试执行:使用不同的测试方法和工具进行测试,跟踪记录缺陷和问题,并向开发人员提供详细的反馈。
  4. 分析测试结果:分析测试结果,评估软件产品的可靠性、稳定性和质量,以及隐含的风险。
  5. 提交测试报告:根据测试结果撰写测试报告,向项目经理或客户汇报测试结果和建议。

总之,软件测试是一个重要的环节,可以有效地降低软件产品的风险和错误,提高整个软件开发项目的成功率和用户满意度。

测试目的:质量保障

软件测试是一个确保软件产品质量的过程。它是在软件开发完成后,对软件产品进行验证、确认和评估其功能、性能、安全性等各方面是否符合要求的一系列活动。软件测试可以帮助发现潜在问题,减少缺陷和错误数量,提高软件质量,从而增加用户体验和信任度。

软件测试的目的:

测试是程序的执行过程,目的在于发现错误

一个成功的测试用例在于发现至今未发现的错误

一个成功的测试是发现了至今未发现的错误的测试

确保产品完成了它所承诺或公布的功能,并且用户可以访问到的功能都有明确的书面说明。

确保产品满足性能和效率的要求

确保产品是健壮的和适应用户环境的

质量保障应该如何理解?我们可以从软件质量保障和交付生命周期的三个阶段来做不同的定义。

需求设计的质量

我们谈软件质量,不可避免要从它的源头说起,而源头就是需求和设计阶段要做的事情。这个阶段包括原型图、PRD文档、交互设计、技术方案、测试用例等几项重要产出物,当然他们有一定的前后依赖关系。

在需求设计阶段,我个人认为比较重要的有如下几点:

  1. 需求评审(是否有遗漏、描述不清、存在逻辑漏洞等);
  2. 设计评审(设计是否满足需求要求、是否合理美观友好);
  3. 方案评审(方案实现难易程度、可测性、是否需要更多资源);
  4. 用例评审(场景是否尽可能覆盖、和技术方案实现是否吻合);

为什么要做大量评审工作?因为如果源头存在问题,那么研发过程和用户使用质量就无从谈起,方向错了就全错了。

评审的价值在于从用户使用场景角度出发,通过评审提问,把需求逐步澄清并形成验收条件,产、研、测三方共同确认,形成共识,以保证大家对需求的认知不发生偏差,为后续团队正确的做事提供有价值的指导。

研发过程质量

软件质量是构建出来的,不是测试出来的”。

测试的本质是验证研发交付的产出物是否达到需求设计及预期的标准。并不能直接带来质量的提升,只能通过种种手段多维度的去验证是否达标,并通过流程规范、度量标准等去保障最终的交付物达标。

因此,我们常说的各种测试技术手段,都是验证和保障交付质量的手段,而不是构建质量的手段。

当然,开发有自己的一套体系,比如编码规范、单元测试覆盖率等,这里不做详细描述,我们重点关注测试维度。

用户使用质量

用户使用质量,指的是软件线上发布后,我们对用户使用过程进行追踪并采集数据进行评估度量的过程

软件工程是将软件研发过程进行科学管理以控制质量,通过流水线的形式进行交付上线。

而软件测试则是通过一系列手段来验证最终的交付产出物是否达到预期的质量标准。

测试原则

测试用例中一个必须部分是对预期输出或接过进行定义

编写软件的组织不应当测试自己编写的软件

应当彻底检查每个测试的执行结果

测试用例的编写不仅考虑功能还要考虑异常

应避免测试用例用后即弃,除非软件本身就是个一次性的软件

计划测试工作时不应默许假定不会发现错误

程序某部分存在更多错误的可能性,与该部分已经发现错误的数量成正比

一、测试证明软件存在缺陷-Testing shows presence of defects

  • 测试只能证明软件中存在缺陷,但并不能证明软件中不存在缺陷。
  • 软件测试是为了降低存在缺陷的可能性,即便是没有找到缺陷,也不能证明软件是完美的。

二、穷尽测试是不可能的-Exhaustive testing is impossible

  • 穷尽测试是不可能的。如计算器的加法-功能的测试。
  • 现在软件的规模越来越大,复杂度越来越高,想做到完全性的测试是不可能的。在测试阶段,测试人员可以根据风险和优先级来进行集中测试,从而保证软件的质量。

三、测试尽早介入-Testing early

  • 为什么测试要尽早介入呢,简单的说就是保证软件质量,降低风险和成本。
  • 测试人员一般在需求阶段就开始介入,使缺陷在需求或设计阶段就被发现,缺陷发现越早,修复的成本就越小。

四、缺陷集群性(2/8 原则)-Defect clustering

  • 这个也是经验之谈了,一般认为,百分之 80 的缺陷集中出现在百分之 20 的核心功能区域。一旦你在某个功能模块找到缺陷,相关附近功能多半也会存在问题。
  • 项目实战中,在写缺陷报告的时候,做横向对比,比对类似功能,相近模块,版本,机型。指定回归测试策略的时候,也可以重点测试。

五、杀虫剂悖论杀虫剂效应)-Pesticide Paradox

  • 反复使用相同的杀虫剂会导致害虫对杀虫剂产生免疫而无法杀死害虫。软件测试也一样。如果一直使用相同的测试方法或手段,可能无法发现新的 bug。
  • 为了解决这个问题,测试用例应当定期修订和评审,增加新的或不同的测试用例帮助发现更多的缺陷。 测试人员不能一直依赖于现有的测试技术,而要不断的提升测试方法以提高测试效率。

六、测试活动依赖于测试内容-Testing is context dependent

  • 根据业务的不同,软件测试内部也分为不同的行业,比如游戏行业、电商行业、金融行业。不同的行业,测试活动的开展都有所不同,比如测试技术测试工具的选择,测试流程都不尽相同,所以软件测试的活动开展依赖于所测试的内容。
  • 比如:你在金融公司测试,安全性就是第一位。电子商务测试,功能性则更加重要。

七、不存在缺陷的谬论-Absence of error

  • 软件测试不仅仅是为了找出 Bug 而存在的活动,而是还需要确认软件是否满足用户的期望和需求,如果产品不能满足用户的需求,即使没有出现任何缺陷,这个产品也是失败的。
  • “没有错误” 并不是我们的追求,在互联网时代,始终快速给用户创造最大的价值才是我们孜孜不倦的追求。

你是怎么理解软件测试的? - 知乎 (zhihu.com)

测试用例作用

一个测试老兵眼里的测试用例-CSDN博客

 1.完成需求拆分

2.测试执行依据

3 让产品、开发、设计等人员分别站在自己的角度评估下,测试覆盖是否全面。

4. 完成需求再次确认。这样的一个确认过程,也起到了产品设计到技术设计的桥梁作用,因为通常技术设计不会写这么细致。而产品可通过测试用例了解测试人员理解是否正确,开发可通过测试用例回顾下自己的设计/编码是否与测试用例一致。

测试用例除了上面分析提到的作用外,通常我们还会提取部分冒烟用例给开发人员做提测前的自测、给业务人员/第三方进行验收测试;同时测试用例作为测试最主要的交付文档,需进行整理归档,以备后续迭代复用。

设计测试用例需要注意和考虑哪些

1、复用率,随产品不断升级,需要涉及更详细些,可一劳永逸;如仅使用一两次,没必要写的太仔细。

2、项目进度,时间允许可详尽,时间紧可执行即可。

3、使用对象,如果供多人使用,尤其让后参加测试的工程师来执行,则需要设计的更加详细些。

4、关注有效功能,大多数情况:我们不太可能在一个测试用例包含全部测试要求,因为众多的功能及不同的路径组合将使测试用例步骤繁多,操作复杂,或者完全不具可操作性。说这些并不是意味为需求中定义的每个功能和特性,编写一个或多个测试用例,只要把握好适度即可。

  如何区分有效功能:

  第一点,这个功能是可以还原到用户原始的手工业务流程中去的。

  第二点,这个功能是否标志用户实际业务的一个阶段性结束,并且这项业务完成后,被完成的业务实体是否可以交付给其他用户或业务供完成下面的工作?

5、做好需求分析,这里的需求包含显示和隐式需求,根据需求文档将不同需求来源划分成一个个需求点,针对每小点进行测试分析,界定测试范围,并运用多种测试用例设计方法产生测试节点。

6、注重测试用例评审,评审会以检验功能是否覆盖完全,评审会成员有设计,开发,测试及专家成员。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/nuist_NJUPT/article/details/129677355

测试用例包含哪些内容

1、用例编号:相当于一个人的身份证号、一个用例也有一个英里编号
2、用例名称:也就是一个人的名字,每一个都有一个名字,用例也有一个自己的名字
3、测试背景:就是测试环境背景,说明什么项目,测什么,在什么情况背景下去测
4、优先级:根据自己安排来确定哪一个优先
5、重要级:根据事情的重要程度来确定,和优先级有一点差别
6、测试数据:测试的参数数据
7、测试步骤:也就是测试的一个过程我
8、预期结果:想象的一个可能达到的结果
9、实际结果:实际测试过程出现的最终结果
10、备注:强调特殊情况内容
11、前置条件:测试的前提条件,比如你要测一个登陆界面,你要有一个已注册的账号密码,这才能测

设计测试用例/测试方法

设计测试用例需要考虑以下几个方面:

测试目标与需求分析:
理解产品、项目和客户需求,明确待测软件的功能、性能和安全等要求;
确定测试目标和测试范围,制定测试计划。
测试设计技巧:
了解常用的测试设计技巧,如等价类划分法、边界值分析法、因果图法、决策表法等;
根据具体情况选择合适的测试设计技巧。
编写测试用例:
设定测试条件和测试数据,包括输入数据、预期输出结果和测试步骤等;
编写测试用例时应尽量覆盖各种典型和异常情况,以发现潜在缺陷。
评审和修改:
在编写测试用例后,进行评审和修改,保证测试用例质量和覆盖率;
确认每个测试用例都是可执行的、准确的和完整的。
执行和管理:
根据测试计划和测试用例进行测试;
记录测试结果和缺陷信息,进行缺陷管理和跟踪。

白盒测试方法

语句覆盖、条件覆盖、判定覆盖、条件-判定覆盖、组合覆盖、路径覆盖-CSDN博客

黑盒测试

(SUB)黑盒测试方法-CSDN博客

黑盒测试分为功能测试和性能测试:

1)功能测试(function testing),是黑盒测试的一方面,它检查实际软件的功能是否符合用户的需求。

包括逻辑功能测试(logic function testing)

界面测试(UI testing)UI=User Interface

易用性测试(usability testing):是指从软件使用的合理性和方便性等角度对软件系统进行检查,来发现软件中不方便用户使用的地方。

兼容性测试(compatibility testing):包括硬件兼容性测试和软件兼容性测试

2)性能测试(performance testing)

软件的性能主要有时间性能和空间性能两种

时间性能:主要指软件的一个具体事务的响应时间(respond time)。

空间性能:主要指软件运行时所消耗的系统资源。

软件性能测试分为:

一般性能测试:指的是让被测系统在正常的软硬件环境下运行,不向其施加任何压力的性能测试。

稳定性测试也叫可靠性测试(reliability testing):是指连续运行被测系统检查系统运行时的稳定程度。

负载测试(load testing):是指让被测系统在其能忍受的压力的极限范围之内连续运行,来测试系统的稳定性。

压力测试(stress testing):是指持续不断的给被测系统增加压力,直到将被测系统压垮为止,用来测试系统所能承受的最大压力。(Validate the system or software can allowed the biggest stress.)

其它测试:回归测试(regression testing)是指对软件的新的版本测试时,重复执行上一个版本测试时的用例。

测试计划与测试方案(删除线的就是方案)

测试计划包含以下内容:

测试目标和范围:明确测试的目的和范围。包括测试的系统、模块、功能和特性等。

测试策略:确定测试策略,包括测试类型、测试方法、测试环境、测试用例的编写和管理等

测试计划:制定测试计划,包括测试的时间、资源、进度、人员安排等。

测试任务分配:明确测试人员的工作任务,包括测试负责人、测试执行者、测试设计人员等。

测试风险分析:分析测试中可能出现的风险,并制定相应的风险应对计划。

测试数据和工具:确定测试所需的数据和工具,包括测试数据准备和测试工具的选择和使用

测试报告和评审:制定测试报告和评审计划,包括测试结果的汇报和评审过程的安排。

测试质量标准:制定测试质量标准,包括测试通过的条件、测试结果的可靠性等。

测试验收准则:确定测试验收准则,用于判断测试是否达到预期目标、需求是否得到满足、系统是否符合要求等。

测试结束和总结:制定测试结束和总结计划,包括测试结果的总结、问题的回顾、经验的总结等。

测试策略

性能测试常用指标

老鸟总结,性能测试-常用指标/指标评估及/通过标准(超级细) - 知乎 (zhihu.com)

外部看:

1. 并发量(RequestPerSecond):

这个指标反应压测过程中是否模拟出指定压力

模拟海量用户使用最大能同时多少人使用

模拟同时在线(测试session会话,服务器存储)

模拟同时操作(并发请求, 双十一淘宝排队付款)

——系统能支撑并发量越高越好

同时如何定义:以s为单位主流

2. 响应时间(ResponseTime):

服务处理一个请求或一个任务的耗时

用户体验角度

定义:一个用户从请求开始到收到服务器响应时间

3. 吞吐量(TansactionsPerSecond,QueryPerSecond):

每秒钟系统能够处理的请求数,任务数

eg:每秒30人请求处理了20个,30:并发量,20:吞吐量TPS

什么是TPS:事务操作,后端或前端多个操作,作为一个整体

单个请求角度:用户操作伴随数据变更(下单),后端需要多处理步骤形成事务

多个请求角度:比如首页访问会触发多个接口,系统每秒能处理多少次首页访问请求

什么是QPS:

用户查询数据,比如打开商品页面

3. 错误率:

一批请求中结果出错的请求所占比例,表示系统在高压力情况下,用户请求能否正确处理

——错误率越高代表系统在高并发下越不稳定

从服务器角度看:

4. 资源占用率:CPU,内存,服务器负载,网络,磁盘IO

top命令

——同样功能保证功能正常使用,资源占用率越低性能越好

如何对登录功能做性能测试

单用户登陆的响应界面是否符合预期

单用户登陆时后台请求数量是否过多

高并发场景下用户登录的响应界面是否符合预期

高并发场景下服务端的监控指标是否符合预期

高集合点并发场景下是否存在资源死锁和不合理的资源等待

长时间大量用户连续登录和登出,服务器端是否存在内存泄漏

 中断测试

测试如何模拟404、断网、断电、找不到网页的情况?

大厂测试面试题含答案_如何模拟404/断网-CSDN博客
模拟404:在测试环境中,可以修改请求的URL地址,将其修改为不存在的地址,从而模拟404错误。

模拟断网:可以使用网络模拟工具,如Network Link Conditioner(Mac)或Clumsy(Windows),来模拟网络连接不稳定或断开的情况。

模拟断电:可以使用硬件模拟器,如Chaos Monkey,来模拟服务器宕机或断电的情况。

模拟找不到网页:可以在测试环境中删除或移动网页文件,从而模拟找不到网页的情况。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/weixin_50829653/article/details/133924897

中断测试-CSDN博客

mock测试

Mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。

1. 解决依赖问题:当我们测试一个接口或者功能模块的时候,如果这个接口或者功能模块依赖其他接口或其他模块,那么如果所依赖的接口或功能模块未开发完毕,那么我们就可以使用mock模拟被依赖接口,完成目标接口的测试

2. 单元测试:如果某个功能未开发完成,我们又要进行测试用例的代码编写,我们也可以先模拟这个功能进行测试

3. 模拟复杂业务的接口:实际工作中如果我们在测试一个接口功能时,如果这个接口依赖一个非常复杂的接口业务,那么我们完全可以使用mock来模拟这个复杂的业务接口,其实这个和解决接口依赖是一样的原理

4.前后端联调:如果你是一个前端页面开发,现在需要开发一个功能:根据后台返回的状态展示不同的页面,那么你就需要调用后台的接口,但是后台接口还未开发完成,是不是你就停止这部分工作呢?答案是否定的,你完全可以借助mock来模拟后台这个接口返回你想要的数据
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/nuist_NJUPT/article/details/129676208

接口测试

首先获取接口规范、接口文档、需求文档,设计接口测试功能用例,用例设计要考虑单接口和多接口业务流程。

单接口主要进行接口的正确性和健壮性验证,要考虑各种入参验证(正常情况、异常情况,包括输入参数个数不对,类型不对,可选/必选,还要考虑参数互斥或关联的情况)、接口返回值各种验证(符合接口文档需求)。

多接口业务流程测试主要关注业务流和数据流,也就是多个接口的串联操作能否满足需求文档里的需求。

接口测试就是通过接口的不同情况下的输入和与之对用的输出之间的关系,看看是否满足接口规范所规定的功能性、安全性以及性能方面的要求.

最知名的就是postman,当然还有restclient之类的 。当然也可以用jmeter,jmeter也可以用来做接口性能测试,当然我们也可以通过编写脚本(代码)进行接口测试。

接口测试要遵循一些要点:

是否有依赖业务,比如查看订单,需要用户登录

逻辑业务测试:传递正确的参数,接口对数据库进行查询操作,需要去验证数据库查询是否正确,接口对数据库进行增删改操作也需要验证数据库是否同步了这些操作。

测试接口的功能实现. 检查不同参数的数据请求时,接口返回的数据与预期结果也就是接口文档的规范的一致性.
测试接口的健壮性(容错性), 比如说传递的数据类型是错误或者传递空数据,特殊字符等与接口规范不符的能否正常处理.
测试接口参数的边界值. 比如说传递的数据超出了接口规范的规定的范围,或者数据足够大或者为负数时能否正常处理
测试接口的性能, 接口处理和响应数据的时间,并发性等等, 当然这牵扯到代码实现的优化,需要与开发人员沟通
测试接口的安全性.比如登录的用户名密码等敏感数据是否明文显示,需要权限的接口是否暴露在外面

bug包含哪些内容

(SUB)bug包含哪些内容-CSDN博客

 APP测试

APP与web测试流程类似

分为如下七个阶段:

根据需求说明书编写测试计划;
制定测试方案,主要是测试任务、测试人员和测试时间的分配;
测试准备,包括搭建测试环境,准备测试数据,确定测试方法;
测试用例的设计与编写,进行用例评审及补充完善;
执行测试时首先进行冒烟测试,然后对主功能流程进行测试,包括客户端的单个功能模块,及功能业务逻辑功能交互,回归测试;
提交测试结果,包括测试用例,测试计划;
日常维护性测试;

App与web测试比增加复杂性

  • 操作系统: 大量的设备,各种操作系统,目前使用最多的操作系统有:Android、iOS、windows、blackberry等等,它们之间的应用软件互不兼容。
  • 设备:触摸式和非触摸式设备、有限的内存容量,电池耗电量,屏幕尺寸、分辨率等。
  • 网络:不同的网络和运营商,目前我国的三大运营商就有电信、联通和移动,不同的网络制式,如GSM、CDMA、3G等,在不好或无网络的情况下的App行为。
  • 可用性:方向,触摸,缩放,分页和导航的局限性,各种干扰,如来电,来电短信,闹钟,和低电量警报等。

思维导图如下:

手机APP测试

主要包括功能、性能测试、稳定性、兼容性、用户测试。

兼容性测试:屏幕分辨率 /网络状态,状态切换 /android版本 /安装卸载升级等 /权限设置 /与其他APP兼容性 (①安装卸载测试:测试App在指定终端上是否可正常安装、正常卸载,准确定位错误原因。②遍历测试:自动识别App可执行的功能,在一定时间内遍历App的不同功能界面,通过截图记录操作路径 并输出日志、定位异常现象。③运行稳定性测试:类似Monkey的随机性压力测试,测试App运行期的稳定性。④UI适配测试:测试App的UI与目标终端的屏幕是否适配,记录是否存在渲染失败、错位、黑边框、黑白屏等现象。)

稳定性测试包括:服务器异常时稳定性 /外部事件影响(电话,短信等) /内存是否有溢出或者泄漏 /多线程问题 。

性能测试:CPU占用/内存占用 /耗电测试 /流量消耗测试 /安装包大小 /加载时间测试 /核心功能相应时间 (①启动时间检测:检测App在终端上首次启动时间。②内存、CPU耗用检测:检测App在终端上运行时不同时段占用内存、CPU情况。③流量耗用检测:检测App在终端上运行时的网络流量消耗情况。④电池温度检测:检测App在终端上运行时,对终端的电池温度等性能指标的影响情况 )

手机app性能测试

(SUB)app性能测试-CSDN博客

APP原生开发、H5开发和混合开发的区别?


1、原生开发

原生开发(Native App开发), 利用官方提供的开发语言、开发类库、开发工具进行App开发。比如Android是利用Java;IOS是利用Objective-C进行开发。

原生开发优点:

运行速度快、性能高,绝佳的用户体验;
支持大量图形和动画,不卡顿,反应快;
兼容性高,每个代码都经过程序员精心设计,一般不会出现闪退的情况,还能防止病毒和漏洞的出现;
比较快捷地使用设备端提供的接口,处理速度上有优势。
原生开发缺点:

开发时间长;
制作费用高昂,成本较高;
可移植性比较差,一款原生的App,Android和IOS都要各自开发,同样的逻辑、界面要写两套;
必须等下载完毕用户才可以打开,获得新版本时需重新下载应用更新。

2、H5开发

HTML5应用开发,是利用Web技术进行的App开发,可以在手机端浏览器里面打开的网站就称之为webapp。Web技术本身需要浏览器的支持才能进行展示和用户交互,因此主要用到的技术是HTML、CSS、Javascript以及jQuery、Vue、React等JS框架。

H5开发优点:

支持设备范围广,可以跨平台,编写的代码可以同时在Android、IOS、Windows上运行;
开发成本低、周期短;
适合展示有大段文字(如新闻、攻略等),且格式比较丰富(如加粗,字体多样)的页面;
用户可以直接使用最新版本(自动更新,不需用户手动更新)。
H5开发缺点:

由于Web技术本身的限制,H5移动应用不能直接访问设备硬件和离线存储,所以在体验和性能上有很大的局限性;
对联网要求高,离线不能做任何操作;
APP反应速度慢,页面切换流畅性较差;
图片和动画支持性不高;
用户体验感较差。
3、混合开发

混合开发(Hybrid App开发),是指在开发一款App产品的时候,为了提高效率、节省成本而利用原生与H5的开发技术的混合应用。通俗点来说,这就是网页的模式,通常由“HTML5云网站+APP应用客户端”两部份构成。

混合开发优点:

开发效率高,节约时间。同一套代码Android和IOS基本上都可使用;
更新和部署比较方便,每次升级版本只需要在服务器端升级即可,不再需要上传到App Store进行审核;
代码维护方便、版本更新快,节省产品成本;
比web版实现功能多;
可离线运行。
混合开发缺点:

功能/界面无法自定:所有内容都是固定的,不能换界面或增加功能;
加载缓慢/网络要求高:混合APP数据需要全部从服务器调取,每个页面都需要重新下载,因此打开速度慢,网络占用高,缓冲时间长,容易让用户反感;
安全性比较低:代码都是以前的老代码,不能很好地兼容最新手机系统,且安全性较低,网络发展这么快,病毒这么多,如果不实时更新,定期检查,容易产生漏洞,造成直接经济损失。

python

常用包

Logger

import logging
from logging import handlers


class Logger(object):
    level_relations = {
        'debug': logging.DEBUG,
        'info': logging.INFO,
        'warning': logging.WARNING,
        'error': logging.ERROR,
        'crit': logging.CRITICAL
    }  # 日志级别关系映射

    def __init__(self, filename, level='info', when='D', backCount=3,
                 fmt='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'):
        self.logger = logging.getLogger(filename)
        format_str = logging.Formatter(fmt)  # 设置日志格式
        self.logger.setLevel(self.level_relations.get(level))  # 设置日志级别
        sh = logging.StreamHandler()  # 控制台输出
        sh.setFormatter(format_str)  # 控制台显示的格式
        th = handlers.TimedRotatingFileHandler(filename=filename, when=when, backupCount=backCount, encoding='utf-8')
        # 文件输出处理器
        # when是间隔的时间单位,单位有以下几种:
        # S 秒
        # M 分
        # H 小时、
        # D 天、
        # W 每星期(interval==0时代表星期一)
        # midnight 每天凌晨
        th.setFormatter(format_str)
        self.logger.addHandler(sh)
        self.logger.addHandler(th)
json 
pytest
from pathlib import Path:Path(cur_path).resolve().parent
time:time.sleep(3)
sys:sys.path.append(os.getenv("_NET_TEST_DIR"))
zipfile:zip_list = zipfile.ZipFile(zfile);zip_list.namelist():  # 得到压缩包里所有文件zip_list.extract(f, path)  # 循环解压文件到指定目录
os:os.chmod;os.path.isfile(filePath);os.remove(filePath);os.path.exists;os.listdir(dir1);os.chdir
subprocess:subprocess.run(cmd);subprocess.getstatusoutput(cmd)
  1. 在Python 3.5之后的版本中,官方文档中提倡通过subprocess.run()函数替代其他函数来使用subproccess模块的功能;
  2. 在Python 3.5之前的版本中,我们可以通过subprocess.call(),subprocess.getoutput()等上面列出的其他函数来使用subprocess模块的功能;
  3. subprocess.run()、subprocess.call()、subprocess.check_call()和subprocess.check_output()都是通过对subprocess.Popen的封装来实现的高级函数,因此如果我们需要更复杂功能时,可以通过subprocess.Popen来完成。
  4. subprocess.getoutput()和subprocess.getstatusoutput()函数是来自Python 2.x的commands模块的两个遗留函数。它们隐式的调用系统shell,并且不保证其他函数所具有的安全性和异常处理的一致性。另外,它们从Python 3.3.4开始才支持Windows平台。
requests
stat:os.chmod(path, stat.S_IWRITE):
以下旗标还可以 os.chmod() 的在 mode 参数中使用:

stat.S_ISUID
设置 UID 位。

stat.S_ISGID
设置分组 ID 位。 这个位有几种特殊用途。 对于目录它表示该目录将使用 BSD 语义:在其中创建的文件将从目录继承其分组 ID,而不是从创建进程的有效分组 ID 继承,并且在其中创建的目录也将设置 S_ISGID 位。 对于没有设置分组执行位 (S_IXGRP) 的文件,设置分组 ID 位表示强制性文件/记录锁定 (另请参见 S_ENFMT)。

stat.S_ISVTX
固定位。 当对目录设置该位时则意味着此目录中的文件只能由文件所有者、目录所有者或特权进程来重命名或删除。

stat.S_IRWXU
文件所有者权限的掩码。

stat.S_IRUSR
所有者具有读取权限。

stat.S_IWUSR
所有者具有写入权限。

stat.S_IXUSR
所有者具有执行权限。

stat.S_IRWXG
组权限的掩码。

stat.S_IRGRP
组具有读取权限。

stat.S_IWGRP
组具有写入权限。

stat.S_IXGRP
组具有执行权限。

stat.S_IRWXO
其他人(不在组中)的权限掩码。

stat.S_IROTH
其他人具有读取权限。

stat.S_IWOTH
其他人具有写入权限。

stat.S_IXOTH
其他人具有执行权限。

stat.S_ENFMT
System V 执行文件锁定。 此旗标是与 S_ISGID 共享的:文件/记录锁定会针对未设置分组执行位 (S_IXGRP) 的文件强制执行。

stat.S_IREAD
Unix V7 中 S_IRUSR 的同义词。

stat.S_IWRITE
Unix V7 中 S_IWUSR 的同义词。

stat.S_IEXEC¶
Unix V7 中 S_IXUSR 的同义词。
shutil:shutil.rmtree(filePath, ignore_errors=False, οnerrοr=self.remove_readonly);shutil.copyfile(file1, file2)
pandas
    case_menu = case_category.split("-")
    conf = os.path.join(os.path.dirname(os.path.abspath(__file__)), conf_loc, "case_list.xlsx")
    df = pd.read_excel(conf, sheet_name=0, header=0)
    labels = df.columns.values.tolist()
    menu_len = labels.index("TestCase")
    case_index = labels.index("TestCase")
    all_data = df.loc[:, :].values
    rows, cols = all_data.shape
    start_row = 0
    end_row = start_row
    cur_row = start_row
    runcase_menu_len = len(case_menu)
    for cur_col in range(menu_len):
        while cur_col < runcase_menu_len and all_data[cur_row][cur_col] != case_menu[cur_col]:

python的内存池机制

python内存管理机制 python的内存管理_mob6454cc6c1f4a的技术博客_51CTO博客

 数组与列表

数组:numpy中的概念:大小固定,数据类型一致

列表:大小动态,数据类型可不同

元组:大小固定,数据类型可不同

谈谈Python中列表、元组和数组的区别和骚操作 - 知乎 (zhihu.com)

Python数组和列表的区别 - Python基础教程 (python51.com)

深度解密 Python 列表的实现原理-CSDN博客

Python元组的底层实现机制是什么?Python元组是怎么实现的 - 优草派

Python常见数据结构底层实现 - 知乎 (zhihu.com)

 面向对象与面向过程

面向对象与面向过程的区别 - xing柠檬 - 博客园 (cnblogs.com)

python反射

python反射的四个方法

hasattr() 判断对象是否含有字符串对应的数据或者功能

getattr() 根据字符串获取对应的变量名或者函数名

setattr() 根据字符串给对象设置数据 (名称空间的名字)

delattr() 根据字符串删除对象对应的数据 (名称空间中的名字)

【测试开发】python系列教程:python反射_python 反射-CSDN博客

python数据结构

Python的常见数据结构 - 知乎 (zhihu.com)

列表extend添加元素:python的extend函数详解_python extend-CSDN博客 

备注:

::-1

b = a[i:j:s]这种格式呢,i,j与上面的一样,但s表示步进,缺省为1.
所以a[i:j:1]相当于a[i:j]
当s<0时,i缺省时,默认为-1. j缺省时,默认为-len(a)-1
所以a[::-1]相当于 a[-1:-len(a)-1:-1],也就是从最后一个元素到第一个元素复制一遍。

dict如何解决hash冲突

开放寻址法

从CPython源码理解:Python字典如何解决哈希冲突? - 知乎 (zhihu.com)

装饰器

Python 中的装饰器本质上是一个函数或类

类装饰器就是使用类来实现的装饰器。
它们通常通过在类中定义 __call__ 方法来实现。
当我们使用 @ 语法应用装饰器时,
Python 会调用装饰器类的 __init__ 方法创建一个实例,
然后将被装饰的函数或类作为参数传递给 __init__ 方法。
当被装饰的函数或方法被调用时,
Python 会调用装饰器实例的 __call__ 方法。

下面是一个基本的类装饰器的例子:

class MyDecorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("Before call")
        result = self.func(*args, **kwargs)
        print("After call")
        return result

@MyDecorator
def hello():
    print("Hello, world!")

hello()
如果是函数装饰器,
函数的第一个参数通常是被修饰的函数对象(可以带有其他参数),
并返回一个新的函数。
装饰器函数可以在内部包含额外的逻辑和功能。
def decorator(func):
    def wrapper(*args, **kwargs):
        print("执行装饰器逻辑")
        result = func(*args, **kwargs)  # 调用原函数
        result1 = result + ',I am a decorateor'
        return result1
    return wrapper

# 应用装饰器到函数
@decorator
def greet(name):
    return f"Hello, {name}!"

# 使用被装饰的函数
message = greet("Alice")
print(message)

修饰类

def decorator(aClass):
    class newClass:
        def __init__(self, age):
            self.total_display = 0
            self.wrapped = aClass(age)

        def displayA(self):
            self.total_display += 1
            print("total display", self.total_display)
            self.wrapped.displayC()

    return newClass


def decorator2(aClass):
    class newClass:
        def __init__(self, age):
            self.total_display = 0
            self.wrapped = aClass(age)

        def displayB(self):
            self.total_display += 1
            print("total display2", self.total_display)
            self.wrapped.displayA()

    return newClass


@decorator2
@decorator
class Bird:
    def __init__(self, age):
        self.age = age

    def displayC(self):
        print("My age is", self.age)


eagleLord = Bird(5)
eagleLord.displayB()

GIL锁

什么是Python全局锁(GIL),如何避开GIL限制?_python gil锁-CSDN博客

is和==

is比较的是两个对象的id值是否相等,也就是比较两个对象是否为同一个实例对象,是否指向同一个内存地址。

==比较的是两个对象的内容是否相等,默认会调用对象的__eq__()方法。

new和init

1. __new__是构造方法,__init__是初始化函数。
2.__new__通常不需要手动定义,一般在元类编程中使用,控制类的生成过程。
3.__new__第一个被执行,然后执行__init__绑定实例变量。
4.__new__必须有返回值,返回值是该类的实例,它会被__init__函数接收,通常叫做self变量

循环打印123

import threading
import time

red_lock = threading.Lock()      # 红灯锁
yellow_lock = threading.Lock()   # 黄灯锁
green_lock = threading.Lock()    # 绿灯锁

count = 18   # 为避免一直循环,我们在这里假设每个数字输出6次,3×6=18

def red():
	"""红灯显示函数"""
	global count
	while count >= 0:
		red_lock.acquire()      # 将红灯的锁给锁住
		print(1, end = '-')     # 将红灯表示为1
		# print('id:', threading.get_ident())  # 查看线程id
		yellow_lock.release()   # 下一个为黄灯亮,将黄灯的锁给释放
		count -= 1

def yellow():
	"""黄灯显示函数"""
	global count
	while count >= 0:
		yellow_lock.acquire()   # 将黄灯的锁给锁住
		print(2, end = '-')     # 将黄灯表示为2
		# print('id:', threading.get_ident())
		green_lock.release()    # 下一个为绿灯亮,将绿灯的锁给释放
		count -= 1
	
def green():
	"""绿灯显示函数"""
	global count
	while count >= 0:
		green_lock.acquire()    # 将绿灯的锁给锁住
		print(3, end = '-')     # 将绿灯表示为2
		# print('id:', threading.get_ident())
		red_lock.release()      # 下一个为红灯亮,将红灯的锁给释放
		count -= 1

if __name__ == '__main__':
	thread_list = []
	
	func_list = [red, yellow, green]
	for func in func_list:      # 创建三个线程
		th = threading.Thread(target = func)
		thread_list.append(th)

	# 红灯先亮,因此将黄灯和绿灯的锁给锁住,以阻塞线程2和3的执行
	yellow_lock.acquire()   # 2上锁
	green_lock.acquire()   # 3上锁

	for th in thread_list:
		# print(time.time())  # 用于判断启动时间
		th.start()

	for th in thread_list:
		th.join()

数据库

数据分析面试【二】—— SQL复杂语句查询_面试复杂的sql查询语句-CSDN博客

 Mysql总结-CSDN博客

表架构如下:
Student(S#,Sname,Sage,Ssex) 学生表
Course(C#,Cname,T#) 课程表
SC(S#,C#,score) 成绩表
Teacher(T#,Tname) 教师表

1、查询“001”课程比“002”课程成绩高的所有学生的学号; 
  select a.S# from (select s#,score from SC where C#='001') a,(select s#,score 
  from SC where C#='002') b 
  where a.score>b.score and a.s#=b.s#; 
2、查询平均成绩大于60分的同学的学号和平均成绩; 
    select S#,avg(score) 
    from sc 
    group by S# having avg(score) >60; 
3、查询所有同学的学号、姓名、选课数、总成绩; 
  select Student.S#,Student.Sname,count(SC.C#),sum(score) 
  from Student left Outer join SC on Student.S#=SC.S# 
  group by Student.S#,Sname 
4、查询姓“李”的老师的个数; 
  select count(distinct(Tname)) 
  from Teacher 
  where Tname like '李%'; 
5、查询没学过“叶平”老师课的同学的学号、姓名; 
    select Student.S#,Student.Sname 
    from Student  
    where S# not in (select distinct( SC.S#) from SC,Course,Teacher where  SC.C#=Course.C# and Teacher.T#=Course.T# and Teacher.Tname='叶平'); 
6、查询学过“001”并且也学过编号“002”课程的同学的学号、姓名; 
  select Student.S#,Student.Sname from Student,SC where Student.S#=SC.S# and SC.C#='001'and exists( Select * from SC as SC_2 where SC_2.S#=SC.S# and SC_2.C#='002'); 
7、查询学过“叶平”老师所教的所有课的同学的学号、姓名; 
  select S#,Sname 
  from Student 
  where S# in (select S# from SC ,Course ,Teacher where SC.C#=Course.C# and Teacher.T#=Course.T# and Teacher.Tname='叶平' group by S# having count(SC.C#)=(select count(C#) from Course,Teacher  where Teacher.T#=Course.T# and Tname='叶平')); 
8、查询课程编号“002”的成绩比课程编号“001”课程低的所有同学的学号、姓名; 
  Select S#,Sname from (select Student.S#,Student.Sname,score ,(select score from SC SC_2 where SC_2.S#=Student.S# and SC_2.C#='002') score2 
  from Student,SC where Student.S#=SC.S# and C#='001') S_2 where score2 <score; 
9、查询所有课程成绩小于60分的同学的学号、姓名; 
  select S#,Sname 
  from Student 
  where S# not in (select S.S# from Student AS S,SC where S.S#=SC.S# and score>60); 
10、查询没有学全所有课的同学的学号、姓名; 
    select Student.S#,Student.Sname 
    from Student,SC 
    where Student.S#=SC.S# group by  Student.S#,Student.Sname having count(C#) <(select count(C#) from Course); 

什么是聚簇索引、什么是非聚簇索引?

聚簇索引(Clustered Index)和非聚簇索引(Non-clustered Index)是关系型数据库中常见的两种索引类型。

聚簇索引:将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据。

非聚簇索引:将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置。

聚簇索引是物理有序的;非聚簇索引是逻辑有序,物理无序,在mysql中数据存储顺序就是聚簇索引的顺序,所以一个表只有一个聚簇索引,其他索引都是非聚簇的。

 非聚簇索引的叶子结点存储的是索引列的值,它的数据域是聚簇索引即ID,聚簇索引叶子结点存储的是对应的数据。聚簇索引默认是主键,如果表中没有定义主键,InnoDB 会选择一个唯一且非空的索引代替。如果没有这样的索引,InnoDB 会隐式定义一个主键(类似oracle中的RowId)来作为聚簇索引。如果已经设置了主键为聚簇索引又希望再单独设置聚簇索引,必须先删除主键,然后添加我们想要的聚簇索引,最后恢复设置主键即可。

在数据库中,聚簇索引和非聚簇索引是两种常见的索引类型,它们都有不同的优缺点。

聚簇索引是一种将数据行存储在表中相邻位置的索引方式,通常使用主键作为聚簇索引。聚簇索引可以快速地定位到需要查找的数据行,因为查询时只需要访问少量的数据块就能够获取全部数据。但是如果表经常进行插入或删除操作,会导致数据行的移动,从而增加维护聚簇索引的成本,并可能导致表的碎片化。

非聚簇索引则是将索引结构和数据行分开存储,通过指向数据行的指针来实现查询。非聚簇索引可以支持更高的并发性,因为它不需要对整个表进行锁定。同时也能够减少维护索引的成本,因为非聚簇索引不会随着数据行的移动而改变。

回表查询是指在查询中需要多次读取表的数据,通常是在使用非聚簇索引时,先根据索引找到符合条件的数据行,再根据指针回到表中读取完整的数据行。这种查询方式会增加IO操作的次数,降低查询效率,因此在设计索引时需要考虑减少回表查询的情况。

综合来说,聚簇索引适用于查询次数较多、插入和删除操作较少的表,而非聚簇索引则适用于插入和删除操作频繁的表。当使用非聚簇索引时,需要尽量减少回表查询的次数,以提高查询效率。

InnoDB 存储引擎在使用索引时,会根据一些规则来选择使用聚簇索引还是非聚簇索引。

对于主键查询和使用某些唯一索引的查询,InnoDB 存储引擎会使用聚簇索引。因为聚簇索引的叶子节点存储了数据行,可以直接查找到需要的数据行,因此能够提高查询效率。如果没有定义主键或者唯一索引,则 InnoDB 存储引擎会隐式地创建一个隐藏的聚簇索引,其中包含所有列。

对于非唯一索引的查询,InnoDB 存储引擎会使用非聚簇索引。因为非聚簇索引的叶子节点只包含索引列和指向数据行的指针,查询时需要先根据索引找到符合条件的数据行,再回表查询获取完整的数据行,因此查询效率可能会较低。

但是,InnoDB 存储引擎在使用索引时,并不完全依赖上述规则。如果表中的大多数查询都通过某个特定的非唯一索引进行,那么该索引也可能会被选为聚簇索引。这种情况下,可以通过将该索引设置为主键或唯一索引,或者使用 ALTER TABLE 命令显式地将其转换为聚簇索引来优化查询性能。

综上所述,InnoDB 存储引擎在使用索引时,会根据查询类型和表结构等因素综合考虑选择使用聚簇索引还是非聚簇索引。需要根据具体情况进行分析和调整,以提高查询性能。

索引的数据结构是什么?

在关系型数据库中,索引一般采用树形结构来进行存储和管理,特别是B+树和B树。它们都是多路平衡查找树的变种。

B+树是一种多路平衡查找树,其每个非叶子节点包含k个关键字和k+1个指针,其中k为树的阶数。每个叶子节点包含了对应索引列的值和指向数据记录的指针。B+树除了根节点外所有节点都是叶子节点,且叶子节点按照关键字大小从小到大连成一个链表,这使得范围查询和排序等操作更加高效。

B树也是一种多路平衡查找树,与B+树类似,其每个节点包含k个关键字和k+1个指针,但是B树的非叶子节点也可以同时存储数据记录,因此B树的高度比B+树更低,适用于随机读写和频繁更新的场景。

Hash表是另一种常见的索引数据结构,它通过哈希函数将关键字转换成哈希值,并将哈希值作为指针索引到对应的数据记录,从而实现快速查找。Hash表对于等值匹配查询具有优秀的性能表现,但是不支持范围查询和排序等操作。

除了以上常见的索引数据结构,还有一些特殊类型的索引,如全文索引、空间索引等,它们使用不同的数据结构来适应各种场景的数据查询需求。

前缀索引?

前缀索引是指在数据库索引中只使用索引列的部分值作为键值来创建索引。例如,对于一个文本类型的列,可以只使用该列开头的几个字符来创建前缀索引。

前缀索引的优点是能够显著减小索引的大小,降低索引维护和查询的成本,尤其对于大数据量的表格尤为明显。同时,前缀索引也能够提高查询效率,并减少索引碎片化的问题。

但是,使用前缀索引也存在一些潜在的问题,最主要的就是可能会导致信息损失和不准确性。因为前缀索引只使用了列的一部分进行索引,所以在索引列有重复值的情况下,可能会出现索引冲突或者误判的情况,从而影响查询结果的正确性和精度。

因此,在使用前缀索引时需要仔细考虑具体的索引列和应用场景,权衡索引大小和查询效率之间的关系,以便为系统提供更好的性能和可靠性。

MySQL/MongoDb 端口号,redis端口号?

MySQL的默认端口号是3306,而MongoDB的默认端口号是27017。这些端口号都是数据库服务监听连接请求的网络接口,客户端在连接数据库时需要指定相应的端口号才能与数据库建立通信连接。当然,在实际使用过程中,可以根据具体的需求和安全性要求来修改端口号并进行必要的防火墙设置,以保障数据的安全性和可靠性。Redis 默认的端口号是 6379。但是如果需要在同一台机器上运行多个 Redis 实例,就需要修改端口号。可以通过修改 Redis 的配置文件 redis.conf 来设置不同的端口号。

数据库有几种表之间的连接形式(左连接,右连接,内连接,完全连接)?

在关系型数据库中,常见的表之间连接形式有以下几种:

内连接(INNER JOIN):内连接是指将两个表中符合条件的记录进行配对,只返回其交集部分。如果某个表中没有对应的匹配记录,则不会返回该表的任何数据。

左连接(LEFT JOIN):左连接是指将左侧表中所有记录和右侧表中符合条件的记录进行匹配,如果右侧表中没有对应的匹配记录,则返回null值。左连接保留了左侧表中的所有记录。

右连接(RIGHT JOIN):右连接与左连接类似,只是将右侧表中所有的记录和左侧表中符合条件的记录进行匹配。如果左侧表中没有对应的匹配记录,则返回null值。右连接保留了右侧表中的所有记录。

全连接(FULL OUTER JOIN):全连接是一种比较少用的连接方式,它将左侧表和右侧表中的所有记录都进行匹配,并返回所有匹配的记录以及没有匹配的记录,如果没有匹配的记录则返回null值。

上述四种连接方式可以组合使用,例如在一个查询语句中同时使用左连接和右连接,或者使用内连接和左连接等,以满足复杂查询需求。需要注意的是,连接操作可能会引起数据冗余和性能问题,因此需要仔细规划和优化数据表结构和查询语句,以提高系统的性能和可靠性。

三大范式?

三大范式是关系型数据库设计中的重要概念,主要为了确保数据库中的数据不会出现冗余、不一致和更新异常等问题。具体来说,三大范式包括:

第一范式(1NF):第一范式要求每个属性都具有原子性,也就是不能再分解成更小的数据项。如果存在复合属性,则需要将其拆分为单一属性。

第二范式(2NF):第二范式要求每个非主键属性完全函数依赖于主键,也就是说,每个非主键属性都必须与主键相关,并且不能只依赖于部分主键。

第三范式(3NF):第三范式要求每个非主键属性不传递依赖于主键,也就是说,一个非主键属性不能依赖于另一个非主键属性。

第四范式:主属性对主键完全函数依赖且不传递依赖

这些范式的目标是减少数据冗余和不一致,降低数据处理的复杂度。但是范式过度使用也可能导致查询复杂度增加,因此在实际应用中需要根据具体情况进行灵活调整。例如,在某些查询场景下,为了提高查询性能可以选择适当的冗余或者反规范化操作。

数据库隔离等级,分别解决了哪些问题?

数据库隔离等级是指在多个并发事务同时访问数据库时,数据库管理系统为了保证数据的一致性和可靠性所采用的隔离策略。常见的隔离级别有四种:读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)和序列化(Serializable),它们分别解决了以下问题:

读未提交(Read Uncommitted):该隔离级别下事务可以读取其他事务未提交的数据,因此可能会出现脏读问题,即读取到还未提交的数据。但是,由于该级别下锁的粒度较低,因此并发性能比较高。

读已提交(Read Committed):该隔离级别下事务只能读取其他事务已经提交的数据,因此可以避免脏读问题。但是,由于该级别下只对行级数据加锁,因此可能会出现不可重复读和幻读的问题。

可重复读(Repeatable Read):该隔离级别下事务在读取数据时会对所有查询结果集进行快照,并且在事务结束之前都不允许其他事务修改这些数据,因此可以避免不可重复读的问题。但是,由于该级别下只对行级数据加锁,因此可能会出现幻读的问题。

序列化(Serializable):该隔离级别下事务是串行执行的,可以避免脏读、不可重复读和幻读的问题。但是,由于该级别下锁的粒度最高,因此并发性能最低。

要选择适当的隔离级别需要综合考虑数据的一致性、并发性能和应用场景等多个因素,并在实际应用中进行灵活调整。

为什么要用b+树索引而不用hash?

在关系型数据库中,我们通常使用B+树索引来提高查询效率,而不是使用哈希(Hash)索引。这主要有以下几个原因:

范围查询:B+树支持范围查询,可以通过遍历数据结构中的节点来实现范围查询操作。而哈希索引只支持等值查询,不能满足范围查询的需求。

排序:B+树是有序的数据结构,可以很方便地支持排序和分页等操作。而哈希索引没有排序功能,无法进行排序和分页等操作。

内存限制:哈希索引需要一次性将所有索引数据加载到内存中,对于大数据量的表格并不适用。而B+树索引可以将数据划分为多个块,并且每个块都可以单独加载或者卸载,因此对于大数据量的表格具有更好的可扩展性和性能表现。

索引重建:当哈希索引的存储桶数量不足时,需要重新计算哈希函数并将数据全部重新插入到新的存储桶中,这个过程比较耗时。而B+树索引的重建过程相对简单,并且可以在后台进行,不会对正常查询产生影响。

综上所述,B+树索引具有更好的范围查询、排序和内存限制能力,同时也可以实现高性能的数据扩展和索引重建,因此在关系型数据库中通常使用B+树索引。而哈希索引则主要适用于等值查询场景,例如缓存和哈希表等应用中。

MySQL解决不可重复读的原理?具体怎么实现的?

参照这个:服务端开发之Java秋招面试11_nuist__NJUPT的博客-CSDN博客

innodb底层存储

深入理解InnoDB -- 存储篇 - 知乎 (zhihu.com)

 redis详解

(ROOT)redis学习笔记-CSDN博客

 说说redis中的数据结构和应用场景?

(SUB)redis数据结构和数据类型及应用-CSDN博客

Redis是一种内存型的键值数据库,支持多种数据结构,可以用于缓存、消息队列、计数器等各种场景。以下是Redis中常见的数据结构及其应用场景:

字符串(String):字符串是Redis最基本的数据类型,用于存储单个字符串或二进制数据等,常用于缓存、计数器、分布式锁等场景。

列表(List):列表是一个有序的字符串序列,支持在头部和尾部进行插入和删除操作,常用于实现消息队列、任务队列等场景。

哈希表(Hash):哈希表是一种键值对集合,可以看作是一个小的字典,通常用于存储对象属性、统计数据等信息。

集合(Set):集合是一组无序且唯一的元素,支持快速地新增、删除和判断元素是否存在等操作,常用于去重、好友关系等场景。

有序集合(Sorted Set):有序集合是一组唯一的元素,每个元素都关联着一个权重值,可以按照权重值进行排序,常用于排行榜、leaderboard等场景。

除了以上常用的数据结构之外,Redis还支持位图、HyperLogLog、Geo等特殊数据结构,这些数据结构可以根据具体的应用场景进行选择和使用。

总体来说,Redis的数据结构广泛应用于各种实时性要求高、读取频繁,且对数据结构支持有一定要求的场景,例如缓存、计数器、消息队列等。但是需要注意的是,由于Redis是一种内存型数据库,因此数据容易受到内存大小和并发访问等因素的影响,需要仔细规划和优化系统架构和应用代码,以提高系统的性能和可靠性。

redis作为缓存三大问题(击穿穿透雪崩)和如何解决缓存一致性

(SUB)redis作为缓存的常见问题(三大问题+缓存一致性)-CSDN博客

Linux

 jps, stat, jstack,jmap:

jvm性能监控、故障处理命令行工具详解(jps、jstat、jinfo、jmap、jhat、jstack)(宝藏博文)_sun jdk 监控和故障处理命令有 jps jstat jmap jhat jstack jinf-CSDN博客

https://www.cnblogs.com/chenpi/p/5377445.html

linux命令

(SUB)常用linux命令-CSDN博客

 Linux如何防止新人误操作rm -rf?

利用alias命令将rm命令替换为带有-i选项的rm命令。即在用户的bash配置文件(如~/.bashrc)中添加一行类似于alias rm='rm -i'的命令。这样,每次执行rm命令时,都会自动加上-i选项,防止误操作。

利用chattr命令设置文件或目录的不可删除属性。可以通过执行类似于sudo chattr +i /path/to/file的命令,将文件或目录设置为只读、不可修改和不可删除的,这样就可以避免误删除文件或目录。

堆栈区别(java)

堆和栈的区别主要体现在以下几个方面。

内存分配方式
栈(stack)和堆(heap)都是内存中的一段区域,但它们的内存分配方式是不同的。栈是由程序自动创建和释放的,通常用于存储函数调用时的临时变量、函数的返回地址等信息。而堆则是由程序员手动申请和释放的,通常用于存储程序中需要动态分配的内存(如动态数组、对象等)。

内存管理方式
栈的内存分配是按照“后进先出”的原则进行的,即最后一个进入栈的变量最先被释放。因此,栈中的内存管理是由系统自动完成的,程序员不需要过多考虑内存的分配和释放问题。堆的内存管理则需要程序员自行负责,使用完毕后必须手动释放,否则会导致内存泄漏或其他问题。

内存大小
栈的容量较小,一般只有几百KB到几MB的空间,具体容量由操作系统和编译器决定。相对而言,堆用于存储较大的数据结构,大小一般比栈要大得多,可以动态扩展内存空间。但是,因为堆需要手动管理内存,如果不及时释放,会导致内存泄漏,进而影响系统性能。

访问速度
因为栈的内存分配是系统自动完成的,所以访问速度相对堆更快。栈中的数据直接存放在系统内存中,而访问堆中的数据需要通过指针进行间接访问,会造成一定的时间损耗。此外,在多线程环境下,由于栈的线程独享,所以不会发生竞争问题。而堆则需要考虑多线程并发访问时的同步和互斥机制。

应用场景
栈适合用于存储局部变量和函数调用,主要用于内存的临时分配;而堆适合用于存储需要动态分配和管理的数据结构,如动态数组、字符串、对象等。在实际开发中,应该根据具体的应用场景选择合适的内存分配方式。

进程通讯,线程通信

进程间通讯的7种方式_进程间通信的几种方法-CSDN博客

线程间的通信方式_线程间通信的几种方法-CSDN博客

 进程状态

在这里插入图片描述

线程状态 

在这里插入图片描述

 ————测试工具——————

docker

Docker 从入门到精通(新手建议收藏的教程)_docker教程-CSDN博客

selenium

selenium实现web自动化测试_8. 需求:打开‘注册a.html’页面,完成以下操作 1). 填写注册信息 2). 截图保存-CSDN博客

seleniumgrid

selenium Grid详解 - 习久性成 - 博客园 (cnblogs.com)

 jmeter

分布式性能测试-CSDN博客

 jmeter关联多线程组

jmeter跨线程组传值和jmeter跨线程组调用 - 知乎 (zhihu.com)

fiddler

Fiddler抓包工具保姆级使用教程(超详细)_抓包软件怎么使用-CSDN博客

 fiddler mock接口

  fiddler:Fiddler进行mock数据_fiddler mock 百度-CSDN博客

fiddler模拟弱网

爆肝整理,Fiddler+Charles+Chrome开发者工具弱网测试总结,一篇概全..._charles设置弱网速率-CSDN博客

fiddler测手机接口 

前言
1、Fiddler模拟弱网测试

Fiddler原理:

Fiddler代理位于 Web 客户端和 Web 服务器之间,扮演“中间人”的角色。Fiddler既代理客户端向服务器发送请求,又代理服务器向客户端返回响应内容。

Fiddler弱网测试方法:

Fiddler弱网测试是通过设置,上传和下载1KB数据所需要的时间,来控制上行和下行的速率。在实际测试过程中,只能修改延迟时间,需要我们事先确定模拟的网络传输速率,转换成延迟时间。

1)配置需要模拟的弱网环境

启动fiddler找到Rules—Customize Rules点击打开

在Fiddler script里搜索delay关键字,找到设置模拟延迟的代码,设置网络请求和响应延迟的时间(MS),点击保存

注意:

此处设置的是时间,以毫秒(MS)为单位;
request-trickle-delay 为上行延迟的时间,即请求延迟的时间;
response-trickle-delay 为下行延迟的时间,即响应延迟的时间;

换算的规则,脚本中是1KB为数据大小,换算多少毫秒MS,完成请求和响应。
计算公式:(1KB*8/上下行速率kbps)*1000=延迟时间(MS)

公式解释:

数据存储的最小单位是Byte字节,数据传输的单位是bit比特,即位,1Byte=8bit。
通讯商网络上传和下载的速率是以kbps表示:千bit每秒,为了统一kb单位。把Fiddler中固定数据大小1KB换算成Kb,最后1KB*8=8Kb。
乘以1000是把秒S换算成毫秒MS,即我们在脚本文件中配置的时间。

例子:

Fiddler默认的上行延迟300ms,下行延迟150ms。
换算成网络传输的速率为:
上行:8kb/(300ms/1000)=26.67kbps
下行:8kb/(150ms/1000)=53.33kbps

如果要模拟上行750kbps,下行1500kbps速率。
Fiddler中需要设置的延迟时间为:
上行:(8kb/750kbps)*1000=10.67ms
下行:(8kb/1500kbps)*1000=5.33ms

2)启动限速开关

设置完延迟时间之后,返回Fiddler首页菜单。在Fiddler→Rules→Performance,勾选Simulate Modem Speed。

网络知识:

1B(byte 字节)=8bit(位);
1KB(Kilobyte 千字节)=1024B;
1MB(Megabyte 兆字节 简称“兆”)=1024KB;
1GB(Gigabyte 吉字节 又称“千兆”)=1024MB;
1TB(Terabyte 万亿字节 太字节)=1024GB;

网络通讯商,打广告说的百兆宽带,不是100MB,而是100Mb。换算成MB,实际带宽为100Mb/8=12.5MB。

参考上下行速率设置:

网络段    上行    下行    丢包    延迟
弱3G    330kbps    780kbps    10%    100ms
强3G    750kbps    1500kbps    5%    40ms

postman mock接口工具

PostMan笔记(四)Mock服务与API文档管理-CSDN博客

postman

Postman进阶使用_postman view summary-CSDN博客

 常见adb命令

常用ADB命令_adb打印日志命令-CSDN博客

 selenium的css定位和xpath定位

Selenium定位元素的方法css和xpath的区别!_span标签算是 selenium 的css样式吗-CSDN博客

 httprunner

HttpRunner 3.x快速上手_har2case命令-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值