面试总结1:较多的http问题

第一次面试:tuzhan

你的自动化脚本是怎么写的

  • 我写自动化主要实现的功能是不同并数进行自动化测试
  • 我就把shell脚本实现的逻辑讲了,定义一个jmx的模板文件,写一个傻掉jmeter进程的函数,通过awk,grep获取特定的jmeter的pid,用kill pid删掉,作用是假设你要运行60秒,但可能jmeter60秒后还有些请求需要发送,来不及发送出现卡顿,避免下次重复执行jmeter压测
  • 接下来定义一个并发数的数组,用for循环拿到数组的值,比如第一次循环拿到100,定义新的jmx文件,名字加上100,定义新的jtl文件,名字加上100,复制jmx的模板到新的jmx文件,当心的jmx运行完毕之后,就可以删除jmx文件,模板的jmx可以不用删除。我们的jmx文件是先删除,后复制,因为可能之前运行了,没有删除
  • 用nohup &后台运行jmeter,配上jmx和jtl,sleep时间比运行之间长一点,运行结束后杀掉进程
  • 最终脚本运行完毕后,只会留下jtl的报告,用jmeter打开就可以获取不同并发下的数据了

你对性能测试了解有多少

  • 讲了一下参数化,接口参数传递,聚合报告主要的指标,顺带提了一下可以结合influxdb grafana设计一个测试环境的接口监控。目的是为了及时发现开发接口可能发生的拓展和更新。性能深层次的不太了解,因为项目不太需要

你所写的自动化性能测试的脚本,仅仅是自动跑不同的并发数,我用一个jmeter的一个插件就可以实现

  • 的确可以通过插件的方式实现不同并发量的测试,但是聚合函数记录的是一个总的数据,假设并发数是100,200,300,只能记录三者共同的响应时间、错误率、吞吐量(Throughput),无法记录单独并发的聚合报告的数据
  • 想要解决这个问题可以搭建influxdb+grafana环境,我们只需要选取我们测试的时间段,就可以记录不同并发独自的数据了
  • 我之所以会写这个脚本,是因为我的电脑使用这个插件有些问题,并发数设置的数量并不对

jmeter聚合报告的流量是怎么计算的

  • 这个是叫吞吐量(throughput),是每秒完成的请求数
  • 计算的公式有两个:
    • 吞吐量=并发数/请求的平均响应时间s,例子:假设有10个并发,请求响应时间是47ms,TPS=10/(47/1000)
    • 吞吐量=总的请求数量/总的请求时间,例子:

加密方式有哪些

  • 普通的加密:base64
  • 不可逆的加密方式:MD5,sha1,sha1安全性高,速度慢
  • 有对称式加密:DES,AES
  • 非对称式加密:RSA

http的无状态是什么意思

  • 每一次请求之间是没有关联的,比如我登录了之后,给服务器发送了账户名和密码,返回了登录的界面,下次我想再请求登录后的界面,服务器就不认识我了,因为服务器不知道客户端是谁,客户端没有携带任何信息证明自己

cookies和session的区别是什么

  • cookies是保存在客户端的,session是保存在服务器端的,当我们登录了之后,服务器会把session-id给到客户端的cookies中。当客户端再发送请求,客户端就在cookies中携带这个session-id给到服务器
  • session-id如果存在redis中,key通过是固定死的,比如就叫session-id,服务器就拿session-id的value进行检验比对,识别到客户端的身份

那服务器是怎么比对session-id的

  • session-id如果存在redis中,key通过是固定死的,比如就叫session-id,服务器就拿session-id的value进行检验比对,识别到客户端的身份

cookies里面有什么内容

  • 有session-id,识别用户身份
  • 有token,识别用户身份
  • 有Domain:域,cookies在哪个域名下有作用
  • 有Path,表示哪些路径下的目录有权限读取
  • 有Expire time有效期时间
  • secure,表示必须用https传输的cookies才有效
  • 有http only,只允许http和https传输,无法使用js脚本,防止xss跨脚本攻击
    • 反射型XSS,通过邮件或者其他方式,给用户链接,用户点击链接后,就会自动运行链接的js脚本,达到获取cookies或者其他攻击
    • 存储型xss,用于论坛,博客,黑客把js代码直接留言到论坛或者博客,可以保存这些js代码到数据库,当其他用户访问论坛,浏览器就会自动读取当前页面的js代码,实现攻击

