当前位置:   article > 正文

软件测试面试常见问题总结(持续更新ing)_软件测试面试官笔试后面试问什么问题

软件测试面试官笔试后面试问什么问题

一、语言基础类

1.重写、重载和重构的区别

重写:子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写(重写的方法和父类的方法名称一定要相同,参数的类型、个数也要相同)。方法重写又称方法覆盖。
重载:简单说,重载就是函数或者方法有同样的名称,但是参数列表不相同,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法(发生在同一类中,方法名相同,参数列表()不同) 。
在这里插入图片描述

2.python多线程有关知识

python多线程详解

3.python正则表达式有关知识

python正则表达式详解

二、计算机网络类

1.cookie和session的区别

(1)cookie数据存放在客户的浏览器上,session数据放在服务器上
(2)cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,如果主要考虑到安全应当使用session
(3)session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用cookie
(4)单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的cookie不能3K。
(5)所以:将登陆信息等重要信息存放为session;其他信息如果需要保留,可以放在cookie中

2.http相关问题

问题一、 http的请求方法有哪些?其中get和post的区别?
答:GET,POST, HEAD, OPTIONS,PUT, DELETE, TRACE 和 CONNECT 方法。

get和post区别:

  1. 一般来说GET是获取数据,POST是提交数据的。但是因为GET和POST都是HTTP的方法,HTTP又是是基于TCP/IP的关于数据在万维网中 如何让通讯的协议。所以本质上来说GET和POST请求是没有区别 的,都是TCP链接。他们能做的事情是一样的。
  2. GET传输数据的时候是在URL地址中的、对所有人都是是可见的、是不安全的、是有浏览器缓存记录的。所以说GET是不安全的,发送密码等数据的时候不要用GET传输。
    GET只能传输ASCLL字符,不能进行编码。
    POST传输的时候是放在HTTP的请求体之中的,并且是经过urlencode编码的所以是相对安全的。
    POST是没有对数据类型的限制的,二进制数据也是可以的。
  3. HTTP协议并没有对GET和POST的长度做限制,其实是浏览器限制了他们传输大小。
    URL地址是有长度限制的,浏览器不同长度限制的具体数值也是不一样的。比如IE是2083字节。需要注意的是这些仅仅是URL地址栏的长度限制。
    理论上来说POST的长度是没有限制的,但是受服务器的配置限制或者内存大小的限制,造成了实际开发中POST也是有数据长度的限制的。

问题二、http的状态码有哪些?
答:常用的状态码如——200:请求成功、302:重定向、403:服务器拒绝请求、404:服务器找不到请求的网页、503:服务不可用
在这里插入图片描述
问题三、http的请求头部有哪些?
请求头名称 作用
Host 主机IP地址或域名
User-Agent 客户端相关信息,如操作系统,浏览器等信息
Accept 指定客户端接收信息类型,如image/jpg等
Accept-Charset 客户端接收的字符集
Accept-Encoding 可接受的内容编码
Accept-Language 接收的语言
Authorization 客户端提供给服务器,进行权限认证的信息
Cookie 携带的Cookie信息
Referer 当前文档的URL, 防止盗链
Content-Type 实体头内容类型
Content-Length 数据长度
Cache-Control 缓存机制
Pragma 防止页面被缓存

3.为什么是三次握手而不是两次握手

1:由于 TCP 是一个双向通信协议, 通信双方都有能力发送信息, 并接收响应。 因此, 通信双方都需要随机产生一个初始的序列号, 并且把这个起始值告诉对方。

2:同步序号

3:两次的话只有客户端的序号被确认了,服务器端的序号没有被确认。

4:tcp是可靠的面向连接的传输方式,但是如何保证这种方式呢,那就是通过同步一个序列号来就行的,通过这个序列号可以实现重复数据刷掉,以及丢包重发的功能,保证了数据的完整性和数据传输的可靠性,以及数据包之间的有序性

5:但是这种功能的实现依赖于syn(synchronize sequece number) ,可以理解成一个1个1位的数据包,专门用于同步序列号的。

也就是说如果客户端要与服务端建立连接都要发送syn,然而根据tcp建立连接的方式:

