努力了那么多年,回头一望,几乎全是漫长的挫折和煎熬。对于大多数人的一生来说,顺风顺水只是偶尔,挫折、不堪、焦虑和迷茫才是主旋律。我们登上并非我们所选择的舞台,演出并非我们所选择的剧本。继续加油吧!
目录
1.讲一下redis和mySQL的区别?
2.讲一下put/get/post的区别?
3.redis的缓存击穿,缓存穿透,缓存雪崩?
4.http常见状态码?
5.消息队列的使用场景?
6.朋友圈点赞功能测试用例?
7. 单例模式实现的方式?
8.DNS解析的过程是?
9.怎么判断链表相交?
10.测试的流程?
11.测试方法?
12.支付设计测试用例?
13.登录设计测试用例?
14.怎么判断bug是前端还是后端的?
15.Python的基本数据类型?
16.什么是接口测试?
17.postman请求方式有哪些?
18.get 和post区别?
19.自动化测试框架?
20.进程和线程的区别?
21.json数据了解吗,用过什么工具查看 ?
mysql是关系型数据库,主要用于存放持久化数据,将数据存储在硬盘中,读取速度较慢。
redis是NOSQL,即非关系型数据库,即将数据存储在缓存中,缓存的读取速度快,能够大大的提高运行效率,但是保存时间有限。
mysql用于持久化的存储数据到硬盘,功能强大,速度较慢,基于磁盘,读写速度没有Redis快,但是不受空间容量限制,性价比高
redis用于存储使用较为频繁的数据到缓存中,读取速度快,基于内存,读写速度快,也可做持久化,但是内存空间有限,当数据量超过内存空间时,需扩充内存,但内存价格贵
mysql和redis因为需求的不同,一般都是配合使用。
需要高性能的地方使用Redis,不需要高性能的地方使用MySQL。存储数据在MySQL和Redis之间做同步。
最直观的区别就是Get
请求把参数包含在url
中,但是Post
通过request body
传递参数Get
请求是一个幂等的请求,一般Get
请求用于对服务器资源不会产生影响的场景(如请求一个网页的资源);Post
不是一个幂等的请求,一般用于对服务器资源会产生影响的场景(如注册用户)
最直观的区别就是Get
请求把参数包含在url
中,但是Post
通过request body
传递参数
Put
请求是向服务器端发送数据,从而修改数据的内容,但是不会增加数据的种类等,也就是说不管进行多少次操作,它的结果并没有不同,可以看做是更新数据
Post
请求时在向服务器发送数据后,请求会改变数据的种类等资源,会创建新的内容
① 缓存穿透:大量请求根本不存在的key,请求根本不存在的资源(DB本身就不存在,Redis更是不存在)
解决方案:
对空值进行缓存
使用布隆过滤器( 使用BitMap作为布隆过滤器,将目前所有可以访问到的资源通过简单的映射关系放入到布隆过滤器中(哈希计算),当一个请求来临的时候先进行布隆过滤器的判断,如果有那么才进行放行,否则就直接拦截)
② 缓存雪崩:redis中大量key集体过期
③ 缓存击穿:redis中一个热点key过期(大量用户访问该热点key,但是热点key过期)
缓存雪崩和缓存穿透解决方案:
进行预先的热门词汇的设置,进行key时长的调整
实时调整,监控哪些数据是热门数据,实时的调整key的过期时长
使用锁机制(当热点key过期,那么就使用锁机制防止大量的请求直接打在DB)
下面是常见的 HTTP 状态码:
异步处理,应用解耦,流量削锋和消息通讯四个场景。
应用解耦:在分布式系统中,不同的应用之间需要相互通信,但直接依赖会导致代码耦合度过高。使用MQ作为中间件,可以进行解耦。每个应用只需向MQ发送消息,而不需要了解其他应用的具体实现细节。
流量销峰:使用MQ作为中间件,将高峰期的请求缓存到队列中,在系统负载降低后再逐一处理。这可以避免系统崩溃或响应变慢。
异步调用:应用向MQ发送消息,并不需要等待消息的处理结果,从而实现异步调用。处理结果可以通过回调函数或其他方式返回给应用。
削峰填谷:使用MQ作为缓存,将请求写入队列中并按照一定速率消费,避免突发请求对系统造成压力过大。当系统负载较低时,可以加速消费消息以“填谷”,保证在高峰期前消费完所有消息。
功能测试:
正常:1.点赞和取消点赞的正常使用 2.点赞后下方是否正常显示微信名称
3.取消点赞后显示的名称消失 4.点赞后的名称显示顺序是否按照时间顺序
5.是否支持多次点赞 6.一条朋友圈所支持的点赞人数
7.点赞后是否提醒被点赞用户 8.用户点赞过的朋友圈被微信好友点赞时是否会通知用户
9.点赞后可见分组好友是否可见,其他是否不可见 10.同一条朋友圈在手机,电脑上同时点赞
11.同一条朋友圈两人同时点赞的显示顺序
异常:1.断网 2.手机/电脑低电量
3.服务器异常 4.离线 5.来电,短信
6.点赞刚刚删除的朋友圈
性能测试
1.点赞/取消点赞受网络环境影响
2.压力测试-频繁点赞和取消点赞
3.大量用户并发点赞时,该接口的响应时间,最大承受的qps
4.大量用户并发点赞时,此时界面进行点赞,点赞功能是否正常
5.点赞后好友消息的更新速度
安全性测试
1.点赞后可见分组好友是否可见
2.未登录时查看点赞信息
3.点赞内容非法
4.点赞带有病毒的消息
5.点赞过程中染上病毒
界面,易用性测试
1.排版,按钮正常,无错别字
2.界面美观
3.正常显示点赞用户的头像
4.最多显示多少个点赞用户的头像
5.点赞一行显示多少个用户的头像,最多显示多少行
6.操作简单易懂
兼容性
1.不同平台:Windows,Mac
2.不同系统:Windows7,Windows10
3.不同的移动设备:Iphone.Andriod
4.不同地域
5.不同版本
单例模式分为饿汉模式和懒汉模式,都是每个类中只创建一个实例,并提供全局访问点来访问这个实例。饿汉模型是线程安全的,懒汉模式线程不安全,需要使用双重检测锁保证线程安全,具体的Java代码实现如下:
/**
* 单例模式:确保每个类只有一个实例,并提供全局访问点来访问这个实例
*/
//饿汉模式:线程安全
class Singleton1 {
private static Singleton1 instance = new Singleton1() ;
public Singleton1 getInstance(){
return instance ;
}
}
//懒汉模式:线程不安全,需要通过双重检查锁定机制控制
class Singleton2{
private static Singleton2 instance2 = null ;
public Singleton2 getInstance2(){
if(instance2 == null){
instance2 = new Singleton2() ;
}
return instance2 ;
}
}
//使用双重检查锁的方式保重线程安全
class Singleton3{
//使用双重检查进行初始化的实例必须使volatile关键字修饰
private volatile static Singleton3 instance3 = null ;
public Singleton3 getInstance3(){
if(instance3 == null){
synchronized (Singleton3.class){
if(instance3 == null){
instance3 = new Singleton3();
}
}
}
return instance3 ;
}
}
public class Main {
public static void main(String[] args) {
Singleton1 singleton1 = new Singleton1() ;
Singleton1 singleton2 = new Singleton1() ;
Singleton2 singleton21 = new Singleton2() ;
Singleton2 singleton22 = new Singleton2() ;
Singleton1 instance1 = singleton1.getInstance();
Singleton1 instance2 = singleton2.getInstance();
Singleton2 instance21 = singleton21.getInstance2();
Singleton2 instance22 = singleton22.getInstance2();
System.out.println(instance1 == instance2);
System.out.println(instance21 == instance22);
}
}
客户端首先会发出一个 DNS 请求,问 www.server.com 的 IP 是啥,并发给本地 DNS 服务器(也就是客户端的 TCP/IP 设置中填写的 DNS 服务器地址)。
本地域名服务器收到客户端的请求后,如果缓存里的表格能找到 www.server.com,则它直接返回 IP 地址。如果没有,本地 DNS 会去问它的根域名服务器:“老大, 能告诉我 www.server.com 的 IP 地址吗?” 根域名服务器是最高层次的,它不直接用于域名解析,但能指明一条道路。
根 DNS 收到来自本地 DNS 的请求后,发现后置是 .com,说:“www.server.com 这个域名归 .com 区域管理”,我给你 .com 顶级域名服务器地址给你,你去问问它吧。”
本地 DNS 收到顶级域名服务器的地址后,发起请求问“老二, 你能告诉我 www.server.com 的 IP 地址吗?”
顶级域名服务器说:“我给你负责 www.server.com 区域的权威 DNS 服务器的地址,你去问它应该能问到”。
本地 DNS 于是转向问权威 DNS 服务器:“老三,www.server.com对应的IP是啥呀?” server.com 的权威 DNS 服务器,它是域名解析结果的原出处。为啥叫权威呢?就是我的域名我做主。
权威 DNS 服务器查询后将对应的 IP 地址 X.X.X.X 告诉本地 DNS。
本地 DNS 再将 IP 地址返回客户端,客户端和目标建立连接。
首先分别获取两个链表的长度lenListA与lenListB,然同用快慢指针法,先让较长的链表走N步,N=(lenListA-lenListB)的绝对值。然后两个链表再同时走,直到两个链表的结点是一样的,此时这个结点就是两个链表相交的起始节点.
立项(确定项目)——>产品说明书(PRD)——>需求文档(需求人员)——>需求评审(开发、测试人员、经理)——>开发人员进行(详细概要设计——>编码——>自测——>提测)——>测试人员进行(测试计划——>编写测试用例——>测试用例评审)——>冒烟测试(测试主流程是否通过)——>功能测试——>禅道记录bug——>回归测试(验证上个版本出现的问题是否解决,是否出现新的问题)——>验收测试(客户、经理、需求、开发、测试人员)——>上线
1、从是否关心内部结构来看
(1)白盒测试:又称为结构测试或逻辑驱动测试,是一种按照程序内部逻辑结构和编码结构,设计测试数据并完成测试的一种测试方法。
(2)黑盒测试:又称为数据驱动测试,把测试对象当做看不见的黑盒,在完全不考虑程序内部结构和处理过程的情况下,测试者仅依据程序功能的需求规范考虑,确定测试用例和推断测试结果的正确性,它是站在使用软件或程序的角度,从输入数据与输出数据的对应关系出发进行的测试。
(3)灰盒测试:是一种综合测试法,它将“黑盒”测试与“白盒”测试结合在一起,是基于程序运行时的外部表现又结合内部逻辑结构来设计用例,执行程序并采集路径执行信息和外部用户接口结果的测试技术。
2、从是否执行代码看
(1)静态测试:指不运行被测程序本身,仅通过分析或检查源程序的语法、结构、过程、接口等来检查程序的正确性。
(2)动态测试:是指通过运行被测程序,检查运行结果与预期结果的差异,并分析运行效率、正确性和健壮性等性能指标。
3、从开发过程级别看
(1)单元测试:又称模块测试,是针对软件设计的最小单位----程序模块或功能模块,进行正确性检验的测试工作。其目的在于检验程序各模块是否存在各种差错,是否能正确地实现了其功能,满足其性能和接口要求。
(2)集成测试:又叫组装测试或联合,是单元测试的多级扩展,是在单元测试的基础上进行的一种有序测试。旨在检验软件单元之间的接口关系,以期望通过测试发现各软件单元接口之间存在的问题,最终把经过测试的单元组成符合设计要求的软件。
(3)系统测试:是为判断系统是否符合要求而对集成的软、硬件系统进行的测试活动、它是将已经集成好的软件系统,作为基于整个计算机系统的一个元素,与计算机硬件、外设、某些支持软件、人员、数据等其他系统元素结合在一起,在实际运行环境下,对计算机系统进行一系列的组装测试和确认测试。
4、从执行过程是否需要人工干预来看
(1)手工测试:就是测试人员按照事先为覆盖被测软件需求而编写的测试用例,根据测试大纲中所描述的测试步骤和方法,手工地一个一个地输 入执行,包括与被测软件进行交互(如输入测试数据、记录测试结果等),然后观察测试结果,看被测程序是否存在问题,或在执行过程中是否会有一场发生,属于比较原始但是必须执行的一个步骤。
(2)自动化测试:实际上是将大量的重复性的测试工作交给计算机去完成,通常是使用自动化测试工具来模拟手动测试步骤,执行用某种程序设计语言编写的过程(全自动测试就是指在自动测试过程中,不需要人工干预,由程序自动完成测试的全过程;半自动测试就是指在自动测试过程中,需要手动输入测试用例或选择测试路径,再由自动测试程序按照人工指定的要求完成自动测试)
5、从测试实施组织看
(1)开发测试:开发人员进行的测试
(2)用户测试:用户方进行的测试
(3)第三方测试:有别于开发人员或用户进行的测试,由专业的第三方承担的测试,目的是为了保证测试工作的客观性
6、从测试所处的环境看
(1)阿尔法测试:是由一个用户在开发环境下进行的测试,也可以是公司内部的用户在模拟实际操作环境下进行的测试
(2)贝塔测试:是用户公司组织各方面的典型终端用户在日常工作中实际使用贝塔版本,并要求用户报告
7、其他测试类型
(1)回归测试(regression testing)是指对软件的新的版本测试时,重复执行上一个版本测试时的用例。
(2)冒烟测试(smoke testing),是指在对一个新版本进行大规模的测试之前,先验证一下软件的基本功能是否实现,是否具备可测性。
(3)随机测试(random testing),是指测试中所有的输入数据都是随机生成的,其目的是模拟用户的真实操作,并发现一些边缘性的错误。
支付流程:
1:正常的发起一笔流量充值请求,检查点:
1)用户发过去的信息有携带key值
2)商户系统本地数据会留存一份用户的订单信息,并且会根据每笔订单信息生成一笔支付信息(同时留存到本地)
3)第三方支付成功,第三方有存支付订单信息
4)充值成功,用户的流量余额有对应增加
异常用例
1、修改用户发过去的数据:
1)产品ID 与价值不对等---->检查点:篡改数据和key,检查商户系统报错:key值不对或者是用户数据有误。
2)取消充值流量
3)重复发起流量充值请求
2、商户系统-第三方之间:
1)密钥搞错-第三方报错,不接收密钥
2)提交商户系统里面不存在的订单/支付订单->第三方这里也是不能通过请求
3)篡改用户支付金额-->第三方也要检查
3、第三方--用户之间:
1)支付密码错误/余额不足
2)取消支付
3)重复支付[对账--->处理退款]
退款流程
正常的用例:
1.用户发起退款--->该用户的订单以及支付订单号都要存在。---检查点:商户系统/第三方检查数据没有问题,可以退款成功--->交易状态改成退款
异常用例:
1:无故发起退款:提交不存在的订单号或者支付订单号 --->订单号不存在/支付订单号不存在
2:信息不匹配发起退款:提交订单号与支付订单号不匹配的数据--->订单号/支付订单号有误
3:退款大于实际金额:提交的退款金额大于实际支付订单的金额-->商户系统要报错
4:商户系统这里发过去的请求:退款金额大于实际支付金额-->第三方要报错
功能、安全、性能、兼容性、中断等。
判断方法:
1.抓包工具常用于查看是前端的显示有误,还是后端返回给前端的数据有误,通常浏览器自自带的F12、fiddler、httpwatch等工具都可以。主要从请求接口、传参、响应三个方面分析。
查看请求接口的URL是否正确,如果错误,那就是前端传错了;同理,如果传的参数错了,也是因为前端;如果URL和传参都正确,响应错了,那就是后端。后端代码出错了,可以通过查看日志,数据库对应的数据,缓存,来具体判断错误在哪发生;此外,记住常见的响应状态码代表意义也有助于判断bug。
2.查看日志
出现bug时,查看服务器里的日志。如果日志没有输出,基本认为该功能没有与后端交互,非后端bug;如果有输出,就查看有无相关错误日志信息来进一步分析。
3.查看数据库
很多bug出现在接口的相互调用的情形里。可以通过在数据库里查询数据、比对来判断是哪些接口出了问题,比如:在A模块添加一条数据,但是在B模块没有展示,这时我们 通过查询数据库的数据来确认,是A模块没有插入数据,还是B模块没有查询到。而知道接口是前端还是后端负责开发的,就知道bug该给谁改了。
4.经验判断
平时的经历多了,对前后端代码的功能实现、交互等知识有了更深认识,事后及时思考总结,自然而然地会level up。关键在于态度和行动。
Python 中主要有8种数据类型:number(数字)、string(字符串)、list(列表)、tuple(元组)、dict(字典)、set(集合)、Boolean(布尔值)、None(空值)。
接口测试:是测试系统组件间接口的一种测试方法
接口测试的重点:检查数据的交换,数据传递的正确性,以及接口间的逻辑依赖关系
接口测试的意义:在较早期开展,在软件开发的同时实现并行测试,减少页面层测试的深入问题,降低开发成本,缩短整个项目的测试周期;脱离页面的限制,更全面的进行测试,发现更底层的问题。
HTTP请求方式: HTTP 1.0 定义了三种请求方法:GET / POST / HEAD HTTP 1.1 增加了五种请求方法: OPTIONS / PUT / DELETE / TRACE / CONNECT 常用的 GET 和 POST 两种方式请求。
POST和GET都是HTTP请求的基本方法。最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数。
1)GET请求在浏览器刷新或者回退的时候是无害的。POST的话数据会被重新提交。
2)GET可以存在缓存中。POST不行。
3)GET 编码格式只能用ASCII码,POST没有限制。
4)可见性 参数在URL用户可以看见,POST的参数在REQUSET BODY中不会被用户看见.GET相对不安全 POST相对安全些。
5)GET请求在URL中传送的参数是有长度限制的而POST么有。
6)GET 和POST在请求的时候:
6-1 GET 是将数据中的hearder 和 data 一起发送给服务端,返回200code
6-2 POST 是先将hearder发给服务器返回100continue,再发送data给到服务器,返回200
6-3 GET 就发送了一个TCP数据包给服务器而POST发送了两次TCP数据包给服务器
本质区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位。
包含关系:一个进程至少有一个线程,线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
资源开销:每个进程都有独立的地址空间,进程之间的切换会有较大的开销;线程可以看做轻量级的进程,同一个进程内的线程共享进程的地址空间,每个线程都有自己独立的运行栈和程序计数器,线程之间切换的开销小。
影响关系:一个进程崩溃后,在保护模式下其他进程不会被影响,但是一个线程崩溃可能导致整个进程被操作系统杀掉,所以多进程要比多线程健壮。
jsonView,其它的接口测试工具中也可以查看。