如何判断跨域,cookies跨域是怎么处理的

如何对一个{“name”:“age”}的字典去进行排序


def test_a():
    name={"abc":200,"aaa":19,"bbb":30,"ddd":25,"qec":100}
    print(len(name))
    result=[]
    for i in range(len(name)):
        new_age=0
        new_name=""
        for b,a in name.items():
            if a>new_age:
                a,new_age=new_age,a
                new_name=b
            # else:
            #     a,new_age=a,new_age
        result.append((new_age,new_name))
        name.pop(new_name)
    print(result)

#对key进行排序
def test_b():
    name={"abc":200,"aaa":19,"bbb":30,"ddd":25,"qec":100}
    for i in sorted(name):
        print(f"{i},{name[i]}")

#对value进行排序
def test_b():
    name={"abc":200,"aaa":19,"bbb":30,"ddd":25,"qec":100}
    print(name.items())
    #从大到小进行排序
    a=sorted(name.items(),key=lambda x:x[1])
    print(a)
    #从小到大进行排序
    b=sorted(name.items(),key=lambda x:x[1],reverse=True)

#对key进行排序
def test_b():
    name={10:200,"aaa":19,"bbb":30,"ddd":25,"qec":100}
    print(name.items())
    #从大到小进行排序
    a=sorted(name.items(),key=lambda x:x[0])
    print(a)
    #从小到大进行排序
    b=sorted(name.items(),key=lambda x:x[0],reverse=True)

def test_c():
    a=[5,9,30,20,60,9,7,100]
    new=0
    for i in range(len(a)-1):
        for j in range(len(a)-1-i):
            if a[j]>a[j+1]:
                a[j+1],a[j]=a[j],a[j+1]
    print(a)

token有什么作用

  • token是令牌,做认证的,可以替代session-id,session-id存在会给服务器带来存储的压力,例如如果你的用户数是亿级的,压力非常大
  • token可以解决这个问题,服务器不去存储token,当客户端把账号密码提供后,服务器就会根据服务器和密码和过期时间做一个加密,形成一个token发给服务器,服务器如果收到了这个token,就会进行解密,可以获取用户名,密码和过期时间,来识别身份
  • token可以防止表单的重复提交,原理不懂
  • token还可以防止CSRF跨站请求伪造
    • CSRF的攻击是用户登录了一个银行网站,保存了cookies,当访问不良的网站,会触发CSRF攻击,自动给黑客转账
    • 原理是不良网站会嵌入一个post请求,包括了转账的url,转账人和金额的表单,而且把这个内容提交设为不可见,或者高度和宽度都为0,post请求还是访问网站就立马提交,非常高效和高隐蔽性
    • 只要token不存储在cookies,把token放在头部,当CSRF触发时,提交的信息没有包括token,服务器就会拦截
    • 当然也可以用refer来预防,因为CSRF请求的源地址不是银行的转账url,refer地址与CSRF地址不一致,服务器就拒绝此次请求

token是怎么解密的,解密方式是什么

  • token包括header,保存加密方式等信息,用base64进行加密获取加密后的header值
  • token包括payload,保存用户非私密信息,用base64加密获取加密后的
  • token包括签名信息,利用自定义的secret秘钥,对加密后的header和payload的值进行字符串合并,然后用SHA256进行加密,获取签名信息,签名信息无法逆向解密,还可以防止header和payload被篡改
  • token=加密后的header+加密后的payload+签名
  • 当服务器把token给客户端,客户端发送token给服务器,服务器会对对header和payload进行解密,查看是否符合要求
  • 然后对加密后的header和payload进行SHA256加密运算,如果获取的签名值和客户端发来的token签名值一致,表示认证通过

