软开、测试岗位面试总结

一、2020/08/21   美团测试开发(一面)

第一次面试,没有准备好 ,面试官还是挺亲切的。面试内存计算机网络、数据库、python的一些基础知识。

美团测试开发的面经     软件测试的基础理论

1.计算机网络七层模型:自上而下

OSI中的上面4层(应用层、表示层、会话层、传输层)为高层,定义了程序的功能;下面3层(网络层、数据链路层、物理层)为低层,主要是处理面向网络的端到端数据流。https://blog.csdn.net/warrior_0319/article/details/80453940

2.HTTP的状态码https://www.cnblogs.com/ranyonsue/p/5984001.html

HTTP(超文本传输协议)工作原理:1、客户端建立TCP连接到Web服务器;2、发送HTTP请求;3、服务器接受请求并返回HTTP响应;4、释放连接TCP连接;5、客户端浏览器解析HTML内容

状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:

1xx:指示信息--表示请求已接收,继续处理

2xx:成功--表示请求已被成功接收、理解、接受

3xx:重定向--要完成请求必须进行更进一步的操作

4xx:客户端错误--请求有语法错误或请求无法实现

5xx:服务器端错误--服务器未能实现合法的请求

HTTPS:HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。

3.TCP/IPhttps://www.jianshu.com/p/ef892323e68f

TCP/IP不是一个协议,而是一个协议族的统称。里面包括了IP协议,IMCP协议,TCP协议,以及我们更加熟悉的http、ftp、pop3协议等等。电脑有了这些,就好像学会了外语一样,就可以和其他的计算机终端做自由的交流了。

TCP 负责应用软件(比如你的浏览器)和网络软件之间的通信。IP 负责计算机之间的通信。TCP 负责将数据分割并装入 IP 包,然后在它们到达的时候重新组合它们。IP 负责将包发送至接受者。

建立连接时,三次握手:SYN为同步序列编号,ACK为确认标志。在双方“握手”之后,TCP 将在两个应用程序之间建立一个全双工 (full-duplex) 的通信。这个全双工的通信将占用两个计算机之间的通信线路。

1、建立连接时,客户端发送SYN包(SYN=i)到服务器,并进入到SYN-SEND状态,等待服务器确认

2、服务器收到SYN包,必须确认客户的SYN(ack=i+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器进入SYN-RECV状态

3、客户端收到服务器的SYN+ACK包,向服务器发送确认报ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手,客户端与服务器开始传送数据。

  

关闭连接时,四次握手:FIN为结束标志

由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当Client完成数据发送任务后,发送一个FIN来终止Client->Server的连接,这一方向上没有数据流动了,即Server不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到Server->Client也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。

TCP与UDP的区别:UDP与TCP的数据格式如下图。

TCP(Transmission Control Protocol,传输控制协议)提供的是面向连接,可靠的字节流服务。即客户和服务器交换数据前,必须现在双方之间建立一个TCP连接,之后才能传输数据。并且提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。

UDP(User Data Protocol,用户数据报协议)是一个简单的面向数据报的运输层协议。它不提供可靠性,只是把应用程序传给IP层的数据报发送出去,但是不能保证它们能到达目的地。由于UDP在传输数据报前不用再客户和服务器之间建立一个连接,且没有超时重发等机制,所以传输速度很快。

1)可靠性:TCP是面向连接的,可靠性高;UDP是基于非连接的,可靠性低 ,不关心对方是否收到数据,没有拥塞控制,导致容易丢包
2)实时性:由于TCP是连接的通信,需要有三次握手、重新确认等连接过程,会有延时,实时性差,同时过程复杂,也使其易于攻击(SYN攻击,即客户端伪造大量的虚假IP,向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,伪造的SYN包将长时间占用Server未连接队列,导致正常的SYN请求因为队列满而被丢弃,导致网络堵塞);UDP没有建立连接的过程,因而实时性较强,从另个角度说也稍安全 。
3)开销方面:在传输相同大小的数据时,TCP首部开销20字节;UDP首部开销8字节,TCP报头比UDP复杂,故实际包含的用户数据较少。TCP在IP协议的基础上添加了序号机制、确认机制、超时重传机制等,保证了传输的可靠性,不会出现丢包或乱序,而UDP有丢包,故TCP开销大,UDP开销较小 。
4)连接方式:每条TCP连接只能时点到点的;UDP支持一对一、一对多、多对一、多对多的交互通信。

