After reading this blog, I guarantee you will certainly make the interface testing.

Recent training new employees to the company's web api interface test, this one found that domestic demand is still relatively large, not just new employees, including some older employees often write interface testing of the interface is also not fully understand, so I am absolutely necessary to write a popular blog under.

Within our company, generally using ruby ​​or python language interface to do the test, this document was to explain the use of language to do the python interface testing.

If you do interface testing, in fact, so long as Ethereal , will assemble http request headers and the request body , examines the http response headers and response body , it can be, we need to need to have the following knowledge! ! ! You also need to have some common testing frameworks, such as unittest and pytest etc.

1, python language requests library

2, http protocol basics, including a request header, in response to the first request and to respond to the body

3, session-cookie (if you are not familiar with the session and cookies, I can see before writing the blog)

https://www.cnblogs.com/bainianminguo/p/9147418.html

https://www.cnblogs.com/bainianminguo/p/8850043.html

4, fiddler packet capture tool

5, testing framework, here do not speak, we are interested can look at what I wrote before blog introduces unittest test framework

https://www.cnblogs.com/bainianminguo/p/11706244.html

https://www.cnblogs.com/bainianminguo/p/11616526.html

 

Following entered, listen to me explain.

A, http protocol

1 Introduction

web api interfaces are mostly based on the http protocol, so to interface testing, we must first understand the basics of the HTTP protocol.

HTTP protocol stands for Hypertext Transfer Protocol. Since HTTP was originally used in the transmission between the browser and web server hypertext (web, video, pictures, etc.) information. Since HTTP is simple to use, and later, to use it not only between the browser and server, between the server and the server, and the server between the phone app, are widely adopted, it has become one of the preferred protocol for a communication between software systems .

HTTP protocol has several versions, including 0.9,1.0,1.1,1.2, the most widely used HTTP / 1.1 version

The greatest feature of the HTTP protocol is divided into two sides communications client and server.

Due to the current HTTP protocol is based on TCP, so to communicate, the client must create a precedent server TCP connection. HTTP and information exchange between the two sides, we must be in such a form

a, the client first sends http request (request) to the server

b, then the server sends a http response (response) to the client

c, with particular attention in the http protocol, the server is not actively message to the client

Flow diagram of the

 

 

 

http1.1 version to create a TCP connection, and can make multiple interactive information in this connection, where attention is unsolicited request to the client service side

 

Two, http request

Example POST http request and the following is http get request

GET /mgr/login HTTP/1.1
Host: 192.168.3.1
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Encoding:gzip, deflate, sdch

  

POST /api/test HTTP/1.1
Host:192.168.3.1
Origin:http://192.168.3.1
Referer:http://192.168.3.1/html/index.html
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Content-Type:application/json;charset=UTF-8
Content-Length:214
Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Encoding:gzip, deflate

{"csrf":{"csrf_param":"35iUJau6mdmmJeIg0N8W80OmoMK8A2Kr","csrf_token":"KfKSfpH0hnsSc0uQyX6ZUB8i8KRFSZ0C"},"data":{"username":"admin","firstnonce":"c7eb46830667147fc62838e7ba9a0c09187d28bafa45b133897efa9d4e46a880"}}

  

A http request message is composed of the following components

a, request line request line

The first line is the content of the http. Indicate what resources to operate, what version of the http protocol using, which contains a three-part message. The method of the request, the operation resource address, the protocol version number

 

GET https://securepubads.g.doubleclick.net/pagead/adview?ai=C3a-FX0L-XZ7nH8Hn2gT1vpKQBofP2MxZl96OgJYKsfz66E0QASC3tpYCYJ0ByAEBqQIDDuevOSiDPuACAKgDAcgDCqoE5AFP0PxttPf1dpFDQI04YpU7K4Qhq0WGx-H6233i9kddKMRmZ8rfGeWBQrr479rzo9D8pahF4GnAvGpwUHZntCL7HcXpQi_xqWQt3alVu7iKmqOQ2r6wzaMJli0vfW_rWq9l6hMmC3THotaE3aaCu8-yQ18_cRaCfgKTCRRx0Eze2gWYfJic33lRDI5NHSVfSlXDsc3SItNtoxG4tZhzRdw3omfX6oWwyvxUVboGzJwd8Rfij2Abfe4gFMviIlfhgVkNNRVv3U-Zhi6Xu5dTGhbV952-dpPUto1PgnRuTQpfsnvJ9UbABKmyupce4AQBkgUECAQYAZIFBAgFGASAB9GIrh6oB47OG6gH1ckbqAeT2BuoB7oGqAfy2RuoB6a-G6gH7NUb2AcB8gcEEPCNAtIIBwiAYRABGB2ACgHICwHYEwKIFAE&sigh=RmPL7gCMtsg&tpd=AGWhJmu9ZlDGyMSGWoSTQKbLoOl12TOWdSdugT6uZH2DizpViw HTTP/1.1

  

