接口+接口自动化

接口测试需要验证数据库么?

有的接口会返回很多数据,有的接口可能就返回一个状态码及success之类的消息,这些需要验证数据库么?现在在写一个测试框架,配置接口参数和预期返回值,生成xml文件管理用例,用一个比较方法对预期和返回作比较,不需要根据每个接口写脚本,现在的疑惑只是比较返回值,并不清楚接口是否真的成功了,比如删除之类的接口,返回说成功了,但数据是否真的删除了?如果要验证数据库,感觉得为每个用例写脚本去验证了,这就和初衷不符(只写个比较函数,比较返回的所有值,不需要为每个接口单独验证)。

不少同学在做自动化是都会问要不要验证数据库?我的答案是不要!

根据分层自动化测试的概念。

UI层自动化模拟的是用户操作,假设我是一个普通的用户,在你家的系统上购买了一件商品,我怎么知道有没有购买成功?难道要去查你家系统的已购买表?没权限,就算有权限我也不会!那我怎么验证?很简单啊!系统不是有已购买” 商品列表嘛!点开已购买菜单看就可以了!(如果没有这功能,那说明你的系统设计有问题。用户体验不好,差评!!)

 

接口自动化模拟的是开发的代码操作,A开发写的接口给B开发去调用,A系统的接口给B系统去调用,假设我是一个开发,我调用了微信的接口去做获取用户头像,有个用户获取不到,来!微信团队,你让我查查你们的数据库呗!微信肯定不答应。(数据库不是你想查,想查就给你查!)

 

那接口返回了“success”,但没有把数据添加/删除成功怎么办?从我两年接口自动化的经验来说,这中情况基本非常少见,因为开发在写代码的时候,返回“success”的前提条件肯定是基于操作成功的。(开发写代码的时候肯定会自已运行一下啊!怎么会运行都不运行,哪儿来的自信!)

 

你们的开发就是粗心怎么办?我是这么做的,开发提交了新的接口,我会边读接口代码边设计接口用例(如果接口逻辑看不懂接口数据可能就构造不出来,接口用例自然也不会写。),代码有问题就直接告诉开发改了,在这个过程中,我是会查数据库的。一旦接口用例写好之后,后面再回归去跑的时候就不管了,当然,每条接口用例里面肯定不会加查询数据库的动作。

 

在特殊情况下,我调用了一个删除数据的接口,有没有真的删除一条数据,我可以调用查询数据的接口啊!查不出来刚才删除的数据,不就证明刚才的删除接口操作是ok的了。

 

大多数测试问这个问题就是把自己当测试了,在做手工测试的时候就是这么查数据库的呀!典型的站在测试的思维上想问题。我做UI自动化的时候,我就是普通的用户;我做接口测试的时候我就是开发。只不过,我会比普通用户和开发更细致更全面的使用系统所提供的功能而已。但使用姿势和他们是一样的!

1.如何做好接口测试

谈起软件测试,就不得不说一下接口测试,凡是有功能的软件都离不开接口,没有接口的软件只是一个模具或页面,不具备任何功能。

1.1 什么是接口

硬件接口:USB接口,投影仪接口,鼠标键盘接口。

软件接口:称为API,微信(腾讯公司):提现和充值。银行卡(银行系统),银联接口(想要调用必须拿到鉴权码:tokenkeyappkey)。软件的接口主要使用与数据交互。

业内常说的接口一般指两种:

API:应用程序编程接口,程序间的接口,软件接口测试中的接口特指API接口,接口测试又称API测试GUI:图形用户界面,人与程序的接口

接口实例:系统与系统间的接口调用,作用:实现了两个或多个独立系统或模块间的通信和数据交换能力。

1.2 接口测试是什么

接口测试就是验证这些信息能否正确传递,验证这个方法是否正确,有没有存在潜在的安全,性能问题。

 接口一般来说有两种,一种是程序内部的接口,一种是系统对外的接口。
系统对外的接口:比如你要从别的网站或服务器上获取资源或信息,别人肯定不会把数据库共享给你,他只能给你提供一个他们写好的方法来获取数据,你引用他提供的接口就能使用他写好的方法,从而达到数据共享的目的,比如说咱们用的app、网址这些它在进行数据处理的时候都是通过接口来进行调用的。

  1. 系统调用外部的接口:开发的电商系统需要支付宝和微信支付。只需要测正例。
  2. 系统对外提供的接口:这种接口外部的用户是可以接触到,对安全性要求很高。              