4.数据库中的索引https://www.cnblogs.com/wwxzdl/p/11116446.html

组成:索引的实现使用的是B+树,一般将索引创建在经常搜索、排序的列上。

作用:数据库索引其实就是为了使查询数据效率快。创建和维护成本高,索引文件会占用物理空间。

类别:

  1. 聚集索引(主键索引):在数据库里面,所有行数都会按照主键索引进行排序。
  2. 非聚集索引:就是给普通字段加上索引。
  3. 联合索引:就是好几个字段组成的索引,称为联合索引。联合索引遵从最左前缀原则,即几个字段联合组成索引,在使用索引进行select时,需要按照联合索引最左边的字段依次查询,如果where中没有最左边的字段,则没有使用到索引。“=”表示使用到该字段索引,“!=”没有是用到该字段索引。“> ”或 “<”使用到该字段索引,但后面的其他字段没有使用到。

B+树https://www.cnblogs.com/wwxzdl/p/11089358.html

  1. 中间元素不存数据,只是当索引用,所有数据都保存在叶子结点中。
  2. 所有的中间节点在子节点中要么是最大的元素要么是最小的元素 。
  3. 叶子结点包含所有的数据,和指向这些元素的指针,而且叶子结点的元素形成了自小向大这样子的链表。

5.视图和表的区别

视图:是一些SQL语句的结果集,是虚拟在内存中的表,不实现数据的存储。其作用:1.简化了操作,把经常使用的查询结果定义为视图。2.安全性,用户只能查询和修改能看到的数据。且视图是被动的修改,根据基表的更新而更新。

1、视图是已经编译好的sql语句。而表不是。

2、视图没有实际的物理记录。而表有。

3、表是内容,视图是窗口。

4、表只用物理空间而视图不占用物理空间,视图只是逻辑概念的存在,表可以及时对它进行修改,但视图只能有创建的语句来修改。

5、表是内模式,视图是外模式。

6、视图是查看数据表的一种方法,可以查询数据表中某些字段构成的数据,只是一些SQL语句的集合。从安全的角度说,视图可以不给用户接触数据表,从而不知道表结构。

7、表属于全局模式中的表,是实表;视图属于局部模式的表,是虚表。

8、视图的建立和删除只影响视图本身,不影响对应的基本表。

6.python的内存管理机制

python内存管理机制总结为:引用计数,垃圾回收,内存池机制https://www.cnblogs.com/vamei/p/3232088.html

1.引用计数:

  1. 当一个python对象被引用时 其引用计数增加 1 ; 当其不再被变量引用时(可能被del掉引用,可能原来的引用被重定向)引用计数减 1 ; 当对象引用计数等于 0 时, 对象被删除(引用计数是一种非常高效的内存管理机制)。
  2. 由于Python缓存了整数和短字符串,因此每个对象只存有一份。比如,所有整数1的引用都指向同一对象。即使使用赋值语句,也只是创造了新的引用,而不是对象本身。
  3. 长的字符串和其它对象可以有多个相同的对象,可以使用赋值语句创建出新的对象。
  4. getrefcount(a)即获得列表对象的引用次数,由于当使用某个引用作为参数,传递给getrefcount()时,参数实际上创建了一个临时的引用,getrefcount()所得到的结果,会比期望的多1,返回结果为2和3。

2.垃圾回收(garbage collection):

  1. 当Python的某个对象的引用计数降为0时,说明没有任何引用指向该对象,该对象就成为要被回收的垃圾了。
  2. 频繁的垃圾回收将大大降低Python的工作效率。所以,Python只会在特定条件下,自动启动垃圾回收。记录的分配对象的次数(object allocation)和取消分配对象(object deallocation)的次数,差值高于某个阈值时,垃圾回收才会启动。我们也可以手动启动垃圾回收,即使用gc.collect()。
  3. Python同时采用了分代(generation)回收的策略。假设,存活时间越久的对象,越不可能在后面的程序中变成垃圾。出于信任和效率,所以减少扫描长期使用对象的频率。Python将所有的对象分为0,1,2三代。所有的新建对象都是0代对象。当某一代对象经历过垃圾回收,依然存活,那么它就被归入下一代对象。
  4. 孤立引用环情况,如果两个对象的引用计数都为 1 , 他们之间循环引用,删除两个对象的引用时,这两个对象不可能再从程序中调用,就没有什么用处了。但是由于引用环的存在,这两个对象的引用计数都不会降到0,不会被垃圾回收。但python通过遍历对像,让这种对象的引用数降为0。

 