b, request method

Get request

Obtain resource information from the server, which is one of the most common request

For example, the page from the server to obtain resources, access to pictures resources, access to user information and other data

 

Post request

Add the resource information to the server for processing, for example, to add user information, upload pictures to a server data, the specific data information, typically in the message body of the HTTP request, this latter speaks

 

 Put request

Server updates the resource information request

For example, to update the user's name and address, etc.

Specific updated data, typically in the HTTP message body, later speaks

 

Delete request

Server delete the resource information request

For example, to delete a user, a resource, etc.

HTT sheet protocol there are many other methods, such as PATCH, HEAD, etc., are not particularly common, let us neglect

 

c, Resource Locator

 

 

 

d, the request header

 

 

 

Here we have a business question, my http request is based on the tcp connection, why there should pass a host it? Because we know the ip address, but may have multiple sites on the ip address, so here we want to assign specific access which site

http request body request the following, which kept some information.

For example, what the server domain name is the request, receiving a response message desired language, a request message body length and the like;

Usually a good number of the request header, a request header row occupies

Is a single request header format: Name: Value

 

e, request body

Request url, request header can store some data, but some data is often stored in the message body needs China; in particular post, put the request, add, modify data information is usually stored in the request message body ;

If the HTTP request with a message body, the agreement, the message needs to be inserted between the header and the message body of a blank line, spaced from them;

Stored in the message body of the request data to a server-side submission

For example: Client to upload a file to the server, you can request data file to the server via http;

A message data file should be in the request body

Request message body is generally a format string, there are three common, but the most common format is json

Json

Xml

www-form-urlencoded

There will be described in detail later

 

request payload is a request body, the following is the format of the message body format Json

 

 

 

Request body can only store a string, you can also put binary information, such as the following video, text and the like, for our scene to upload files, but usually does not involve binary interface testing information, are strings of information, behind I will write a blog dedicated to how to upload files

 

2, http response

We focus on the message response status code

a, 2xx

通常表示请求消息没有问题,而且服务器也正确处理了

b、3xx

这是重定向响应,常见的是是301、302,表示客户端的这个请求的url地址已经改变了,需要客户端重启发起一个请求到另外一个url

c、400

表示客户端请求不符合接口要求,比如格式完全错误

d、401

表示客户端需要先认证才能发送请求

e、403

表示客户端美誉哦权限要求服务器处理这样的请求,比如普通用户的没有管理员的权限

f、404

表示客户端方法的url不存在

g、5xx

表示服务端在处理请求中,发送了未知错误,通常是服务端的代码设计的问题,或者服务端系统出了故障了

 

有了以上的基础,我们就可以做web的接口测试了

二、接口测试

1、什么是接口测试

我们通常说的接口测试,其实就是对软件系统的消息交互接口的参数,消息交互接口是软件系统和其他软件系统交互的那部分,比如,你正在用浏览器使用一个网站,浏览器和后端服务器之间就是消息交互的;在比如,你手机上使用美团订餐,美团app和美团服务器之间,也是消息交互的,当你提交订单,使用功能微信支付的时候,美团服务器和微信服务器之间也是通过消息交互的

 

 

 

 

接口测试就是

依据接口规范,写出测试用例

使用软件工具,直接通过消息接口对被测系统进行消息收发

验证被测系统行为是否正确

 

目前软件系统之间的消息接口大部分是基于HTTP协议收发的

HTTP协议的特点是,客户端发出一个HTTP请求给服务端,服务端就返回一个HTTP相应,好像API程序调用;

所有接口测试通常又被称为API接口测试或者WEB API接口测试

 

API接口传递数据信息是通过HTTP协议进行收发的,网站获取网页,图片,css等资源,也是通过HTTP协议进行收发的