程序内部的接口:方法与方法之间,模块与模块之间的交互,程序内部抛出的接口,比如bbs系统,有登录模块、发帖模块等等,那你要发帖就必须先登录,要发帖就得登录,那么这两个模块就得有交互,它就会抛出一个接口,供内部系统进行调用。

常见接口类型:

1.webService接口:是走soap协议通过http传输,请求报文和返回报文都是xml格式的,我们在测试的时候都用通过工具才能进行调用,测试。可以使用的工具有SoapUIjmeterloadrunner等;

2.http api接口:是走http协议,通过路径来区分调用的方法,请求报文都是key-value形式的,返回报文一般都是json串,有getpost等方法,这也是最常用的两种请求方式。可以使用的工具有postmanRESTClientjmeterloadrunner等;

 

1.3 为什么要做接口测试

1.互联网的快速发展,公司内部系统或与外部系统的关联越来越多,一个业务流程关联多个后端系统,它们的关联都是基于接口来实现,接口测试可以将复杂的系统关联进行简化,只要做好每个接口的测试就能够较好的保证系统质量。

2.单个系统的变更,是否会影响到关联业务系统,比较难用常规的测试方面来覆盖相关的应用系统(例如使用此接口的外部 系统有N个,不可能每个做功能兼容性测试),但可以通过对接口功能的覆盖来验证是否影响它人对接口的调用。

3.接口功能比较单一,能够比较好的进行测试覆盖,也相对容易实现自动化持续集成,可以减少人工回归成本与时间,缩短测试周期。

4.接口相对于界面功能,会更底层一些,测试覆盖会更容易(如业务在调用接口时做了判断,当不满足条件时链接就不显示,此时从界面无法测试相关功能是否做好判断,通过接口就比较容易)

5.大家都知道,接口其实就是前端页面或APP等调用与后端做交互用的,所以好多人都会问,我功能测试都测好了,为什么还要测接口呢?OK,在回答这个问题之前,先举个栗子:

6.比如测试用户注册功能,规定用户名为6~18个字符,包含字母(区分大小写)、数字、下划线。首先功能测试时肯定会对用户名规则进行测试时,比如输入20个字符、输入特殊字符等,但这些可能只是在前端做了校验,

后端可能没做校验,如果有人通过抓包绕过前端校验直接发送到后端怎么办呢?试想一下,如果用户名和密码未在后端做校验,而有人又绕过前端校验的话,那用户名和密码不就可以随便输了吗?如果是登录可能会通过SQL注入等手段来随意登录,甚至可以获取管理员权限,那这样不是很恐怖?

所以,接口测试的必要性就体现出来了:

  1. 可以发现很多在页面上操作发现不了的bug
  2. 检查系统的异常处理能力
  3. 检查系统的安全性、稳定性
  4. 前端随便变,接口测好了,后端不用变

1.4 接口的组成

首先,接口文档应该包含以下内容:

1.接口说明

2.调用url

3.请求方法(get\post

4.请求参数、参数类型、请求参数说明

5.返回参数说明

由接口文档可知,接口至少应有请求地址、请求方法、请求参数(入参和出参)组成,部分接口有请求头header

有同学问我header和入参有什么关系?它们不都是发送到服务器的参数吗?

OK,首先,它们确实都是发送到服务器里的参数,但它们是有区别的,header里存放的参数一般存放的是一些校验信息,比如cookie,它是为了校验这个请求是否有权限请求服务器,如果有,它才能请求服务器,

然后把请求地址连同入参一起发送到服务器,然后服务器会根据地址和入参来返回出参。也就是说,服务器是先接受header信息进行判断该请求是否有权限请求,判断有权限后,才会接受请求地址和入参的。

1.5 接口测试范围

  1. 业务功能(包括正常、异常场景是否实现)
  2. 业务规则(覆盖度是否全面)
  3. 参数验证(边界、业务规则是否达到要求)
  4. 异常场景(重复提交、并发提交、事务中断、多机环境、大数据量测试)
  5. 性能测试响应时间、吞吐量、并发数、资源要求)
  6. 安全测试(权限验证、SQL注入等)

1.6 接口测试的重点

1.检查接口返回的数据是否与预期结果一致。

2.检查接口的容错性,假如传递数据的类型错误时是否可以处理。

3.接口参数的边界值。例如,传递的参数足够大或为负数时,接口是否可以正常处理。

4.接口的性能,http请求接口大多与后端执行的SQL语句性能、算法等比较相关。接口的安全性,外部调用的接口尤为重要。

1.7 做好接口测试的前提

系统化的接口文档

