全栈自动化第三期—基于Requests实现接口自动化教程

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: API接口测试介于单元测试和界面测试之间,是一种灰盒测试方法,主要测试内部接口功能的完成性。相较于UI自动化测试,它具有自动化成本低和测试效率高的特点。

1、安装Requests库

Requests库 是 Python编写的,基于urllib 的 HTTP库,使用方便。以下两种方式取其一。

  • 使用国外Github从中央仓库暗装
pip install requests
  • 使用国内镜像源
pip install requests -i https://pypi.douban.com/simple/

安装完成后可用命令进行查看是否安装成功

  • pip list
  • pip show requests

2、发起一个请求

import requests # 导包
resp = requests.请求方法(url='URL地址', params={k:v}, headers={k:v},
                     data={k:v}, json={k:v}, cookies='cookie数据'(如:令牌))

请求方法(Restful风格)

  • Get请求 - get()
  • Post请求 - post()
  • Put请求 - put()
  • Delete请求 - delete()

其他参数

  • url: 待请求的url - string类型
  • params:查询参数 - 字典
  • headers:请求头 - 字典
  • data:表单格式的 请求体 - 字典
  • json:json格式的 请求体 - 字典
  • cookies:cookie数据 - string类型

响应参数

  • 获取 URL:resp.url
  • 获取 响应状态码:resp.status_code
  • 获取 Cookie:resp.cookies
  • 获取 响应头:resp.headers
  • 获取 响应体:

    • 文本格式:resp.text
    • json格式:resp.json()

3、Cookie和Session关系

Cookie:针对 http协议是无连接、无状态特性,设计的 一种技术。 可以在浏览器端 存储用户的信息。

  • cookie 用于存储 用户临时的不敏感信息。
  • cookie 位于浏览器(客户端)端。默认大小 4k(可以调整)
  • cookie 中的数据,可以随意被访问,没有安全性可言。
  • cookie 中存储的数据类型, 受浏览器限制。

Session:通常出现在网络通信中,从客户端借助访问终端登录上服务器,直到退出登录所产生的通信数据,保存在 会话中。

  • Session 用于存储 用户的信息。
  • Session 位于服务端。大小直接使用服务器存储空间
  • Session 中的数据,不能随意被访问,安全性较高。
  • Session 中存储的数据类型,受服务器影响,几乎能支持所有的数据类型。

Session和Cookie的区别?

  • 数据存储位置:cookie数据存放在客户的浏览器上,session数据放在服务器上。
  • 安全性:cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。
  • 服务器性能:session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
  • 数据大小:单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
  • 信息重要程度:可以考虑将登陆信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中。

Session和Cookie协同工作

    session是用户第一次访问用户时,服务器创建的对象并分配唯一性的sessionID,创建之后将sessionID通过Cookie返回给用户所在浏览器,用户再次访问时直接将sessionID发送过去服务器验证登陆凭证就可以。因为Cookie中的数据,都是Session传递的。因此Session 可以直接自动管理 cookie

Session代码案例