为什么charles装了证书,就可以抓包了,其中的原理是什么

  • 证书的内容包括了公钥、过期时间、认证的机构名、指纹加密算法、证书的序列号、指纹,,指纹是证书其他内容用指纹算法进行hash加密获得的值,然后用CA机构的私钥去加密指纹,获得签名。证书就包含了之前的内容+签名了
  • 客户端收到了数字证书后,会去浏览器查看有没有对应的CA,如果有就用CA的公钥对签名进行解密,获取指纹,对比证书里面的指纹,如果一致,表示证书是对的,就可以拿到服务器的公钥的
  • 如果证书内容被篡改,或者的指纹也不一样,黑客由于没有CA的私钥,只能用自己的私钥对指纹进行加密获得签名。客户端获取黑客的证书,用CA的公钥解密获得指纹,这个指纹与证书的指纹进行对比,发现不一致,证书是假的。因为我们只信任CA的公钥,不信任黑客的公钥
  • charles作为代理,当客户端访问百度的时候,charles作为服务器接收请求百度的内容,再讲这些内容作为请求发给百度服务器,百度服务器响应的内容先给到charles,charles再把响应信息给到浏览器,这时候出现了问题,浏览器并不知道charles是不是百度的服务器
  • 所以在浏览器请求之前,浏览器先装上charles的证书,也就是信任charles作为CA机构,charles返回百度的响应,会伪造百度的数字证书。客户端拿到伪造的证书,会去CA查看,用charles的CA证书去验证伪造的百度证书,认证当然成功,因为浏览器信任了charles的根证书,所以charles伪造百度证书成功,浏览器就默认charles是百度的服务器。双方就进行请求和响应的操作了

selenium的原理是什么

  • python和java的代码就是client端,driver就是一个服务器端,不同的浏览器有不同的driver,他们通过http传递selenium的代码,driver接收到代码就会转化成浏览器能识别的api接口,driver再充当客户端,把这些api接口的操作通过http发送给浏览器,浏览器就会执行api接口,并返回执行成功与否,服务器收到这些内容再把操作结果发给client端,client执行下一段代码,driver也相当于一个代理服务器

上传文件的用例怎么设计

  • 功能测试
    • 符合要求的文件上传成功
    • 上传成功的文件名显示正常
    • 可查看、下载上传成功的文件
    • 删除上传成功的文件
    • 替换上传成功的文件
    • 上传文件是否支持中文
    • 文件路径是否可手动输入
    • 手动输入正确的文件路径上传成功
    • 手动输入错误的文件路径上传失败
  • 文件大小测试
    • 文件大小为0kb的文件上传成功
    • 文件大小等于限制大小上传成功
    • 文件大小略小于限制大小上传成功
    • 文件大小大于限制大小上传失败
    • 上传的文件大小超过剩余的存储空间,上传失败
    • 上传文件时空间已满,无法继续上传有内容的文件
  • 文件名称测试:
    • 文件名过长无法上传成功
    • 文件名称达到最大限制上传成功
    • 文件名包含特殊字符看需求
    • 文件名全为中文,英文或者中英混合
  • 文件格式测试
    • 上传正确的格式
    • 上传不允许的格式,无法上传
  • 界面测试
    • 上传成功提示语正确
    • 上传失败提示语正确
    • 说明性文字是否正确
    • 界面美观性
  • 性能测试
    • 弱网下的测试
    • 不同3G、4G网络测试
    • 上传过程中断网,提示是否正常
  • 安全测试:
    • 上传exe文件
    • 上传木马文件
    • 没有授权的用户是否可以访问或者下载文件或者删除文件
    • 文件误删除是否有数据备份,回收站恢复的功能
  • 其他测试:
  • 断网后,重新连接网络会不会上传
  • 在后台运行会不会上传
  • 来中断的时候会不会上传成功,比如电话、闹钟、短信
  • 程序关闭后,文件是否会继续上传
  • 在非wifi环境下,用流量下载是否有提示:在非wifi情况下,是否继续上传文件

装饰器你的了解有多少,装饰器加参数,或者函数加参数怎么设计

  • 装饰品实际上是一个闭包函数,一般设计为了复用之前的功能,通过外层函数传参,内部函数参数为需要实现的其他函数名,最内层函数通过*args,*kwargs接受其他函数参数
  • 源函数带参数和返回值的处理
import time
# 被装饰的函数带有返回值和参数的处理方式
def log(func):
    # 内层函数需要传入参数,但不知道参数传入什么,所以使用万能的方式,*args,**kwargs
    def improve_func(*args, **kwargs):
        start_time = time.time()
        # 可以确保源函数也有参数传入
        # 函数有返回值,直接给一个返回值ret
        ret = func(*args, **kwargs)
        end_time = time.time()
        print(f"运行的时间为:{end_time - start_time}")
        # 最后返回ret即可
        return ret

    return improve_func

@log
def a(b=100):
    for i in range(100000):
        b += i
    return b

def test_a():
    print(a(20))
  • 装饰器本身带参数的简单写法