传统的接口文档,一般采用wordwiki等系统来记录,从单次使用上似乎比较简单,因为大家会更习惯这样的操作,但这种形式存在比较大的问题:

1.接口文档非标准化,无法直接与接口测试工具接口使用。

2.接口维护困难,接口有变化时比较难标识清楚,沟通成本很高。

系统化接口文档,例如rap(淘宝分源的一个系统),具备接口维护标准化、版本化管理、MOCK测试等功能;对标准化的接口内容做二次开发,可以直接导出Soapui等工具使用的格式,直接导入工具中使用,有以下好处:

1.接口测试时不再需要手工输入相关字段,节省时间成本

2.版本化管理,能够清晰的知道哪些接口有变化

标准化的接口规范

接口管理是做好接口测试很重要的前提,如果一个系统有哪些接口都不太清楚,测试就很难覆盖到,接口管理建议采用以下方式:

  1. 按接口提供方为单位进行首次划分,按接口使用方进行二次划分,再按业务模块进行细分,分类原则根据内容多少进行优化,不需要固定,如本身接口较少就没有必要分得过细,较多时就需要多划分模块。如:系统A,提供有 123456789 9个接口,接口分别给B系统、C系统使用,其中12为公用接口,345B专用,6789C系统专用,
  2. 按接口链接URL做为唯一,不同的接口参数做为接口变量,接口有参数变更时在原来接口上进行维护,而不是新增加接口
  3. 为接口增加版本号,方便清楚哪些接口本次有变更,易于维护用例。

1.8 接口测试怎么测

在进行接口测试前,还需要了解:

1.8.1 GETPOST请求

如果是get请求的话,直接在浏览器里输入就行了,只要在浏览器里面直接能请求到的,都是get请求,如果是post的请求的话,就不行了,就得借助工具来发送。
GET请求和POST请求的区别:

1.GET使用URLCookie传参。而POST将数据放在BODY中。

2.GETURL会有长度上的限制,则POST的数据则可以非常大。

3.POSTGET安全,因为数据在地址栏上不可见。

4.一般get请求用来获取数据,post请求用来发送数据。

其实上面这几点,只有最后一点说的是比较靠谱的,第一点post请求也可以把数据放到url里面,get请求其实也没长度限制,post请求看起来参数是隐式的,稍微安全那么一些些,但是那只是对于小白用户来说的,就算post请求,你通过抓包也是可以抓到参数的。所以上面这些面试的时候你说出来就行了。

http状态码每发出一个http请求之后,都会有一个响应,http本身会有一个状态码,来标示这个请求是否成功,常见的状态码有以下几种:

1.200  2开头的都表示这个请求发送成功,最常见的就是200,就代表这个请求是ok的,服务器也返回了。

2.300 3开头的代表重定向,最常见的是302,把这个请求重定向到别的地方了

3.400 400代表客户端发送的请求有语法错误,401代表访问的页面没有授权403表示没有权限访问这个页面,404代表没有这个页面。

4.500 5开头的代=表服务器有异常,500代表服务器内部异常,504代表服务器端超时,没返回结果

1.8.2接下来再说接口测试怎么测

1.拿到api接口文档(规范:swaggershowdoc,不规范:word文档,没有:抓包或录制,一般需要抓包或者录制的接口很有可能只测正例),熟练接口业务,接口地址,接口鉴权,接口入参,接口出参,错误码。头痛的面试题:在你们的这个项目(App)你测了哪些接口?

凡是有数据交互的地方就有接口。例如:查询支付宝余额接口。查询芝麻分接口。

2.编写接口测试计划和方案(接口怎么测)?

通用接口用例设计

通过性验证:首先肯定要保证这个接口功能是好使的,也就是正常的通过性测试,按照接口文档上的参数,正常传入,是否可以返回正确的结果。

  • 参数组合:现在有一个操作商品的接口,有个字段type,传1的时候代表修改商品,商品id、商品名称、价格有一个是必传的,type2的时候是删除商品,商品id是必传的,这样的,就要测参数组合了,type1的时候,只传商品名称能不能修改成功,id、名称、价格都传的时候能不能修改成功。
  • 接口安全:
         1、绕过验证,比如说购买了一个商品,它的价格是300元,那我在提交订单时候,我把这个商品的价格改成3元,后端有没有做验证,更狠点,我把钱改成-3,是不是我的余额还要增加?
         2、绕过身份授权,比如说修改商品信息接口,那必须得是卖家才能修改,那我传一个普通用户,能不能修改成功,我传一个其他的卖家能不能修改成功
         3、参数是否加密,比如说我登陆的接口,用户名和密码是不是加密,如果不加密的话,别人拦截到你的请求,就能获取到你的信息了,加密规则是否容易破解。
         4、密码安全规则,密码的复杂程度校验
  • 异常验证:所谓异常验证,也就是我不按照你接口文档上的要求输入参数,来验证接口对异常情况的校验。比如说必填的参数不填,输入整数类型的,传入字符串类型,长度是10的,传11,总之就是你说怎么来,我就不怎么来,其实也就这三种,必传非必传、参数类型、入参长度。