客户端在发送一个连接请求的时候(syn)服务端会发送一个确认信号,这是还需要客户端继续发送一个确认信号,但是如果这个时候客户端不发送确认信号,服务端会在限制时间内继续发送确认信号,这样会大大的消耗服务器资源

三、操作系统类

1.进程有哪几种状态

(1) 运行态(Run): 进程占有处理机资源,正在运行。 显然,在单处理机系统中任一时刻只能有一个进程处于此种状态;

(2) 就绪态(Ready): 进程本身具备运行条件,但由于处理机的个数少于可运行进程的个数,暂未投入运行。 即相当于等待处理机资源;

(3) 等待态(Wait): 也称挂起态(Suspended)、封锁态(Blocked)、睡眠态(Sleep)。 进程本身不具备运行条件,即使分给它处理机也不能运行。 进程正等待某一个事件的发生,如等待某一资源被释放,等待与该进程相关的I/O传输的完成信号等。

(4) 创建状态:进程正在被创建,操作系统为进程分配资源。

(5) 结束状态:进程正在从系统中撤销,操作系统会回收进程拥有的资源。

2.进程与线程的区别

(1)概念
进程
一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,一个进程可以有多个线程,比如在Windows系统中,一个运行的xx.exe就是一个进程。

线程
进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。

(2)区别
根本区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位

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

包含关系:如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

内存分配:同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的

影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。

执行过程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行

3.多线程会出现哪些问题

由于线程之间是进行随机调度,并且每个线程可能只执行n条执行之后,当多个线程同时修改同一条数据时可能会出现脏数据,所以出现了线程锁,即同一时刻允许一个线程执行操作。线程锁用于锁定资源,可以定义多个锁,当需要独占某一个资源时,任何一个锁都可以锁定这个资源,就好比你用不同的锁都可以把这个相同的门锁住一样。
如果有多个线程同时操作一个对象,如果没有很好地保护该对象,会造成程序结果的不可预期,我们因此也称为“线程不安全”。

锁(LOCK):锁对象一旦创建,就可以随时被进程或者线程调用,并且一次创建锁只有一把,如果多个资源想同时获取锁,必须‘排队’,等上一个进程/线程释放了锁才可以请求获取锁

单纯的锁可能会出现死锁问题:

  1. 当一个进程或者一个线程一直调用或者占用同一锁Lock而不释放资源而导致其他进程/线程无法获得锁,就会出现的死锁状况,一直阻塞在aquire()处
  2. 当有两个进程同时想获取两个锁的时候(再往上推就是多个进程想获取多个锁),由于两者都是出于竞争关系,谁也不让谁,谁快谁得手,但计算机中这种竞争关系是很微妙的,时间的差异性很小,于是,就出现了两者都阻塞在同一个地方,都无法同时获得两个锁或者获取对方已经获取的但还没有释放的锁。
    为解决此问题,引入了可重入锁

可重入锁(RLOCK):重入锁定义后,一个进程就可以重复调用指定次数的一个重入锁,而不用去跟别的进程一起争夺其他锁。
全局解释锁(GIL):其实Python的CPython(C语言实现的)解释器上有一把GIL锁,也就是说Python的程序是处于一个解释器锁的环境中的。GIL是Python解释器层面的锁,解决解释器中多个线程的竞争资源问题。因为GIL的存在,在Python中同一时刻有且只有一个线程会执行,所以Python中的多线程被称为“伪多线程”。

4.linux相关问题

问题一、linux查看文件内容的指令
more(分页查看)、less(可上下滚动查看)、head -n(显示前n行)、tail -n(查看后n行)、cat(内容过多时只会显示最后一屏内容)

四、数据库类

1.数据库视图

作用:简化操作、安全、逻辑独立
详见 数据库视图详解

2.数据库索引的类型?索引的作用

普通索引:
基本的索引类型,没有唯一性限制,允许为NULL值,不可以被引用为外键,一个表可以有多个普通索引

唯一索引:
数据列不允许重复,允许为NULL值,不可以被引用为外键,一个表允许多个列创建唯一索引

主键索引:
数据列不允许重复,不允许为NULL,可以被引用为外键,一个表只能有一个主键索引