import requests
# 1. 创建一个 Session 实例。
session = requests.Session()
# 2. 使用 Session 实例,调 get方法,发送 获取验证码请求。(不需要获取cookie)
resp_v = session.get(url="http://tpshop-test.itheima.net/index.php?
m=Home&c=User&a=verify&r=0.21519623710645064")
# 3. 使用 同一个 Session 实例,调用 post方法,发送 登录请求。(不需要携带 cookie)
resp = session.post(url="http://tpshop-test.itheima.net/index.php?
m=Home&c=User&a=do_login&t=0.7094195931397276",
data={"username": "12345678", "password": "12345678", "verify_code":
"8888"})
print(resp.json())
# 4. 使用 同一个 Session 实例,调用 get 方法,发送 查看我的订单请求。(不需要携带 cookie)
resp_o = session.get(url="http://tpshop-test.itheima.net/Home/Order/order_list.html")
print(resp_o.text)

4、用例管理框架(Unittest、Pytest)

4.1、Unittest

Unittest六大组件

  • TestCase(测试用例)
  • TestSuite(测试套件)
  • TestLoader(测试收集)
  • TextTestRunner(测试执行器)
  • TestReport(测试报告)
  • fixture(测试夹具)

TestCase使用

# 1.导包
import unittest
# 2.定义一个类,这个类必须要继承unittest.TestCase
class TestDemo(unittest.TestCase):
# 3.测试类中,一个以test开头的方法,就是一条测试用例
    def test_add001(self):
        # 准备用例数据
        params = {'a': 11, 'b': 22, 'method': '+'}
        expected = 33
        # 调用功能函数(调用接口),获取实际结果
        result = counter(**params)
        # 比对预期结果和实际结果是否一致(断言)
        self.assertEqual(expected, result)   

断言种类

  • 断言两个值是否相等:self.assertEqual(11, 22),即【a==b】
  • 断言两个值不相等:self.assertNotEqual(11, 22),即【a!=b】
  • 断言数据的布尔值是否为True【python中非0为True, 数据的值为0、数据的长度为0、None的布尔值为False】:self.assertTrue('python'),即【bool(x) is True】
  • 断言数据的布尔值是否为False:self.assertFalse(''),即【bool(x) is False】
  • 成员运算符断言:self.assertIn('错误','账号错误'),即【a in b】
  • 非成员断言:self.assertNotIn('错误', '登录成功'),即【a not in b】

TestSuite和TestLoader使用

# 创建用例套件
suite = unittest.TestSuite()
# 创建用例加载器
load = unittest.TestLoader()
# 用例加载器相当于一个容器,装载测试用例,将用例按模块、类名、目录等方式进行装载
# 1.按类名加载
suite.addTest(load.loadTestsFromTestCase(TestDemo))
# 2.按模块,模块就是相当于一个.py文件
suite.addTest(load.loadTestsFromModule(demo_testcase))
# 3.按目录,试用例目录下面的用例模块必须要使用test开头
suite = unittest.TestLoader().discover('testcases')

TextTestRunner使用

# 创建一个测试运行程序
runner = unittest.TextTestRunner()
runner.run(suite)

TestReport使用

runner = HTMLTestReport(地址, description="登录测试用例", title="管理系统")
runner.run(suite)

fixture使用

  • 1、setUpClass:测试类级别的前置方法,每个测试类中的用例全部开始执行之前会执行(只会执行一次)
  • 2、tearDownClass:测试类级别的后置方法,每个测试类中的用例全部执行完成之后会执行(只会执行一次)
  • 3、setUp:用例级别的前置方法,每条用例开始执行之前都会执行
  • 4、tearDown:用例级别的后置方法,每条用例执行完成之后都会执行
import unittest

class TestDome(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        print('---setUpClass------')
    @classmethod
    def tearDownClass(cls) -> None:
        print('---tearDownClass------')

    def setUp(self) -> None:
        print('---setUp------')
    def tearDown(self) -> None:
        print('---tearDown------')

    def test_01(self):
        print('------------test--01---------------')
    def test_02(self):
        print('------------test--02---------------')

4.2、Pytest

  • 使用国外Github从中央仓库暗装
pip insatll pytest
  • 使用国内镜像源
pip install pytest -i https://pypi.douban.com/simple/

用例识别规则

  • 用例文件:所有文件名为 开头 或者 开头的文件会被识别为用例文件。test__test
  • 用例类,测试文件中没有每个 Test 开头的类型就是一个测试用例类。
class TestDome:

    def test_demo1(self):
        assert 11 == 11

    def test_demo(self):
        assert 22 == 21
  • 测试用例:测试类中每个 test 开头的方法就是一条测试用例,测试文件中每个 test 开头的函数也是一条测试用例
def test_demo():
    assert 100 == 100

执行测试用例

命令行参数详解:

  • 参数详解(主函数模式和命令行模式是一样的):
  • -s:表示输出调试内容,包括print打印的内容
  • -v:表示运行的结果 passed或fail
  • -vs:表示显示调试内容又显示运行结果
  • -vs test_login.py:指定脚本的运行
  • -vs ./api_testcase:指定目录运行脚本
  • -n X: 支持多线程或者分布试运行测试用例
  • –reruns 2 :任何用例失败后会进行重跑2次
  • -x:表示只要一个用例报错,那么测试停止
  • –maxfail=2 :表示出现两个用例失败就停止
  • -k: 根据测试用例的部分字符串指定测试用例

用例跳过:

@pytest.mark.skip
或者
@pytest.mark.skipif(判断条件,reason="***")

生成测试报告

在pytest.ini文件中的addopts写入对应参数
addopts = -vs --html ./report/reporet.html

参数化

@pytest.mark.parametrize(("name, age"), data_list)
    def test_002(self, name, age, ):
        print(name, age)

前置、后置器

    def setup_class(self):
        print("类前置器")

    def teardown_class(self):
        print("类后置器")

    def setup(self):
        print("方法前置器")

    def teardown(self):
        print("方法后置器")

失败重试器

@pytest.mark.flaky(reruns=3, reruns_delay=2)

5、PyMySQL-连接数据库

  • 使用国外Github从中央仓库暗装
pip install PyMySQL
  • 使用国内镜像源
pip install PyMySQL -i https://pypi.douban.com/simple/
  • 建立数据库连接
# 导包
import pymysql
# 建立连接
conn = pymysql.connect(host="", port=0,
user="", password="", database="", charset="")
"""
host:数据库所在主机 IP地址 - string
port:数据库使用的 端口号 - int
user:连接数据库使用的 用户名 - string
password:连接数据库使用的 密码 - string
database:要连接的那个数据库的名字 - string
charset:字符集。常用 utf8 - string
conn:连接数据库的对象。
"""
  • 创建游标
cursor = conn.cursor()
  • 执行SQL语句
cursor.execute('SELECT * FROM `student`')
  • 查询数据库
print(cursor.fetchone())

fetchone():查看执行语句后的一条数据

fetchmany(size):查看指定数量的数据

fetchall():查看所有数据

  • 事务提交
conn.commit()
  • 事务回滚(配合异常处理一起使用)
conn.rollback()
  • 关闭操作(防止占用进程)
cursor.close()
conn.close()

6、封装

6.1、按照代码结构封装:

额

6.2、按照模块分层封装

(一)接口对象层:

  • 将 动态变化的数据,设计到⽅法的参数。
  • 将 固定不变的,直接写成⽅法实现。
  • 将 响应结果,通过返回值传出。

案例:

# 接⼝对象层
import requests
class IhrmLoginApi(object):
@classmethod
def login(cls, json_data):
resp = requests.post(url="http://ihrm-test.itheima.net/api/sys/login",
json=json_data)
return resp

(二)测试用例层:

import unittest
from ihrm_login_api import IhrmLoginApi
# 定义测试类
class TestIhrmLogin(unittest.TestCase):
# 测试⽅法 - 登录成功
def test01_login_success(self):
# 调⽤ ⾃⼰封装 login
login_data = {"mobile": "13800000002", "password": "123456"}
resp = IhrmLoginApi.login(login_data)
print("登录成功:", resp.json())
# 断⾔
self.assertEqual(200, resp.status_code)
self.assertEqual(True, resp.json().get("success"))
self.assertEqual(10000, resp.json().get("code"))
self.assertIn("操作成功", resp.json().get("message"))
# 测试⽅法 - ⼿机号未注册
def test02_mobile_not_register(self):
# 调⽤ ⾃⼰封装 login
login_data = {"mobile": "1384780932", "password": "123456"}
resp = IhrmLoginApi.login(login_data)
print("⼿机号未注册:", resp.json())
# 断⾔
self.assertEqual(200, resp.status_code)
self.assertEqual(False, resp.json().get("success"))
self.assertEqual(20001, resp.json().get("code"))
self.assertIn("⽤户名或密码错误", resp.json().get("message"))
# 测试⽅法 - 密码错误
def test03_pwd_error(self):
# 调⽤ ⾃⼰封装 login
login_data = {"mobile": "13800000002", "password": "890"}
resp = IhrmLoginApi.login(login_data)
print("密码错误:", resp.json())
# 断⾔
self.assertEqual(200, resp.status_code)
self.assertEqual(False, resp.json().get("success"))
self.assertEqual(20001, resp.json().get("code"))
self.assertIn("⽤户名或密码错误", resp.json().get("message"))
# 测试⽅法 - ⼿机号为空
def test04_mobile_is_none(self):
# 调⽤ ⾃⼰封装 login
login_data = {"mobile": None, "password": "123456"}
resp = IhrmLoginApi.login(login_data)
print("⼿机号为空:", resp.json())
# 断⾔
self.assertEqual(200, resp.status_code)
self.assertEqual(False, resp.json().get("success"))
self.assertEqual(20001, resp.json().get("code"))
self.assertIn("⽤户名或密码错误", resp.json().get("message"))
# 测试⽅法 - 多参
def test12_more_params(self):
# 调⽤ ⾃⼰封装 login
login_data = {"mobile": "13800000002", "password": "123456", "abc":"123"}
resp = IhrmLoginApi.login(login_data)
print("⼿机号为空:", resp.json())
# 断⾔
self.assertEqual(200, resp.status_code)
self.assertEqual(True, resp.json().get("success"))
self.assertEqual(10000, resp.json().get("code"))
self.assertIn("操作成功", resp.json().get("message"))
# 测试⽅法 - ⽆参
def test14_none_params(self):
# 调⽤ ⾃⼰封装 login
login_data = None
resp = IhrmLoginApi.login(login_data)
print("⼿机号为空:", resp.json())
# 断⾔
self.assertEqual(200, resp.status_code)
self.assertEqual(False, resp.json().get("success"))
self.assertEqual(99999, resp.json().get("code"))
self.assertIn("抱歉,系统繁忙,请稍后重试", resp.json().get("message"))

(三)断言:

def common_assert(self, resp, status_code, success, code, message):
self.assertEqual(status_code, resp.status_code)
self.assertEqual(success, resp.json().get("success"))
self.assertEqual(code, resp.json().get("code"))
self.assertIn(message, resp.json().get("message"))

本期教程帮助小伙伴们温习了pytest,unittest等用例管理库,下一期我将详细解析requests的用法以及封装技术(重难点)。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
4月前
|
测试技术 Python
Python接口自动化测试框架(基础篇)-- 流程控制之循环语句for&while
本文介绍了Python中的循环语句,包括while和for循环的使用,range()函数的运用,以及continue、break和pass关键字的说明,同时提出了关于while循环是否能与成员运算符结合使用的思考。
54 1
Python接口自动化测试框架(基础篇)-- 流程控制之循环语句for&while
|
4月前
|
测试技术 索引 Python
Python接口自动化测试框架(练习篇)-- 数据类型及控制流程(一)
本文提供了Python接口自动化测试中的编程练习,包括计算器、猜数字、猜拳和九九乘法表等经典问题,涵盖了数据类型、运算、循环、条件控制等基础知识的综合应用。
48 1
|
3月前
|
JSON 移动开发 监控
快速上手|HTTP 接口功能自动化测试
HTTP接口功能测试对于确保Web应用和H5应用的数据正确性至关重要。这类测试主要针对后台HTTP接口,通过构造不同参数输入值并获取JSON格式的输出结果来进行验证。HTTP协议基于TCP连接,包括请求与响应模式。请求由请求行、消息报头和请求正文组成,响应则包含状态行、消息报头及响应正文。常用的请求方法有GET、POST等,而响应状态码如2xx代表成功。测试过程使用Python语言和pycurl模块调用接口,并通过断言机制比对实际与预期结果,确保功能正确性。
267 3
快速上手|HTTP 接口功能自动化测试
|
4月前
|
IDE 测试技术 开发工具
Python接口自动化测试框架(基础篇)-- 不只是txt的文件操作
本文介绍了Python中的文件操作方法,包括使用open()打开文件、close()关闭文件、read()读取内容、readline()读取单行、readlines()读取多行、write()写入内容以及writelines()写入多行的方法。同时,探讨了文件操作模式和编码问题,并扩展了上下文管理器with...as的使用,以及对图片和音频文件操作的思考和练习。
33 1
Python接口自动化测试框架(基础篇)-- 不只是txt的文件操作
|
4月前
|
测试技术 索引 Python
Python接口自动化测试框架(基础篇)-- 函数与内置函数
本文详细介绍了Python中的函数概念,包括自定义函数、参数传递、局部与全局变量,以及内置函数的使用,还扩展了匿名函数、return和yield、exec()、vars()、iter()、map()、zip()、reversed()和sorted()等高级函数和概念。
34 1
Python接口自动化测试框架(基础篇)-- 函数与内置函数
|
4月前
|
测试技术 Python
Python接口自动化测试框架(基础篇)-- 流程控制之if条件控制
Python中的流程控制语句if条件控制,涵盖了比较运算符、成员运算符、身份运算符、逻辑运算符的使用,if语句的嵌套,以及如何使用input和print函数进行交互式编程练习。
33 1
Python接口自动化测试框架(基础篇)-- 流程控制之if条件控制
|
4月前
|
存储 测试技术 数据库
Python接口自动化测试框架(练习篇)-- 函数编程(一)
本文通过实际的编程练习,讲解了面向过程编程的概念和应用,包括如何定义函数、处理文件读写以及实现用户注册功能,最终将这些过程封装成函数,体现了Python作为脚本语言的面向过程编程特性。
32 2
|
4月前
|
前端开发 测试技术 UED
【测试效率对比】深入分析:为何UI自动化测试的投资回报率通常低于接口自动化测试?
这篇文章深入分析了UI自动化测试与接口自动化测试的投资回报率(ROI)问题,指出UI自动化测试在某些情况下的ROI并不低,反驳了没有实施过UI自动化就轻易下结论的观点,并强调了实践的重要性和自动化测试在项目迭代中的作用。
91 1
|
4月前
|
测试技术 Python
Python接口自动化测试框架(练习篇)-- 函数编程(二)
本文通过具体的编程练习,深入探讨了Python中的函数编程,包括如何定义函数、使用参数和返回值,以及函数式编程的技巧和应用,如使用lambda表达式和递归函数解决实际问题。
31 1
|
4月前
|
测试技术 索引 Python
Python接口自动化测试框架:回顾Python3基础语法知识总览
本文是Python 3基础语法知识的全面总结,涵盖了标识符、数据类型、运算符、控制流程、函数、模块和文件操作、异常处理以及面向对象编程的各个方面,旨在为编写Python接口自动化测试框架提供必要的语法知识支持。
36 1