那么这两者有什么区别呢?为什么获取网页,图片这些HTTP消息不叫做API接口消息呢?

网页,图片,css这些资源都是静态资源,就是一个一个文件存储在服务器中,获取这些消息,服务端直接读取文件,返回给客户端即可,无需特别的数据处理

 

而API接口请求消息,通常都需要服务端程序进行一番处理,比如对请求的权限检查,从数据库中读出数据,进行消息过滤和格式转换,最后在HTTP响应中返回给客户端

接口测试需要工具和被测系统之间进行消息的收发,这个工具可以是别人开发的,也可以自己开发,基于HTTP的接口测试工具有Postman,Jmeter等

 

2、fiddler工具

这里我们使用python语言中的requests库和fiddler抓包工具

Fiddler:代理式抓包

大家一定会反问,我的浏览器就是可以抓包了,为什么还要安装fiddler,多此一举?

其实不然,因为我们是用python的requests库去做接口测试,浏览器是抓不到我们发的请求的,所以需要安装fiddler来抓包,确保我们发送的http请求是正确的

 

fiddler启动后,会启动一个代理服务器,监听在8888端口上,http客户端需要设置fiddler作为代理,把http请求消息发送给fiddler,fiddler转发http消息给服务端,服务端返回消息也是先返回给fiddler。再由fidddler转发给客户端

如下图所示

 

 

  

fiddler安装后,会默认配置操作系统级别的代理,可以通过下面的方式查看

 

 

 

安装fiddler需要配置一个过滤项,因为默认fiddler是作为一个系统代理,所以fiddler抓到包会很多,所以需要配置一个过滤项

 

 

 

 

同样,这里的配置是支持通配符的

 

 

 

抓包

 

 

 

 

查看原始的请求消息

 

 

 

 

我们可以在python代码里配置代理,然后通过fiddler抓包来判断我们发的包是否准确,这里需要配置http和https协议的代理

import requests

proxies = {
    "http":"127.0.0.1:8888",
    "http1": "127.0.0.1:8888"
}

res = requests.get(
    url = "htt://www.baidu.com",
    proxies = proxies
)

  

我们可以通过fiddler进行抓包

 

 

 

fiddler如果 要配置手机抓包代理,需要保证安装fiddler和手机在同一个局域网中

 

 

 

在手机的无线网络处配置代理,代理指向运行fiddler的电脑的ip即可,端口是8888

 

3、requests库的请求

a、构建请求的url参数,这个一般在get请求使用较多

什么是url参数

比如

https://www.baidu.com/s?wd=iphone&res_spt=1

  

问号后面的部分wd=iphone&res_spt=1就是url参数,每个参数之间就用&隔开的。

上面的例子中有两个参数wd和res_spt,他们的值分别iphone和1

url参数参数的格式,有个术语叫urlencoded格式

 

使用requests发送HTTP请求,url里面的参数,通常可以直接在url里面,比如

 

 

但是有的时候,我们的url中参数里面有特殊字符,比如参数中的值包含了一个&这个符号或者参数很多的话,我们可以采用下面的方法,构建一个字典,然后把这个字典传递给params参数 

也可以用下面的方式传递url参数

res = requests.get(
    url = "http://www.baidu.com/",
    params = {
        "wd":"iphone",
        "res_spt":"1"
    },
    proxies = proxies
)

  

b、构建请求消息头

有的时候,我们需要自定义一些http的消息头

每个消息头也就是一种键值对的格式存放数据,在requests,只需要把抓包中的请求头信息放在一个字典中,然后传递headers即可

res = requests.get(
    url = "http://www.baidu.com/",
    headers = {
        "Host": "192.168.3.1",
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
        "Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4",
        "Accept-Encoding":"gzip, deflate, sdch"
        },
    params = {
        "wd":"iphone",
        "res_spt":"1"
    },
    proxies = proxies
)

  

 

c、构建请求的消息体

当我们进行api接口测试的时候,根据接口规范,构建的http请求,通常需要构建消息体

http的消息体就是一串字节,里面包含了一些信息,这些信息可能是文本,比如html网页作为消息体,也可能是视频,音频信息

消息体可能很短,只有一个字节,比如字符a,也可能很长,有几百个字节

最常见的消息体格式当然是表示网页内容的html

当时在web api接口测试中,常见的HTTP消息体的格式有三种,urlencoded,json,xml