注:上面两个10的意思是,每10次0代垃圾回收,会配合1次1代的垃圾回收;而每10次1代的垃圾回收,才有1次2代垃圾回收。

3.内存池机制:

python 中分为大内存和小内存: 256k为界限,大内存使用malloc进行分配,小内存使用内存池进行分配。

Python的内存机制以金字塔行,-1,-2层主要有操作系统进行操作,

  第0层是C中的malloc,free等内存分配和释放函数进行操作(若请求分配的内存大于256K);

  第1层和第2层是内存池,有Python的接口函数PyMem_Malloc函数实现,当对象小于256K时有该层直接分配内存;

  第3层是最上层,也就是我们对Python对象的直接操作;

7.常见的linux指令:

读写文件内容

对文件进行一定的操作处理:awk,sed,grep(linux三剑客)or https://blog.csdn.net/sj349781478/article/details/82930982

grep擅长查找功能,sed擅长取行和替换。awk擅长取列。

grep:筛选匹配的行或数据 例:grep -n A$ file.txt 查找以A结尾的行。

sed:一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。文件内容并没有改变,除非你使用重定向存储输出。例:sed  -n 2,5p file.txt 输出2-5行。sed -i 's/root/abc/g' student.txt   把root换成abc。

awk:报告生成器,格式化文本输出。按照行来读取文档,根据输入分隔符切分成小部分(用內建变量来表示$0$1$2...),用ACTION STATEMENTS来处理。$0表示显示整行。

例:awk -F ":" '{print NR,$1,$3,$NF}' test_grep.txt

解释:-F 指定分隔符,以冒号分割 '{print NR,$1,$3,$NF}' 打印出NR行号,$1第一列 $3第三列 $NF最后一列,注意$0表示整行

查看端口:Linux 查看端口占用情况可以使用 lsof 和 netstat 命令。

lsof -i:端口号 查看XXX端口已经被什么服务占用

netstat -tunlp 用于显示 tcp,udp 的端口和进程等相关情况。netstat 查看端口占用语法格式:netstat -tunlp | grep 端口号。

8.Session和Cookie的区别:

Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中。当浏览器第一次发送请求时,服务器自动生成了一个session和一个session ID用来唯一标识这个session,并将其通过响应发送到浏览器。当浏览器第二次发送请求时,会将前一次服务器响应中的session ID放在请求中一并发送到服务器,服务器从请求中提取session ID,并和保存的所有session ID进行对比,找到这个用户对应的Session。类似于超市办卡时只给客户一个卡号。
Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息。客户端请求某网站服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个cookie,客户端会把cookie保存起来。类似于超市办卡时给客户一张卡。

区别:

  • cookie数据存放在客户端,session数据存放在服务器上。
  • cookie不是很安全,别人可以分析放在本地的cookie。
  • session会在一定时间内保存在服务器上,当访问增多时,会占用服务器的性能,考虑到性能用当使用cookie。
  • 不同浏览器对cookie的数据大小限制不同,个数限制也不同。
  • session存放在服务器上,一段时间后由服务器销毁。

联系:

  • 都是用来记录用户的信息,以便让服务器分辨不同的用户。
  • 可以搭配使用,但都有自己的使用局限。

9.网页解析的全过程

1.用户输入网址,浏览器发起DNS查询请求,DNS服务器(域名解析系统)会根据用户提供的域名查找对应的IP地址。

2.建立TCP连接,浏览器通过DNS获取到WEB服务器真的IP地址后,向WEB服务器发起TCP连接请求,通过三次握手后,建立好连接。

3.浏览器向WEB服务器发送一个HTTP请求,一个HTTP事务由一条请求命令和一个响应结果组成。