聚集索引:
在聚集索引中,表中数据行的物理位置与逻辑值(索引和数据为同一个文件)的顺序相同,一个表中只能包含一个聚集索引,因为物理顺序只能有一个。聚集索引通常提供更快的数据访问速度。

覆盖索引
组合索引
全文索引

索引的作用:
1.提高数据查找速度提高
2.提高group by、order by分组与排序的速度

2.数据库的事务

定义:事务就是一个对数据库操作的序列,是一个不可分割的工作单位
特性:原子性 (Atomicity) 一致性(Consistency)持久性(Durability) 隔离性(Isolation)
解释:
(1)原子性:事务的原子性是指一个事务是一个不可分割的工作单位,要不全部执行,要不全部不执行。
作用:当出现一个完整任务里因意外状况只执行了一半的情况时,会回滚到事务未执行前
(2)一致性:一致性是指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
作用:比如从同一个银行一个账户向另一个账户转账的事务,要保证银行中的总金额保持不变的约束条件
(3)持久性:持久性即当一个事务提交后,对数据库的改变是永久性的,不会被回滚。
实际实现事务对数据库的改变时,会首先写入事务日志。如果数据库发生意外,重启服务后会首先检查日志,将应做却没做的改变持久化到数据库。
(4)隔离性:事务隔离性是指多个事务并发执行时,相互之间无影响。
数据库通过分事务隔离级别来避免事务之间的影响(脏读、不可重复读、幻读、丢失更新)
隔离级别(由低到高):未提交读、已提交读、可重复读、可串行读
在这里插入图片描述
具体实现而言,数据库通过锁来实现隔离级别。
参考:数据库事务1
数据库事务2

3.数据库语句

详见Mysql数据库的使用

五、数据结构类

1.队列和栈的区别,如何用栈实现队列?

队列:先入先出,从一端进,从另一端出。list.append()在列表尾部添加新值,list.pop(0)从列表开头弹出旧值。这样的形式就是队列的结构。python中也有专门的队列格式,即deque。
栈:后入先出,只能从一端进出。在python中的列表的默认结构就是类似栈的结构,list.append()在列表尾部添加新值,list.pop()从列表末尾弹出旧值。

栈实现队列:利用双重栈思想。以列表模拟栈,添加新值到列表A中,再将A的值pop出作为列表B的新值,如此一来,B pop弹出的值的顺序就和添加新值到A的顺序一致了。

2.链表

六、编程类

1.判断一个数组是不是另一个数组的全排列且不相同,是则返回True,不是则返回False。
def judge(A:list,B:list):
    if A ==B:
        return False
    else:
        A.sort()
        B.sort()
        if A ==B:
            return True
        else:
            return False

if __name__ =='__main__':
    A =['a','b','b','c']
    B =['a','b','c']
    print(judge(A,B))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
'
运行

这里有一个很容易出错的问题,我面试的时候就是这个地方出问题却没发现:
列表的排序有两种方法,其中[xxx].sort()改变的列表本身,而不会返回一个新的值,所以用new ==[xxx].sort()得到的结果其实是None。
另外一种是sorted([xxx]),这种方法会产生一个新的值,需要赋值使用。

2.跳台阶问题

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

class Solution:
    def jumpFloor(self, number):
        if number<= 2:
            return number
        fOne =1
        fTwo =2
        for i in range(number-2):
            fNew =fOne+fTwo
            fOne =fTwo
            fTwo =fNew
        return fNew
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
'
运行

思路:n阶台阶,因为只有两种跳法,所以总次数f(n) =f(n-1)+f(n-2)。
实际到代码层面,因为f(n) =f(n-1)+f(n-2),f(n-1) =f(n-2)+f(n-3)…直到最后f(3) =f(2)+f(1),此为最小单位。于是我们从最小单位开始算,fOne和fTwo的初始值1,2为最小单位,两者之和作为新的fTwo,原本fTwo的值作为新的fOne的值,这样就是f(4) =f(3)+f(2)…如此类推。循环n-2次后就得到了总次数。
注意:这个问题其实也可以用递归来写,思路会简单很多,但是递归会消耗大量资源,时间复杂度太高,在有要求的笔试中是不会通过的。

