引言

为什么要做接口自动化测试?

在当前互联网产品迭代频繁的背景下,回归测试的时间越来越少,很难在每个迭代都对所有功能做完整回归。

但接口自动化测试因其实现简单、维护成本低,容易提高覆盖率等特点,越来越受重视。

为什么要自己写框架呢?

使用 requets + unittest 很容易实现接口自动化测试,而且 requests 的api已经非常人性化,非常简单。

但通过封装以后(特别是针对公司内特定接口),再加上对一些常用工具的封装,可以进一步提高业务脚本编写效率。

目录

  1. 接口与接口测试

接口测试认知、
python接口开发、
postman接口测试、
接口测试实战

  1. 接口自动化测试技术篇

接口自动化测试用例设计、
Excel接口测试用例访问、
MySQL数据库接口测试用例访问

  1. 接口自动化测试实战篇
    PyTest测试框架、
    接口自动化测试必备技能-HTTP协议、
    Requests库实现接口请求的代码实现、
    电商平台慕慕生鲜全套接口自动化测试实现

  2. 本阶段达到的目的

  • 能够独立进行接口自动化测试的代码开发
  • 掌握Requests库,能够使用Requests库进行接口自动化测试
  • 掌握Postman工具,并能够使用Postman完成接口测试
  • 能够掌握PyTest测试框架,并能够结合Allure框架自动生成测试报告
  • 掌握PyMySQL,能够使用PyMySQL进行数据库的操作
  • 掌握HTTP协议,能够理解请求头与响应投中信息的含义

环境准备

确保本机已安装 python2.7 以上版本,然后安装如下库:

pip install flask
pip install requests

后面我们会使用 flask 写一个用来测试的接口,使用requests去测试。

第一章. 接口测试的认知

1. 为什么要进行接口测试

  • 常见软件的分类
    1675425071111.png

1675425111469.png

  • 软件的架构演变

关于接口测试的总结与思考-小白菜博客
1675425349483.png

1675425554327.png

1675425588552.png

2. 什么是接口

  • 常见硬件接口
    关于接口测试的总结与思考-小白菜博客
    通过某种约定对其他设备进行接入以实现设备与设备之间的交互
  • 常见软件接口
    1675425877783.png
  • 系统中的软件接口
    1675425942349.png
  • 系统中软件接口的常见约定

1675426048351.png

3. 接口测试与功能测试的区别

  1. 功能测试的测试方法
  • 围绕着页面上的功能点进行测试用例设计与执行
  • 从页面的反馈层面验证,侧重验证功能逻辑实现的准确性
  1. 接口测试的测试方法
  • 根据接口协议,并结合接口参数进行测试用例设计与执行
  • 从接口返回的数据验证,侧重验证返回数据的准确性
  1. HTTP协议的接口请求方法
  • get请求
  • post请求
  1. 什么是get请求
  • 通过url来向接口传递数据的请求方式
  • 比较适合传递数据量小,并且保密性低的数据
  1. 什么是post请求
  • 通过请求体的方式向接口传递数据的请求方式
  • 比较适合传递数据量偏大或数据保密性高的数据
  1. 从测试流程上看介入时机不同
    立项→文档→代码编写→单元测试→接口及自动化→功能测试→集成测试→集成接口及接口自动化→集成功能测试→上线部署→线上回归

第二章. python接口开发

1. python接口开发框架Flask简介与安装

1675425942349.png

  • Flask接口测试框架的简介与安装
  • Flask是轻量级的web开发框架
  • 相比于其他框架,Flask更自由,灵活
  • 相比于其他框架,Flask更容易上手

Flask安装网址:https://flask.net.cn/

  • 安装Flask:pip install Flask

1675495632789.png

2. 使用Flask开发一个Get接口

  • 开发get接口
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "hello world qqqqqq"

if __name__ == "__main__":
    app.run()

1675499464693.png

  • 如果想连续网址后面的参数,那就在写代码时添加/hello后,再打开原有的网址后添加/hello,再重启
    1675498960134.png

http://127.0.0.1:5000/hello

1675499429739.png

  • 如果只是在网址后随意输入任意参数结果是无法接收到的

1675499630762.png

  • 以下解决方法:
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "hello world qqqqqq"

@app.route("/hello")
def hello_world2():
    return "hello22222"

@app.route("/hello/<username>")
def hello_world3(username):
    print(username)
    return "hello22222"  + username

if __name__ == "__main__":
    app.run()

1675499945338.png

  • 并在python里打印出了aaa
    1675499989614.png

  • 路径不能一样,否则打印结果一样
    1675500733859.png

  • 以下代码修改路径之后再重启

from flask import Flask,request

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "hello world qqqqqq"

@app.route("/hello")
def hello_world2():
    return "hello22222"

@app.route("/hello/<username>")
def hello_world3(username):
    print(username)
    return "hello22222"  + username