4.发送响应数据给客户端,WEB服务器通常通过监听80端口,来获取客户端的HTTP请求。与客户端建立TCP连接后,WEB服务器接受到客户端发来的数据,通过HTTP解码,从其中解析出请求的URL信息等。WEB服务器根据这个HTTP请求的信息,将响应数据返回给客户端。

5.浏览器解析HTTP响应数据,包括html文档解析,CSS,解些,JS解析等。

网址的组成:协议://域名:端口号/虚拟路径?参数#锚点

协议:计算机与计算机之间交流使用的协议。主要做的是:控制传输编码,速率,出错的一些控制等等。
域名:ip的别名,192.168.1.1(路由器的默认IP)。IP主要由两部分组成,网络号+该网络中的主机号,IPV4是四个字节,根据网络号所占长度1,2,3对应A,B,C三类。
端口号:0-65535(2的16次方)
http协议:默认端口80
https协议:默认端口443
虚拟路径:用于管理资源的方式,就像计算机盘下的路径一样。
参数:传递给服务器的一些数据,xxx=*****
锚点:用于给过长的网页添加特定的点,可以通过网址快速显示锚点位置。

二、网易互娱游戏开发 2020/09/15(一面)

这次面试出现黑天鹅,面试先从笔试开始,没有了解到流程。这个岗位主要考察C++,以及一些排序查找算法。

C++的面试问题总结:https://blog.csdn.net/kuweicai/article/details/82779648

1.C/C++的指针和引用的区别:

一个对象a,它有地址&a,运行程序时,计算机会为该对象分配存储空间,来存储该对象的值,我们通过该对象的地址,来访问存储空间中的值。

指针p也是对象,它同样有地址&p和存储的值p,只不过,p存储的数据类型是数据的地址

引用可以理解成变量的别名。定义一个引用的时候,程序把该引用和它的初始值绑定在一起,而不是拷贝它。

int a=1;int *p=&a;

int a=1;int &b=a;

  1. 指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)
  2. 指针的值可以为空,但是引用的值不能为NULL,并且引用在定义的时候必须初始化
  3. 指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变了

2.C/C++内存的分配https://blog.csdn.net/weixin_41413441/article/details/81667008

  • 1).堆存放动态分配的对象——即那些在程序运行时分配的对象,使用malloc或new申请内存,在内存使用结束后必须用free或delete释放内存,其生存期由程序控制(手动申请,手动释放),类似于链表结构
  • 2).栈用来保存定义在函数内的非static对象,比如局部变量和函数参数,仅在其定义的程序块运行时才存在(操作系统自动分配区域,在程序结束后自动回收),类似于栈结构;
  • 3).静态内存用来保存static对象,类static数据成员以及定义在任何函数外部的变量,static对象在使用之前分配,程序结束时销毁;
  • 4).栈和静态内存的对象由编译器自动创建和销毁。

注:内存溢出是指存储的数据超出了指定空间的大小,这时数据就会越界  

内存泄露本意是申请的内存空间没有被正确释放,导致后续程序里这块内存被永远占用(不可达)内存空间就这么一点点被蚕食 

3.python的元组和列表的区别:参考

  1. 列表是动态数组,它们可变且可以重设长度(改变其内部元素的个数)。
  2. 元组是静态数组,它们不可变,且其内部数据一旦创建便无法直接改变。
  3. 元组缓存于Python运行时环境,这意味着我们每次使用元组时无须访问内核去分配内存。创建 tuple 比 list 要快,存储空间比 list 占用更小。
  4. tuple 是不可变的,这使得它可以作为 dict 的 key,或者扔进 set 里,而 list 则不能作为dict的key。
  5. 集合是不能出现重复的元素,元组用a = (1,2,3)创建空元组,集合用a = set([1,2,3])或a={1,2,3}。

注:虽然元组是不可变对象,也即是创建元组后不能修改/删除其中的元素,只能整个被删除。但可以使用切片重构来实现:

temp = temp[:1] + ("小猪佩奇",)+temp[2:] # 变相修改temp[1]
temp = temp[:2] + temp[3:] # 变相删除掉temp[1]

相同点:都是序列;都可以存储任何数据类型;可以通过索引访问

4.虚拟内存和物理内存的区别:https://blog.csdn.net/lvyibin890/article/details/82217193

物理内存:指计算机的安装内存,“通俗的讲就是内存条的大小”。