3.合并两个有序数组

注意:
1.保证 A 数组有足够的空间存放 B 数组的元素, A 和 B 中初始的元素数目分别为 m 和 n,A的数组空间大小为 m+n
2.不要返回合并的数组,将数组 B 的数据合并到 A 里面就好了
3. A 数组在[0,m-1]的范围也是有序的

例1:
A: [4,5,6,0,0,0],m=3
B: [1,2,3],n=3
合并过后A为:
A: [1,2,3,4,5,6]

方法一:
这个方法很简单,但是很蠢,完全没有利用到有序这个条件。虽然是对的,面试官也不会满意。

class Solution:
    def merge(self , A, m, B, n):
        for i in range(n):
            A[m+i]=B[i]
        A.sort()
        return A
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
'
运行

方法二:
这个方法的核心思想是三个指针,分别从A、B、和A扩容后的数组末尾的位置开始,循环比较A和B中的最大值(即倒数第一位),将最大值放到扩容后数组的末尾。之后,如果B中的指针计数还存在,即B中存在元素没有挪过来,那么需要再次循环B中剩余的元素,替换到A扩容后的数组中。

class Solution:
    def merge(self , A, m, B, n):
        i =m-1
        j =n-1
        k =m+n-1
        while i>=0 and j>=0:
            if A[i]>B[j]:
                A[k] =A[i]
                i -=1
                k -=1
            else:
                A[k] =B[j]
                j -=1
                k -=1
        while j>=0:
            A[k] =B[j]
            k -=1
            j -=1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
'
运行
4.两数之和

给出一个整型数组 numbers 和一个目标值 target,请在数组中找出两个加起来等于目标值的数的下标,返回的下标按升序排列。
例如:
给出的数组为 [20, 70, 110, 150] , 目标值为90
返回一个数组 [1,2] ,因为 20+70==90

#两个循环,注意range里的范围有讲究以及返回的数组下标是从1开始数的。
class Solution:
    def twoSum(self , numbers , target ):
        for i in range(0,len(numbers)-1):
            for j in range(i+1,len(numbers)):
                if numbers[i] +numbers[j] ==target:
                    result =[i+1,j+1]
                    return result
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
'
运行

七、用例设计类

1.手机支付宝支付设计测试点

付款方式
扫码(扫码识别时间、支持扫描相册图片里的二维码、同屏出现多个二维码处理逻辑)
转账(转给支付宝账户/手机号、转给各个银行卡、输入框校验)
付款码(金额限制、多次扫描限制、存在时间限制、无网络状态能否使用、已过期的二维码能否使用)

支付确认手段
密码(正确、错误、不输、复制粘贴限制、多次错误锁定)
指纹(正确、错误、多次错误锁定)
人脸识别(正确、错误、正确的人但是状态错误(平面图像、闭眼等)、多人同框优先识别谁)

付款来源
余额、花呗、各个银行卡、余额宝能否支付成功

金额限制
金额0,0.01,超大额,-1。能否输入非数字字符。
各个付款来源不足以支付金额时能否支付成功

支付过程
已确认支付后突发异常情况(断网、网络状态切换、强行关机、接电话、跳出应用等)
考虑并发情形(原本支付来源的金额足够,但是在支付过程中,在另外一个途径同时出现对支付来源的扣款可能导致金额不足时,发生什么;
原本支付来源的金额不够,但是进入支付页面后,在另外一个途径同时出现对支付来源的汇款导致金额足够时,能否成功支付)

页面显示
文字信息正确、提示信息正确等

八、自动化框架细节类

1.xpath模糊搜索怎么写

contains(a, b) 如果a中含有字符串b,则返回true,否则返回false
starts-with(a, b)如果a是以字符串b开头,返回true,否则返回false
ends-with(a, b)如果a是以字符串b结尾,返回true,否则返回false

driver.find_element_by_xpath("//div[contains(@id, 'xxx')]")
driver.find_element_by_xpath("//div[starts-with(@id, 'xxx')]")
driver.find_element_by_xpath("//div[ends-with(@id, 'xxx')]") 
  • 1
  • 2
  • 3
本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号