@app.route("/hello/args/<username>")
def hello_world4(username):
    print(username)
    key = request.args.get("key")
    print(key)
    return "hello22222"  + username + "::::" + key

if __name__ == "__main__":
    app.run()

1675501012815.png

  • 并在python里打印出了aaa和qqqqqq
    1675500956879.png
  • 如果想在网址后方添加value以下代码
from flask import Flask,request

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "hello world qqqqqq"

@app.route("/hello")
def hello_world2():
    return "hello22222"

@app.route("/hello/<username>")
def hello_world3(username):
    print(username)
    return "hello22222"  + username

@app.route("/hello/args/<username>")
def hello_world4(username):
    print(username)
    key = request.args.get("key")
    value = request.args.get("value")
    print(key)
    return "hello22222"  + username + "::::" + key + "::::" + value

if __name__ == "__main__":
    app.run()
  • 重启之后打开http://127.0.0.1:5000/hello/args/aaa?key=qqqqqq&value=vvvvv

1675501783568.png

  • 并在python里打印出了aaa和qqqqqq和vvvvv
    1675501819303.png

3. 使用Flask开发一个Post接口

  • 端口号可以在这里修改
    1675502152888.png
  • 开发post接口
from flask import Flask,request

app = Flask(__name__)

@app.route("/mypost",methods=["post"])
def my_post():
    return "post request"


if __name__ == "__main__":
    app.run(port=5555)
  • 如果直接打开这个链接是无法访问的http://127.0.0.1:5555/mypost

1675502491645.png

  • 修改后的代码:
from flask import Flask,request

app = Flask(__name__)




@app.route("/mypost",methods=["post"])
def my_post():
    return "post request"

@app.route("/mypost1",methods=["post"])
def my_post1():
    # 表单数据类型
    username =request.form["username"]
    sex = request.form["sex"]
    print(username)
    print(sex)
    return "post request" + username + "::" + sex




@app.route("/mypost1",methods=["post"])
def my_post2():
    # json数据类型
    request_data =request.get_json()
    sex = request.form["sex"]
    print(request_data)
    print(request_data["user"])
    return "post request" + str(request_data)


if __name__ == "__main__":
    app.run(port=5555)

4. Flask结合PyMySQL接口与数据库的交互

https://pymysql.readthedocs.io/en/latest/user/installation.html

1675503235108.png

  • 这时我们需要打开python下方Terminal
    1675503277359.png

  • 输入exit()回车后弹出输入页面

  • 输入:pip install PyMySQL
    1675503390081.png

  • mysql的基本连接信息

import pymysql
from flask import Flask

# 这里是mysql的基本连接信息
conn = pymysql.connect(
    host="192.168.1.116",
    user="root",
    password="123",
    database="nydb1",
    charset="utf8"
)


cursor = conn.cursor()


app = Flask(__name__)

@app.route("/")
def hello_world():

    sel = "select * from school"
    result = cursor.execute(sql)
    # 得到查询后的真正的结果
    r = cursor.fetchall()
    print(r)
    return str(r)


if __name__ == "__main__":
    app.run()
  • 刷新http://127.0.0.1:5000 后查询到的四条信息v:

1675504774216.png

1675504609850.png

第三章. postman接口测试

1. postman介绍与安装

1675512564688.png

2. postman发送get请求

import pymysql
from flask import Flask,request

# 这里是mysql的基本连接信息
conn = pymysql.connect(
    host="192.168.1.116",
    user="root",
    password="123",
    database="nydb1",
    charset="utf8"
)


cursor = conn.cursor()


app = Flask(__name__)

@app.route("/")
def hello_world():

    sel = "select * from school"
    result = cursor.execute(sql)
    # 得到查询后的真正的结果
    r = cursor.fetchall()
    print(r)
    return str(r)


@app.route("/mypost",methods=["post"])
def my_post():
    return "post request"

@app.route("/mypost1",methods=["post"])
def my_post1():
    # 表单数据类型
    username =request.form["username"]
    sex = request.form["sex"]
    print(username)
    print(sex)
    return "post request" + username + "::" + sex




@app.route("/mypost1",methods=["post"])
def my_post2():
    # json数据类型
    request_data =request.get_json()
    sex = request.form["sex"]
    print(request_data)
    print(request_data["user"])
    return "post request" + str(request_data)

@app.route("/mypost",methods=["post"])
def my_post():
    return "post request"

@app.route("/mypost1",methods=["post"])
def my_post1():
    # 表单数据类型
    username =request.form["username"]
    sex = request.form["sex"]
    print(username)
    print(sex)
    return "post request" + username + "::" + sex




@app.route("/mypost1",methods=["post"])
def my_post2():
    # json数据类型
    request_data =request.get_json()
    sex = request.form["sex"]
    print(request_data)
    print(request_data["user"])
    return "post request" + str(request_data)