虚拟内存:把硬盘中的一部分空间用来当做内存使用。虚拟内存在硬盘上存在的是一个文件 PAGEFILE.SYS。

比如在32位平台下,寻址的范围是2^32也就是4G。并且这是固定的,如果没有虚拟内存,且每次开启一个进程都给4G的物理内存,就可能会出现没有得到分配物理内存的进程就只能等待的低效率问题。因此用虚拟内存来解决这些问题。

虚拟内存的工作流程:

  1. 当每个进程创建的时候,内核会为进程分配4G的虚拟内存,当进程还没有开始运行时,这只是一个内存布局。
  2. 实际上并不立即就把虚拟内存对应位置的程序数据和代码(比如.text .data段)拷贝到物理内存中,只是建立好虚拟内存和磁盘文件之间的映射就好(叫做存储器映射)。这个时候数据和代码还是在磁盘上的。
  3. 当运行到对应的程序时,进程去寻找页表,发现页表中地址没有存放在物理内存上,而是在磁盘上,于是发生缺页异常,于是将磁盘上的数据拷贝到物理内存中。

虚拟内存和物理内存的联系如下图一,页表(存储映射)的工作原理如下图二

虚拟内存的优点:

  1. 既然每个进程的内存空间都是一致而且固定的(32位平台下都是4G),所以链接器在链接可执行文件时,可以设定内存地址,而不用去管这些数据最终实际内存地址,这交给内核来完成映射关系
  2. 实现共享,当不同的进程使用同一段代码时,比如库文件的代码,在物理内存中可以只存储一份这样的代码,不同进程只要将自己的虚拟内存映射过去就好了,这样可以节省物理内存
  3. 提高利用率,在程序需要分配连续空间的时候,只需要在虚拟内存分配连续空间,而不需要物理内存时连续的,实际上,往往物理内存都是断断续续的内存碎片。这样就可以有效地利用我们的物理内存。

5.进程与线程的区别: 参考

进程:是程序的一次执行过程,是一个动态概念,是分配和管理资源的基本单位,每一个进程都有一个自己的地址空间,至少有 5 种基本状态,它们是:初始态,(执行态,阻塞状态,就绪状态),终止状态。

线程:是CPU调度和分派的基本单位,它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

线程是进程的一部分,一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。

区别:

根本区别进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位。

开销方面:每个进程都有独立的代码和数据空间(程序上下文),进程之间切换开销大;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小

所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行

内存分配:系统为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。

包含关系:线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

6.排序算法总结:参考1   参考2  python 实现

稳定:假设a=b并且a原本在b前面,排序之后,如果a还是在b的前面则稳定,反之则不稳定。稳定也可以理解为一切皆在掌握中,元素的位置处在你在控制中。而不稳定算法在两个相同值的排序上充满了未知性。

快速排序最差情况是:划分之后一边是一个,一边是n-1个,这种极端情况的时间复杂度就是O(N^2),即原序列为有序(正序,逆序)。使得二分没法实现。

快速排序最优情况是:最好的情况是每次都能均匀的划分序列,O(N*log2N),即能使得划分后的两边均匀,能进行二分下进一步排序。参考

冒泡排序最差情况:把顺序的排列变成逆序,或者把逆序的数列变成顺序,最差时间复杂度O(N^2)。
冒泡排序最优情况:最好的情况是数据本来就有序,只是遍历一遍复杂度为O(n)。参考

7.查找算法总结:python实现

哈希查找:以空间换时间,通过散列函数构建散列表。散列表构建时有可能会发生地址冲突,用拉链法和线性探测法等。参考

8.C++的map的基本原理:https://blog.csdn.net/city_to_sky/article/details/80042586

TreeMap是基于树(红黑树)的实现方式,即添加到一个有序列表,在O(log n)的复杂度内通过key值找到value,优点是空间要求低,但在时间上不如HashMap。C++中Map的实现就是基于这种方式

HashMap是基于HashCode的实现方式,在查找上要比TreeMap速度快,添加时也没有任何顺序,但空间复杂度高。C++ unordered_Map就是基于该种方式。

C/C++定义数组的几种方式

9.Java访问网络

10.测试分析和测试样例编写

https://blog.csdn.net/gents_hu/article/details/88054388

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值