根据业务逻辑设计

根据业务逻辑来设计的话,就是根据自己系统的业务来设计用例,这个每个公司的业务不一样,就得具体的看自己公司的业务了,其实这也和功能测试设计用例是一样的。

举个例子,拿bbs来说,bbs的需求是这样的:

  1. 登录失败5次,就需要等待15分钟之后再登录
  2. 新注册的用户需要过了实习期才能发帖
  3.  删除帖子扣除积分
  4.  ......

像这样的你就要把这些测试点列出来,然后再去造数据测试对应的测试点。

  1. 编写接口测试用例。
  2. 使用接口测试工具执行接口测试。
  3. 输出接口测试报告(HTML格式)

 

1.9 接口测试常用工具

接口测试的工具很多,比如 postmanRESTClientjmeterloadrunnerSoapUI等,本人首推的测试工具是postmanjmeter,接下来就简单介绍下如何使用这两款工具进行接口测试,其他工具本次暂不介绍。

  • Postman是谷歌的一款接口测试插件,它使用简单,支持用例管理,支持getpost、文件上传、响应验证、变量管理、环境参数管理等功能,可以批量运行,并支持用例导出、导入。
  • jmeter是一款100%Java编写的免费开源的工具,它主要用来做性能测试,相比loadrunner来说,它内存占用小,免费开源,轻巧方便、无需安装,越来越被大众所喜爱。

注:以下用例中所用地址皆为本人在本地所搭的环境,外网无法访问,见谅

例如:

获取用户信息:该接口用于通过userid获取用户信息

请求地址:http://192.168.1.102:8081/getuser

请求方式:POST/GET

入参:

 

参数

数据类型(长度)

是否必传

备注

userid

String

Y

用户id

 

 出参:

参数

数据类型(长度)

备注

code

int

状态码200为成功,500为异常

age

int

年龄

id

string

用户id

name

String

用户姓名

 

 postman中请求如下:

 

 

 jmeter中请求如下:

 

 

 

 

 

 

获取用户信息:需要添加headerContent-Type application/json

请求地址:http://192.168.1.102:8081/getuser2

请求方式:get/post

 入参:

参数

数据类型(长度)

是否必传

备注

userid

String

Y

用户id

 

出参:

参数

数据类型(长度)

备注

code

int

状态码200为成功,500为异常

userid

int

用户id

name

string

用户名称

age

int

用户年龄

 

postman测试如下,本次入参为json类型,当然文档中没说非要用json,用其他方式也是可以的。

 

 

 

 

 

 

 

 

jmeter测试如下:

 

 

 

 

 

 

 

 

修改用户余额2

功能描述:需要添加cookietoken是写死的token12345

请求地址

http://192.168.1.102:8081/setmoney2

请求方式

Post

入参:

参数

数据类型(长度)

是否必传

备注

userid

String

Y

用户id

money

String

Y

修改的余额数值

 

 出参:

参数

数据类型(长度)

备注

code

int

状态码200为成功,500为异常

success

String

状态

 

postman测试如下:

 

 

 

jmeter测试如下:

 

 

 

 

 

 

 

 

文件上传:

postman

 

 

jmeter:

 

 

 

 

请求webService接口:

请求webService接口需要用到的工具是SoapUI,如下图:

 

 

 

 

 

Jmeter:

 

 

1.10 接口测试都要掌握哪些知识?

  1. 了解系统及内部各个组件之间的业务逻辑交互;
  2. 了解接口的I/Oinput/output:输入输出);
  3. 了解协议的基本内容,包括:通信原理、三次握手、常用的协议类型、报文构成、数据传输方式、常见的状态码、URL构成等;
  4. 常用的接口测试工具,比如:jmeterloadrunnerpostmansoapUI等;
  5. 数据库基础操作命令(检查数据入库、提取测试数据等);
  6. 常见的字符类型,比如:charvarchartextintfloatdatatimestring等;

1.11 如何学这些技能?

1.系统间业务交互逻辑:通过需求文档、流程图、思维导图、沟通等很多渠道和方式;