import time
# 装饰器带参数的写法
# 在最外层加入参数
def log(info="默认参数"):
    # 里面一层才是正常的装饰器的写法
    def inter_log(func):
        # 内层函数需要传入参数,但不知道参数传入什么,所以使用万能的方式,*args,**kwargs
        def improve_func(*args, **kwargs):
            start_time = time.time()
            # 可以确保源函数也有参数传入
            # 函数有返回值,直接给一个返回值ret
            ret = func(*args, **kwargs)
            end_time = time.time()
            print(f"运行的时间为:{end_time - start_time}+{info}")
            # 最后返回ret即可
            return ret
        # 先返回最内层的函数
        return improve_func
    # 再返回最外层的函数
    return inter_log

@log(info="通通")
def a(b=100):
    for i in range(100000):
        b += i
    return b

def test_a():
    print(a(20))

三次握手和四次挥手你的理解

  • 我说了三次握手是通过三次握手,刚刚好让客户端和服务器都具备接收和发送的功能,然后面试官就结束了,我说三次握手就这样结束了,后面他想问的点没get到

你是怎么做安全测试的

  • 用的是ZAP的工具,这个工具比较傻瓜化,直接登录我们的网站,然后就和正常的网站进行操作,工具会自动帮我们录制脚本,自动跑安全

这个工具的原理是怎么样的,他们是怎么自动化做的安全测试

  • sql注入:在输入框输入sql相关语句,获得
    • 比如一个登录界面,输入账号密码,登录成功需要输入正确的账号和密码,select * from user where username=‘admin’ and password=‘xxxx’,只有两个条件都满足才能登录成功,在用户名输入admin’ or 1=1 – ,select * from user where username=‘admin’ or 1=1 – 'and password=‘xxxx’,后面的密码就会被注释,1=1永远为真,select执行成功,登录成功,或者获取所有的用户名信息的表格
  • xss攻击:
    • 反射型XSS,通过邮件或者其他方式,给用户链接,用户点击链接后,就会自动运行链接的js脚本,达到获取cookies或者其他攻击
    • 存储型xss,用于论坛,博客,黑客把js代码直接留言到论坛或者博客,可以保存这些js代码到数据库,当其他用户访问论坛,浏览器就会自动读取当前页面的js代码,实现攻击
  • CSRF攻击:
    • CSRF的攻击是用户登录了一个银行网站,保存了cookies,当访问不良的网站,会触发CSRF攻击,自动给黑客转账
    • 原理是不良网站会嵌入一个post请求,包括了转账的url,转账人和金额的表单,而且把这个内容提交设为不可见,或者高度和宽度都为0,post请求还是访问网站就立马提交,非常高效和高隐蔽性
    • 只要token不存储在cookies,把token放在头部,当CSRF触发时,提交的信息没有包括token,服务器就会拦截
    • 当然也可以用refer来预防,因为CSRF请求的源地址不是银行的转账url,refer地址与CSRF地址不一致,服务器就拒绝此次请求

你的po模式是怎么写的

Po模式大家都知道,你要把po模式的层次感描绘出来,为什么这么设计,需要听听课

你还有什么问题

  • 问一下公司的薪资结构和绩效
  • 问一下公司的涨薪+升职的途径
  • 询问岗位信息,我们到岗了之后要从事什么样的工作
  • 公司的测试技术栈是什么,公司用到的是什么架构的技术
  • 服务器管理权限,本机家算计管理权限
  • 针对员工有哪些培训和提升计划
  • 团队正在经历的尚未解决的挑战是什么
  • 团队内和团队之间如何沟通,比如测试团队和开发团队

总结一下你过去的工作,然后现在是想做软件测试,写几个能体现学到的东西的demo,主要是让面试官感受到你的真诚跟上进心

16 个赞

建议分类呀

我裂开了 为什么会考这么多

下面这个是不是写错了? name这个字典中, 如果key既存在int型, 又存在str, 应该无法使用sorted函数排序吧?

如何对一个{“name”:“age”}的字典去进行排序

#对key进行排序
def test_b():
    name={10:200,"aaa":19,"bbb":30,"ddd":25,"qec":100}
    print(name.items())
    #从大到小进行排序
    a=sorted(name.items(),key=lambda x:x[0])
    print(a)
    #从小到大进行排序
    b=sorted(name.items(),key=lambda x:x[0],reverse=True)