注意:消息体采用什么格式,是由开发人员设计决定的,开发人员也可以自定义格式,但是我们通常不会自定义的

 

xml格式

前面时候了,消息体就是存放信息的地方,信息的格式完全取决于设计者的需求,如果设计者决定使用xml格式传输一段信息,用requests库,只需要这样就可以了

 

playload = """
    <?xml version="1.0"?>
    <methodCall>
        <methodName>examples.getStateName</methodName>
        <params>
            <param>
                <value><i4>41</i4></value>
            </param>
        </params>
    </methodCall>"""

res2 = requests.post(
    url = "http://www.baidu.com/",
    headers = {
        "Host": "192.168.3.1",
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
        "Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4",
        "Accept-Encoding":"gzip, deflate, sdch",
        "Content-Type": "text/xml"
        },
    data=playload.encode("utf-8"),
    proxies = proxies
)

  

由于消息体都是字节串,我们直接把字符串使用utf-8解码,然后传递给data参数即可,这里需要注意,需要设置Content-type=text/xml

 

 

 

 

使用data参数,存储消息体的数据,如果传递的是一个字符串,在http请求中,需要编码为字节码,默认的编码格式latin-1,这种编码格式是不支持中文的;通常我们使用utf-8的编码格式

通过fiddler抓包

 

 

 

查看请求的原始信息

 

 

 

 

 

 

Urlencoded格式

这种格式的消息体就是一个key-value键值对的格式存放数据,如下所示

key1=value1&key2=value2

 

Requests发送这样的数据,当然可以直接把这种格式的字符串传入到data参数里;但是这样写的话,如果参数本身就有特殊字符,比如等号,就会有歧义

我们还有更方便的方法,只需要将这些键值对的数据构建一个字典,如下

playload = {
    "key1":"value1",
    "key2":"value2"
}

res2 = requests.post(
    url = "http://www.example.com",
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
        "Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4",
        "Accept-Encoding":"gzip, deflate, sdch",
        "Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
        },
    data=playload,
    proxies = proxies
)

  

这里需要注意下面2个地方

 

 

 

 

通过fiddler抓包

先看请求头

 

 

 

这里明显可以看到,请求头和请求体中间有一个空行

 

 

 

看下请求体中的数据

 

 

 

 

Json格式的消息体

Json字符串一律用双引号,不能用单引号

Json字符串最后一个元素的后面不能加逗号

 

其实我们要把数据放到消息体中,最终的数据都是字节串,也就是把str.encode()

json格式当前被web api接口广泛采用

json是一种表示数据的语法格式,他和python表示数据的语法非常像

json格式有两种方式构建消息体

方式1

playload = {"title": "test", "sub": [1, 2, 3]}
res2 = requests.post(
    url = "http://www.example.com",
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
        "Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4",
        "Accept-Encoding":"gzip, deflate, sdch",
        "Content-Type": "application/json;charset=utf-8"
        },
    json=playload,
    proxies = proxies
)

  

注意下面这里

 

 

 

方式2

import json
playload = {"title": "test", "sub": [1, 2, 3]}
res3 = requests.post(
    url = "http://www.example.com",
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
        "Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4",
        "Accept-Encoding":"gzip, deflate, sdch",
        "Content-Type": "application/json;charset=utf-8"
        },
    data = json.dumps(playload,ensure_ascii=False).encode("utf-8"),
    proxies = proxies
)

  

注意下面这里

 

 

4、requests库的响应

a、检查HTTP响应状态码

要检查HTTP响应的状态码,直接通过response对象的status_code属性获取

import json
playload = {"title": "test", "sub": [1, 2, 3]}
res3 = requests.post(
    url = "http://www.example.com",
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
        "Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4",
        "Accept-Encoding":"gzip, deflate, sdch",
        "Content-Type": "application/json;charset=utf-8"
        },
    data = json.dumps(playload,ensure_ascii=False).encode("utf-8"),
    proxies = proxies
)


print(res3.status_code)

  

运行结果发现返回的结果状态码就是200

 

 

 

 

如果故意写一个不存在的地址

import requests

proxies = {
    "http":"127.0.0.1:8888",
    "http1": "127.0.0.1:8888"
}

res = requests.get(
    url = "http://192.168.3.1/html/index4.html",
    proxies = proxies
)

print(res.status_code)

  

