testing
接口自动化项目流程:两种情况
1:如果后端开发整个接口逻辑已经开发完成: 1:熟悉app项目的主体功能,项目模块,项目的技术框架,熟悉app得基本流程 一:aview监控软件是一款手机监控摄像软件,软件功能强大,帮助用户更方便的进行家庭情况的健康, 软件通过远程的录像和监控,帮助你实时查看,非常的方便实用, 软件内为用户提供语音,对讲,视频,抓拍,录像等功能,帮助你更方便的进行各种监控和拍摄 二:AView主要功能模块简介 本项目包含以下模块 消息模块: 消息列表,系统消息列表,设备消息列表 分享模块: 设备历史分享记录,设备分享,分享详情,分享编辑 设备模块: 设备列表,设备分类,设备筛选及搜索,设备预览,设备操作,设备设置,设备详情 云服务模块: 云服务信息列表,云服务管理,在线支付 用户模块: 登录,注册,找回密码,本地录像管理,个人资料管理 三:项目技术简介: 开发模式:MVC,开发工具:Android Studio 后端开发技术:maven仓+SSH(struts2+spring+hibernate)整合三大框架,使用Mysql数据库 前端开发技术:vue3.0,高性能网络请求框架设计(Retrofit+RxJava+Glide) 2:从开发获取接口文档 3:接口文档评审: 熟悉接口鉴权机制,cookies或者token 查看接口风格:restful还是什么其他风格 查看接口的类型,同步接口还是异步接口 根据接口文档的每一个接口写一个正向的测试用例去尝试发一下请求, 看请求和响应的数据是不是正常 4:接口测试用例的编写:接口文档评审通过,那么就根据接口文档编写接口测试用例 根据必填参数,选填参数,填写参数的数据类型,参数的长度等使用等价类边界值错误推断法设计测试用例 测试用例必须包含接口请求的四大要素:url,请求方式,请求头哪些内容,请求体 还有一些模块模块名称,用例编号,预期结果等也要写在接口测试用例里 5:接口测试用例的评审:接口测试用例编写好了,就进行测试用例的评审,接口用例好了,接口文档也ok就进入接口脚本开发的阶段了 8:选择编码的语言和自动化的框架,报告的类型 python:3.6版本 pytest:测试框架 pytest框架优点: requests: 用requests来模拟http请求 allure 使用allure来展示测试报告 8:前期布局好测试数据的使用 接口测试用例我们选择放在excel表格里进行维护 一些全局的账号密码,项目部署环境的url,邮箱账户和密码,放在yaml配置文件或者py文件 对于一些一次性消耗的数据,比如注册,每次注册不一样的数,可以用随机函数生成 random模块 如果还有一些ui自动化元素定位的表达式可以放在yaml文件,数据和测试脚本的分离 还有一些少量的静态数据放在py文件的开头 9:确定整个项目的目录框架 data:存放测试用例的文件夹 tools:封装的第三方的工具代码的(excel读写,yaml的读写,md5加密,各种对称加密和非对称加密的函数) testcase:测试用例的库文件 log:日志存放在这里面 report:测试报告存放的目录 config:配置文件存放的目录 lib:存放封装的接口代码的 10:开发过程中还需要使用到一些第三方库需要导入:使用.bat批处理文件导入一下 pip install PyYaml 专门针对yaml文件操作的模块, xlrd 读excel模块 xlwd 写excel模块 pip install allure-pytest pytest的allure插件 pip install pytest-html pytest自带的html报告,不怎么使用 pip3 install pymysql 可能还涉及到一些mysql数据库的操作,安装pymysql pytest-xdist 能够实现接口的分布式测试,例有电脑的多核跑测试用例 11:开始正式的编码 先编写一些测试过程中需要用到的自定义的封装的第三方工具代码,excel表用例的读取,yaml文件的读取,md5加密,log日志的配置等 针对原始requests的post,get等请求方法做一个二次封装,重写请求函数,增加日志功能 编写某个模块的接口源代码的时候,需要考虑这个模块有没有前置条件,是不是需要登录才能进行接口的请求 一个模块最好编写一个类函数,看这个类函数里面所有的接口函数特点(模块里面所有接口url是不是一样的,(可以创建课程对象的时候就创建出来,定义成实例对象) 根据api模块写class测试类,比如用户的相关api编写一个user相关的类,注册,登录和退出和注销的class 设备的增,删,改,查,删除多台写个设备的class 根据每个模块编写相关的api接口类的代码 如果restful架构风格,用到put和delete,post和get(对应增删改查) 很多接口类的代码类似的话可以抽离出公共的方法写个baseapi的基类,便于维护 ---也可以不这样 class User(): 编写user类,里面实现登录和一些logou函数 class BaseAPI(): 库里面公共方法抽出来,放到一个公共基类里面,实际业务接口继承公共的类,类似po模式编写代码 请求的库文件写好了,我们可以根据接口文档的testcase写测试用例了, 每个测试用例之间进来做到独立没有关联关系,使用pytest的 测试用例的初始化和清除:@fixture, 做好每个接口的数据清除和环境初始化,每个接口测试完成后删除垃圾数据 还利用好pytest的参数化 @parametrize 实参数化, 各种测试用例打好mark标记 12:allure报告的优化 13:xxx.bat批处理文件一键执行跑起来 14:调试执行 15:结果分析 2:如果后端开发整个接口逻辑没有开发完成 这时候我们拿到接口文档 进行不了接口文档的评审了 为了让测试工作提前, 1:根据接口文档设计接口测试用例 2:接口测试用例评审ok 3:使用mock模拟技术先进行代码的编写 mock:最简单的是一个moco的jar包 需要安装java环境, 下载moco文件 java命令启一个服务 然后维护一个json文件编辑请求 mock只能做到简单模拟接口的收发请求,关联性太强的,接口的初始化和清除搞不定 4:等后端工程师api开发完毕就进入代码的调试和测试 aview的接口主要有: 1:用户的登录注册和退出,注销等 2:设备分享接口(多个,什么查询分享权限,增加设备分享,拒绝分享,同意分享等) 3:用户个设备的绑定等接口(绑定,解绑) 4:设备云套餐相关的(云开通,查询,续费,云转存等) 5:设备Ota相关的接口(查询ota升级路径) 比较记忆深刻的bug: app上添加设备后进行设备权限的分享,分享后在其他设备通过接口查看权限异常 云存储套餐使开通后,接口查询设备云存信息返回数据异常(显示设备未开通的状态) app本身功能测试 云视频播放断流, 最大的一次故障是ios app覆盖安装没问题,但是不能卸载安装
DDBBCCACDA YNYNNNYNYY
#1. 请写一个简单的装饰器函数. # def outer(a): # def func(func): # def inner(*args,**kwargs): # print('前置') # func(*args,**kwargs) # print(a) # print('后置') # return inner # return func # @outer(10) # def function(): # print('傻逼') # #function=func(function) # function()
#2. 有一个双端队列collections.deque,进行以下操作,请写出每一步操作之后q的元素内容 # from collections import deque # q=deque() # q.append(1) #[1] # q.appendleft(2) #左边添加 [2,1] # q.append(3) #默认后加 [2,1,3] # q.pop() #默认后删 [2,1] # q.popleft() #左删 [1] # q.append(1) #后(右加) [1,1] # q.appendleft(2) #左加 [2,1,1] # q.append(3) #后(右加) [2,1,1,3] # q.popleft() #左删除 [1,1,3] # q.append(3) # # q.popleft(1) #这个他妈的报错popleft不接受参数 # print(q) #
#3.用socket编写程序发起简单的http请求. 不会 import socket from urllib.parse import urlparse def get_url(url): url = urlparse(url) host = url.netloc path = url.path if path == "": path = "/" # 建立 socket 连接 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((host, 80)) client.send("GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n".format(path, host).encode("utf-8")) data = b"" while True: d = client.recv(1024) if d: data += d else: break data = data.decode("utf-8") html_data = data.split("\r\n\r\n")[1] print(html_data) client.close() pass if __name__ == '__main__': get_url("http://www.baidu.com")
#4.使用unittest或者pytest编写一个简单的测试用例,判断一个数是否大于0. # import unittest # nunber=int(input('>>>>>>')) # class MYtest200(unittest.TestCase): # def test_001(self): # assert nunber >0 # suite = unittest.TestSuite() # suite.addTest(MYtest200('test_001')) # runner=unittest.TextTestRunner() #实例化TestRunner类 # runner.run(suite) #执行用例
import pytest
def test_001():
num=10
assert num >0
print('执行test_001')
if __name__ == '__main__':
pytest.main(['test1.py'])
#5.使用线程、进程或者协程,编写一个简单的生产者消费者模型. # import threading # import time # a = [] # def foo(): # 不停生产数据 # while True: # a.append("1") # print("生产了一个数据") # time.sleep(1) # t1 = threading.Thread(target=foo) # 主线程启动一个子线程不停的生产数据,主线程继续运行,主线程消耗数据 # t1.setDaemon(True) #守护线程,主线程gg子线程也自动gg # t1.start() #启动线程 # def func(): # for i in range(10): # 主线程消耗数据,消耗10个数据 # if a: # 列表不为空才去消耗数据 # a.remove("1") # print("消费了一个数据") # time.sleep(1) # print("不需要再消费数据了") # func()
#6:linux下,统计所有处于ESTABLISHED状态下的连接数量. # netstat -an|grep "ESTABLISHED"
#7.mysql中,查看某个表的索引信息 # show index from 表名
#8.编写tcpdump或者wireshark过滤规则,抓取ip为1.2.3.4,port为12345的所有tcp数据包. #tcpdump -i et0 host 1.2.3.4 and tcp port 12345
#9.编写一个正则表达式规则,判断输入值是否是一个正确格式的ip地址. # srr_in=input('>>>>') # import re # res=re.search(r'((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)',srr_in) # #0-9 \d # #10-99 \d{2}或者[1-9][1-9] # #100-199 1\d\d # #200-249 2[0-4]\d # #250-255 25[0-5] # try: # print(res.group()) # except: # print('错误的ip地址')
#10.针对上一步写的正则表达式,应该从哪些地方进行测试分析和测试其正确性? # 输入的是一个0.0.0.0 -255.255.255.255的ip地址 # 根据等价类,边界值,错误推断法等写测试用例: # 等价类: # 根据输入的数据类型进行划分: # 有效等价类:0.0.0.0-255.255.255.255范围里的数字 # 无效等价类:输入非数字,比如字母,特殊字符,中文等 # 根据输入是否为空进行划分: # 有效等价类:0.0.0.0-255.255.255.255范围里的数字 非空 # 无效等价类:输入空 # 根据数据范围划分: # 有效等价类:四个数字,每个数字的范围都是0-255,我们每一位都输入一个0-255的数字,点连接起来 # 无效等价类:四个数字,每个数字的范围都是0-255,输入非0-255的数字 # 比如始输入小于0的大于255的 # 0.0.0.0是一个特殊的数据,需要测试 # 边界值:0 和255 # 0的边界:-1 0 1 # 255的边界:254 255 256 # 综合上面的测试用例: # 1:0.0.0.0-255.255.255.255范围里的数字 # 128.128.177.148 # 2:无效等价类:输入非数字,比如字母,特殊字符,中文等 # aaaa.b.ccc.dd # ****.^.%%%.$$ # 傻逼.脑掺.智障.牛逼 # a*傻逼.b^脑掺.智障cc%.d$牛逼 # 3:无效等价类:输入空 # 输入空 # 4:无效等价类:四个数字,每个数字的范围都是0-255,输入非0-255的数字 # -1. -1. -1. -1 # 777.777.777.77 # 6666.6666.6666.6666 # 5:边界-1 # -1. -1. -1. -1 # 6:0.0.0.0是一个特殊的数据,需要测试 # 0.0.0.0 # 7:边界1 # 1.1.1.1 # 8:边界254 # 254.254.254.254 # 9:边界255 # 255.255.255.255 # 10:边界256 # 256.256.256.256 # 无法做到穷举,只能尽量覆盖
#1. 用过哪一种自动化/性能测试工具,其主要优点和缺点. # 都是用postman或者python脚本进行自动化测试的 # 脚本需要懂代码,前期设计和开发周期比较长 # 脚本做自动化比较灵活,可以进行各种定制化 # 比如pytest框架+xdist+python+allure编写脚本: # 结合xdist支持分布式,多终端测试, # 支持分层级的环境初始化和清除(模块级别,包级别,类级别,函数级别) # 结合allure报告支持各种标签定制(一级标签,二级标签,三级标签)报告能做的有层次而且很漂亮 # 还可以使用mark标签定制执行测试用例(比如我只运行冒烟测试的用例,只执行回归测试的用例) # 还能实现接口自动化的数据驱动(参数化)
#2. 协程、线程和进程有什么区别. # 线程和线程的区别: # 地址空间和其它资源(如打开文件):进程之间相互独立,同一进程的各线程之间共享。某进程内的线程在其它进程不可见。 # 通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信 # 需要进程同步和互斥手段的辅助,以保证数据的一致性。 # 调度和切换:线程上下文切换比进程上下文切换要快得多。 # 在多线程操作系统中,进程不是一个可执行的实体。 # 同时操作一个对象的时候,比如操作的是一个全局变量,我用线程,因为全局变量是所有线程共享的。
#3:你用过哪些测试用例设计模式,具体是怎样实现的. # 等价类,边界值,错误推断发,因果图,判定发这些吗
#4. 性能测试中,如何查看被测系统的各种信息,以及性能指标是哪些
业务指标主要包括并发用户数、响应时间、处理能力,成功率这四个指标
通过后台日志log,采用分析工具也可进行分析得出TPS,响应时间等
#5:你是如何准备测试数据的,测试完成后这些数据如何处理. # 使用脚本进行python自动化的时候 # 一些必要的测试数据:比如测试用例放在excel表格里维护 # 一些环境级别的数据放在config文件来 # 一次性消耗的数据,比如注册,每次注册不一样的数,可以用随机函 数生成 # 对于少量的静态数据,比如一个接口的测试数据,也就 2-3 组,可以写到 py 脚本的开头, # 十年八年都不会变更的 # 对应测试过程中一些需要初始化的数据,比如测试一个电商系统 # 测试一件商品的增删改查, # 我们测试增加商品的时候,账户内是没有商品进行添加的 # 测试一个商品的删除的时候,账户内是必须要有商品才能进行测试的 # 测试商品的改查也是修养账户内是有商品的 # 但是做接口自动机的时候不能让testcase测试用例之间有太多的关联 # 不能增加这个接口增加了几件商品给后面的删除和查询使用 # 这样测试用例之间存在关联会参数垃圾数据对测试造成印象 # 而是关联性太强一个测试用例gg会影响到其他测试用例的进行 # 所以我们必须当测试用例之间独立化, # 这时候就需要充分使用到测试用例中的初始化和清除了 # 比如测试商品删除的接口的时候,我们需要初始化环境 # 先删除这个账户内所有商品,避免对当前增加操作参数影响 # 然后在添加几件商品来给删除接口提供数据,最后接口跑完了 # 再把测试中制造的垃圾数据进行清除 # -----数据的初始化和清除,保持测试用例执行前的环境清洁 # 并且制造进行测试的必要数据,测试用例执行完了后自动清除垃圾数据
#6. 执行自动化测试用例时,如何保证测试结果的正确性 # 接口自动化的时候根据接口的返回值进行assert断言 # 可以对各种返回数据进行断言,比如返回的状态码 # 返回的body,返回的头里面的数据也能进行断言操作 # 为了自动化脚本的结果的准确性: # 1:用例设计尽量独立化,不要关联性太强 # 2:执行测试用例的时候进行环境的初始化和清除 # 避免一些垃圾数据和一些情况对测试结果造成的影响 # 3:断言操作的时候可以选择多种情况进行断言,比如body和header一起断言 # 都用过才测试结果通过 # 4:如果有数据库的权限可以加一个数据库层面上的校验来断言测试是否通过
#7. web端自动化中,页面元素如果有延迟显示,如何确保找到该元素. # ui自动化就是找元素操作元素的过程,如果找不到就报错 # 我们可以使用driver.find_elements复数形式来寻找元素 # driver.find_elements返回一个list列表,如果列表不为空,代表找到了元素 # if list: 列表不为空就代表找到元素了,就可以进行下面的操作了
# 8.在web端测试中,如果某个功能出现异常,如何定位前端/后台问题. # 使用fiddler进行抓包,对比前后端发送的数据 # 如果操作前端发送的数据和接口文档一样就证明是后端返回数据的问题 # 如果前端发送的数据和接口文档有差异就是前端的问题
#9. 如何根据性能测试结果定位相关问题. 不会
#10:python中的requests库,如何配置请求头,cookies等参数. # 比如通过一个登录接口获取到cookies # login_cookies=login() # 一:如果我们获取到这个cookie,不需要二次封装 # 我们直接cookies=login_cookies # 把获取到的这个cookies对象直接传进去就可以了 # resp=request(url,headers=headers,cookies=login_cookies) # 二:如果需要在cookie封装一些其他信息 # 比如user_cookie={"sessionid":user_sessionid,"name":"xxxx"} # 需要cookie里添加一些信息这种情况可以获取到cookie里面的重要数据sessionid # 然后把sessionid传递进去自己封装一个user_cookie # 再把user_cookie传递到请求里 # resp=request(url,headers=headers,cookies=login_cookies) # 三:cookie信息还能放在headers头里进行传递 # headers = { # 'user_agent':'xxxx' # 'cookie': 'xxxx' # } # # 设置请求头,字典的格式 # header里封装好cookie,通过headers=headers在请求里进行传递 # resp = request(url, headers=headers, cookies=login_cookies)