if __name__ == "__main__":
    app.run()
  • 执行代码后打开链接:http://127.0.0.1:5000
    1675513772257.png
  • 将127.0.0.1:5000输入到postman里面执行:
    1675513335074.png
  • 另外在代码里看到/hello,也可以输入执行查看结果:
    1675513837370.png

1675514350680.png

3. postman发送post请求

1675517681633.png

import pymysql
from flask import Flask,request

# 这里是mysql的基本连接信息
conn = pymysql.connect(
    host="192.168.1.116",
    user="root",
    password="123",
    database="nydb1",
    charset="utf8"
)


cursor = conn.cursor()


app = Flask(__name__)

@app.route("/")
def hello_world():

    sel = "select * from school"
    result = cursor.execute(sql)
    # 得到查询后的真正的结果
    r = cursor.fetchall()
    print(r)
    return str(r)


@app.route("/mypost",methods=["post"])
def my_post():
    return "post request"

@app.route("/mypost1",methods=["post"])
def my_post1():
    # 表单数据类型
    username =request.form["username"]
    sex = request.form["sex"]
    print(username)
    print(sex)
    return "post request" + username + "::" + sex




@app.route("/mypost1",methods=["post"])
def my_post2():
    # json数据类型
    request_data =request.get_json()
    sex = request.form["sex"]
    print(request_data)
    print(request_data["user"])
    return "post request" + str(request_data)

@app.route("/mypost",methods=["post"])
def my_post():
    return "post request"

@app.route("/mypost1",methods=["post"])
def my_post1():
    # 表单数据类型
    username =request.form["username"]
    sex = request.form["sex"]
    print(username)
    print(sex)
    return "post request" + username + "::" + sex




@app.route("/mypost2",methods=["post"])
def my_post2():
    # json数据类型
    request_data =request.get_json()
    sex = request.form["sex"]
    print(request_data)
    print(request_data["user"])
    return "post request" + str(request_data)

if __name__ == "__main__":
    app.run()

d890d6c407df7a7742a4c02da0a3645.png

6a627178280564d6c7b2f899cce1e9c.png

  • 并在python里打印出
    1675518002395.png

第四章. 接口测试实战——电商网站接口测试

1. 接口测试需求分析

  • 常见接口文档提供的两种方式

①word文档
②在线文档

2. 登陆的分析

1675519712387.png

1675519821278.png

1675521331414.png

  • 将路径添加到以上网址后:
    1675521363164.png
  • 在开发工具里面找到:?userName=imooc&password=12345678 粘贴到网址后方可补充以下
    1675521520751.png
  • 随后点击发送:
    1675521587036.png

1675521867406.png

edaf743d3a144831647b690f5174a25.png

  • 添加新请求后:
    c334e24f6fb616027ddc9c13e77f54a.png

1675522921962.png

  • 之后点击发送,就可以看到网址内的信息

1675522985873.png

3. 环境区分及变量设置

  • 创建dev与test环境保存后,将链接改为{{ip}}
    关于接口测试的总结与思考-小白菜博客
    1675595653376.png

  • 直到通过
    1675595581224.png

  • 然后发送,就可以查看内容
    1675596272073.png

  • postman设置环境变量

Postman 允许用户自己定义环境变量-Environment。在Environment中设置URL域名变量。最常见的是将URL定义成变量的形式,这样随着你的域名无论怎么变,只需要在环境变量中更改URL就可以了,也可以将一些敏感的测试值定义为环境变量,比如密码。对于 Postman 来说,全局变量(Globals)仅有一组,而环境变量(Environment)可以有多组。 (备注:接下来的操作最后都保存后在进行下一步。)

①:在postman中点击右侧的“小眼睛”图标。弹出环境变量和全局变量设置窗口。 image.png ②:设置环境变量,点击:Add,进入环境变量设置页面, image.png ③:在里面填写变量名和初始值。 修改前: image.png 修改后: image.png ④:用设置的变量去取代URL中填写的域名信息,要以 “{{变量名}}” 的方式来引用。 image.png

  • postman设置全局变量

①:设置环境变量,点击:Add,进入环境变量便捷页面, 修改前: image.png 修改后: image.png

  • postman引用CSV文件进行Run collection

①:先在接口里面设置检查点: (一定要设置检查点,不设置检查点的话,Run collection时会报:# This request does not have any tests) image.png ②:鼠标右键选择:Run collection

image.png

③:电脑桌面新建一个txt参数化文本,文本里面设置phone参数化。code不需要设置,因为code在Globals里面已经配置写死了。只需要配置phone的参数就可以了。

image.png

④:选择参数化csv/txt文件 image.png ⑤:点击Run collection就可以看到运行的结果了。 image.png

总结

在本文中,我们以提高脚本开发效率为前提,一步一步打造了一个简易的测试框架。

但因水平所限,并未涉及测试数据初始化清理、测试中如何 MOCK 等话题,前路依然任重而道远,希望给大家一个启发,不足之处还望多多指点,非常感谢。