运行结果发现返回的状态码就是404

 

 

 

 

b、检查响应的消息头

要检查HTTP响应的消息头,直接通过response对象的header属性获取

import json
import requests
import pprint
playload = {"title": "test", "sub": [1, 2, 3]}
proxies = {
    "http":"127.0.0.1:8888",
    "http1": "127.0.0.1:8888"
}
res3 = requests.post(
    url = "http://www.example.com",
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
        "Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4",
        "Accept-Encoding":"gzip, deflate, sdch",
        "Content-Type": "application/json;charset=utf-8"
        },
    data = json.dumps(playload,ensure_ascii=False).encode("utf-8"),
    proxies = proxies
)


print(pprint.pprint(dict(res3.headers)))

  

结果如下

 

 

 

 

 

 

 

c、检查响应消息体的文本内容

前面我们已经说过,要获取响应的消息体的文本内容,直接通过response对象的text属性即可获取

import requests
import pprint
#
proxies = {
    "http":"127.0.0.1:8888",
    "http1": "127.0.0.1:8888"
}
#
res = requests.get(
    url = "http://mirrors.sohu.com",
    proxies = proxies
)
#
#
# print(res.text)
print(pprint.pprint(dict(res.headers)))
print(res.encoding)

  

  

响应体其实也是字节串,但是我们调用text方法没有设置解码格式,他是怎么解码?他是根据响应头的contend-type来决定解码格式,有的时候会指定,但是大部分不会指定

我们

 

 

 

 

我们可以看到我们打印的解码格式,和content-Type中是一样的

 

 

 

 

如果有的时候中文解码出来是乱码,我们可以手动指定解码格式

 

 

 

 

 

如果我们想打印响应体的字节串可以使用content方法

 

 

 

 

 

5、session

a、原理

我们来思考一个问题,一个网站,比如一个购物网站,服务成千上万的的客户,那么多客户同时访问网站,挑选物品,购物估算,都是通过hTTP请求来访问网站的,这个网站的服务端怎么区分每个HTTP请求呢?网站的服务端是怎么实现的?

一种最常见的方式就是:通过Session+cookies机制

session翻译成中文就是会话的意思

session大体的原理如下面2个图

 

 

 

 

 

 

 

 

 

http协议规定了,网站的服务端放HTTP响应的消息头set-Cookies里面的数据,叫做cookies数据,浏览器客户端必须要保存下来。而且后续访问该网站,必须在http的请求头Cookies中携带保存的所有的cookie数据

用户使用客户端登陆服务端,服务端进行验证,比如验证用户名和密码,验证通过后,服务端系统高就会为这次登陆创建一个seesion,同时创建一个唯一的sessionID。标志这个session。然后,服务端通过HTTP响应,把sessionID告诉客户端,客户端在后面的HTTP请求的消息头,都要包含这个sessionID。这样服务端就会知道,这个供求对应哪个session,从而知道这次的请求对应哪个用户;

 

 

 

 

从上图可以看出,服务端是通过HTTP的响应头set-cookies把产生的sessionID告诉客户端。

 

 

 

 

客户端的后续请求,是通过HTTP请求的请求头Cookies告诉服务端他所持有的sessionid的

 

b、request库支持session的

request处理session-cookies

我们在python代码中如果接收到服务器的http响应,其他set-cookies的数据怎么保存呢?后续怎么样把请求消息头中cookies中呢?

前面学过HTTP响应中如何获取响应头,构建请求怎么设置请求头,完全可以处理。

但是requests库为我们这个处理

requests库给我们提供了一个session类。通过这个类,无需我们操心cookies和session这个事情。reqeusts库会自动帮我们保存服务端发挥的cookies数据,HTTP请求自动在消息头中放入cookies数据

如下所示

import requests
import json
session = requests.session()

playload = {"title": "test", "sub": [1, 2, 3]}
proxies = {
    "http":"127.0.0.1:8888",
    "http1": "127.0.0.1:8888"
}

res = session.post(
    url = "http://www.example.com",
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
        "Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4",
        "Accept-Encoding":"gzip, deflate, sdch",
        "Content-Type": "application/json;charset=utf-8"
        },
    data = json.dumps(playload,ensure_ascii=False).encode("utf-8"),
    proxies = proxies
)



res = session.get()

  

 

Guess you like

Origin www.cnblogs.com/bainianminguo/p/12078838.html