2.协议:推荐《图解http》这本书,内容生动,相对算是入门级的书籍,其他的还有《图解tcpIP》等;

3.接口测试工具:百度这些工具,然后你会发现,好多的教学博客、相关问题解决方案、以及一些基于工具的书籍,当然,选择合适的书很重要;

4.数据库操作命令:学习网站(W3C、菜鸟教程)、教学博客,以及一些数据库相关书籍,入门级推荐:《mysql必知必会》、《oracle PL/SQL必知必会》等

5.跟着身边大佬走,多问多学,如果身边没有大佬也可以加入我们,全国的小伙伴天南地北,可以一起聊天学习,更加了解这个行业情况,趋势与走向。

2.接口自动化

2.1为什么做接口自动化

接口测试我们有PostmanJmeter工具,一般采用Postman+Newman+Git+Jenkins实现和Jmeter+Ant+Git+Jenkins实现,也能实现接口自动化功能,那为什么还要做代码级别的接口自动化呢?
主要有以下几点:

  1. 敏捷开发,迭代周期短、接口量大,这种情况下,如果仅仅使用工具级别的接口自动化很难协同,与同事间版本协同困难。
  2. 复杂场景的接口难以实现,加解密
  3. 接口项目中有多种不同的协议
  4. 排错,定位接口问题不方便,要结合抓包实现才行
  5. 有些情况使用工具实现自动化比较困难,例如多接口串联数据库验证、日志监控 
  6. 工具生成的报告不够直观
  7. 有些公司做web自动化+接口自动化难以实现

3.接口自动化之request全局观

3.1 python+request环境准备&框架

安装requests库:pip install requests

框架:python+requests+pytest+allure+yaml

pytest 测试用例框架、allure自动化生成报告、yaml数据驱动配置

3.2 request全局观(请求方法和响应方法)

查看代码
# 1、请求方法--发送http请求
req = requests.get()
requests.post()
requests.delete()
requests.put()
requests.request()  # 最核心的方法,可以支持发起以上几种请求方法

# 2、响应方法--响应参数
req=requests.request()  #定义一个变量req
# 返回字符串格式的数据  (适用返回是文本的)
print(req.text)
# 返回字节格式的数据 (适用返回是文件或图片的)
print(req.content)
# 返回字典格式的数据  (适用返回是json格式的)
print(req.json())
# 状态码
print(req.status_code)
# 状态信息
print(req.reason)
# 返回cookies信息
print(req.cookies)
# 编码格式
print(req.encoding)
# 响应头信息
print(req.headers)

3.2.1 get、post示例

注意:

  1. get请求通过params传递参数
  2. post请求通过json、data传递参数
  • data

若传输的数据报文是dict字典类型,默认情况下请求头是 application/x-www-form-urlencoded,表示以form表单传参,格式:a=1&b=2

若传输的数据报文是str类型,默认情况下请求头是 text/plain

  • json

数据报文:无论是dict/str类型,请求头是 application/json,格式:{”a“:”1”,”b”:”2”}

  3.(其他内容)序列化、反序列化

json.dumps(json_1) 序列化,将字典格式的数据转换成str格式
json.loads(data) 反序列化,将str数据转换成字典格式

  4.总结:

data只能传简单的只有键值对的dict或str格式;json传复杂的、有嵌套的dict

  5.(其他内容)文件上传参数

通过files上传

  6.(其他内容)正则表达式获取响应参数html的内容

token = re.search(”abdbdbbdsjsjd(.*?)”,token)[1]

示例:(接口用的是白月黑羽的测试系统,可以到他的官网获取安装)

查看代码
 # 发送get请求
url = "https://api.bilibili.com/x/web-interface/dynamic/entrance"  # 接口路径
data = {
    "alltype_offset":"0",
    "video_offset":"697162252603621400",
    "article_offset":"0"
      }  # 接口参数
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"}
req_get = requests.get(url=url, params=data, headers=headers, timeout=(10, 7))
print(req_get.status_code)
print(req_get.json())

# 发送post请求,data和json只需要传一个
# json 格式传参
json = {
    "buzz": {"dataType":20001,"apiVersion":2}
}
login_url = "http://127.0.0.1/api/mgr/signin"
login_data = {
    "username": "name,
    "password": "88888888"
}
req_post = requests.post(url=login_url, data=login_data)
# json 格式出参
print(req_post.json()['ret'])
posted @ 2023-02-21 00:48  小泽的窝  阅读(128)  评论(0编辑  收藏  举报