Skip to content

接口自动化测试

接口自动化测试

学习价值

学习目标

  • 掌握接口自动化测试体系。
  • 掌握接口自动化测试用例设计方法。

知识模块

  • 接口自动化测试 L1

实战需求

实战 1:PetClinc 宠物主人搜索接口

PetClinic_Rest 是一个宠物诊所管理系统的后端 RESTful API 接口,为前端提供了宠物、医生、预约等相关数据的增删改查功能。

  • https://spring-petclinic-rest.k8s.hogwarts.ceshiren.com/petclinic/swagger-ui/index.html#/
接口文档

请求方式:GET(HTTPS)

请求地址:https://spring-petclinic-rest.k8s.hogwarts.ceshiren.com/petclinic/api/owners?lastName=LASTNAME

请求参数说明

参数 必须 说明
lastName 输入宠物主人 Last name,长度不超过 1~80 个字母,如果不传则返回全部主人信息

权限说明

暂不进行权限控制

返回结果

[
    {
        "address": "110 W. Liberty St.",
        "city": "Madison",
        "firstName": "George",
        "id": 1,
        "lastName": "Franklin",
        "pets": [
            {
                "birthDate": "2022-10-31",
                "id": 1,
                "name": "Leo",
                "ownerId": 1,
                "type": {
                    "id": 1,
                    "name": "cat"
                },
                "visits": [
                    {
                        "date": "2022-10-31",
                        "description": "rabies shot",
                        "id": 1,
                        "petId": 1
                    }
                ]
            }
        ],
        "telephone": "6085551023"
    }
]

返回参数说明

参数 说明
address 宠物主人的地址
city 宠物主人的城市
firstName 宠物主人的名字
id 宠物主人的 id
lastName 宠物主人的姓氏
pets 宠物的信息
pets.birthDate 宠物的生日
pets.id 宠物的 id
pets.name 宠物的名字
pets.ownerId 宠物主人的 id
pets.type 宠物的类型
pets.type.id 宠物的类型的 id
pets.type.name 宠物的类型的名称
pets.visits 宠物访问记录
pets.visits.date 宠物访问记录的日期
pets.visits.description 宠物访问记录的描述信息
pets.visits.id 宠物访问记录的 id
pets.visits.petId 宠物访问记录访问的宠物 id
telephone 宠物主人的手机号码
实战要求
  • 设计接口测试用例
  • 编写接口自动化测试用例

实战 2:宠物商店接口测试

  • 对宠物商店宠物管理接口完成自动化冒烟测试
  • 宠物商店接口文档:https://petstore.swagger.io
    • 查询宠物接口
    • 新增宠物接口
    • 更新宠物接口
    • 删除宠物接口
  • 添加 allure 描述并生成 allure 报告

相关知识点

教程地址 教程视频地址 时间位置
接口自动化测试框架介绍 接口自动化测试框架介绍 全部 19:43
接口请求方法 接口请求方法 全部 22:50
接口请求参数 接口请求参数 全部 13:21
接口请求头 接口请求头 全部 8:57
接口请求体-json 接口请求体-json 全部 11:55
接口响应断言 接口响应断言 全部 10:55
json 响应体断言 json 响应体断言 全部 13:16

实战演练

实战 1:PetClinc 宠物主人搜索接口

import allure
import pytest
import requests


@allure.epic("宠物医院")
@allure.feature("搜索功能")
class TestOwnerSearch:

    def setup_class(self):
        # 查询宠物主人 url
        self.owner_url = "https://spring-petclinic-rest.k8s.hogwarts.ceshiren.com/petclinic/api/owners"
        # 现存宠物主人数量(值可能会变,执行用例前需要确认)
        self.owner_num = 105

    @pytest.mark.P0
    @allure.story("Owners搜索")
    @allure.title("搜索存在主人-冒烟用例")
    def test_search_owner(self):
        '''
        【冒烟】存在的 LastName 可以正确获取宠物主人信息
        '''
        # 搜索关键词
        search_key = "Green"
        # 拼接请求参数(拼接在 url 后的参数)
        param = {
            "lastName": search_key
        }
        # 发出 get 请求,并携带请求参数
        r = requests.get(self.owner_url, params=param)
        # 打印响应体
        print(r.text)
        # 断言获取到的查询结果不为空
        assert len(r.json()) > 0
        # 断言查询到的第一个结果的 lastName 的值符合预期
        assert r.json()[0].get("lastName") == "Green"

    @pytest.mark.P0
    @allure.story("Owners搜索")
    @allure.title("搜索全部主人-冒烟用例")
    def test_search_allowner(self):
        '''
        【冒烟】无 LastName 获取全量宠物主人信息
        '''
        # 发出 get 请求
        r = requests.get(self.owner_url)
        # 打印响应体
        print(r.text)
        # 断言获取到的查询结果数量大于等于已经有的宠物主人数量
        assert len(r.json()) >= self.owner_num
        assert "Green" in r.text

    @pytest.mark.P1
    @allure.story("Owners搜索")
    @allure.title("搜索主人-模糊搜索测试")
    @pytest.mark.parametrize(
        "search_key",
        ["a", "b", "A"]
    )
    def test_search_only_exists_params(self, search_key):
        """
        输入部分字母,获取此字母开头的主人信息
        使用小写字母能搜索到大写字母的主人信息
        使用大写字母能搜索到小写字母的主人信息
        """
        # 打印搜索关键词
        print(f"搜索关键词为:{search_key}")
        # 拼接请求参数(拼接在 url 后的参数)
        param = {
            "lastName": search_key
        }
        # 发出 get 请求,并携带请求参数
        r = requests.request("GET", url=self.owner_url, params=param)
        # 获取宠物主人列表
        owner_list = r.json()
        # 断言比较结果列表的长度大于等于1
        assert len(owner_list) >= 1
        # 获取搜索第一个结果的 lastName 值
        name = owner_list[0].get("lastName")
        print(f"取出结果列表中的姓氏为: {name}")
        # 断言比较接口返回结果列表中的字典中姓氏与查询的参数一致
        assert search_key or search_key.upper() or search_key.lower() in name

    @pytest.mark.P1
    @allure.story("Owners搜索")
    @allure.title("搜索主人-结果不存在")
    def test_search_not_exists(self):
        """
        使用不存在的字母姓氏搜索
        """
        search_key = "xxx"
        param = {
            "lastName": search_key
        }
        code = requests.request("GET", url=self.owner_url, params=param).status_code
        # 断言响应码为404
        assert code == 404

    @pytest.mark.P2
    @allure.story("Owners搜索")
    @allure.title("搜索主人-异常输入值")
    @pytest.mark.parametrize(
        "owner_url",
        ["hogwartshogwartshogwartshogwartshogwartshogwartshogwartshogwartshogwartshogwartshogwartshogwartshogwartshogwartshogwartshogwartshogwarts",
        "涨", "123", "###"]
    )
    def test_search_not_exists(self, owner_url):
        """
        使用超长的姓氏搜索
        使用中文姓氏搜索
        使用数字姓氏搜索
        使用符号进行搜索
        """
        print(f"给接口设定输入内容:{owner_url}")
        param = {
            "lastName": owner_url
        }
        code = requests.request("GET", url=self.owner_url, params=param).status_code
        # 断言响应码为404
        assert code == 404

实战 2:宠物商店接口测试

import allure
import requests


@allure.feature("宠物商店宠物信息接口测试")
class TestPetstore:

    def setup_class(self):
        '''
        准备测试数据
        :return:
        '''
        # 请求的基础 url
        self.url = "https://petstore.swagger.io/v2/pet"
        # 要操作的宠物 id
        self.pet_id = 9223372000001083222
        # 查询状态
        self.find_parmas = {
            "status": "available"
        }
        # 新增宠物的数据
        self.add_data = {
            "id": self.pet_id,
            "category": {
                "id": 1,
                "name": "cat"
            },
            "name": "miao",
            "photoUrls": [
                "string"
            ],
            "tags": [
                {
                  "id": 5,
                  "name": "cute"
                }
            ],
            "status": "available"
        }
        # 更新宠物的数据
        self.update_data = {
            "id": self.pet_id,
            "category": {
                "id": 1,
                "name": "cat"
            },
            "name": "小小",
            "photoUrls": [
                "string"
            ],
            "tags": [
                {
                    "id": 5,
                    "name": "cute"
                }
            ],
            "status": "available"
        }

    @allure.story("查询宠物接口冒烟用例")
    def test_getpet(self):
        '''
        获取宠物信息
        :return:
        '''
        get_url = self.url + "/findByStatus"

        with allure.step("发出查询接口请求"):
            r = requests.get(get_url, self.find_parmas, verify=False)
        with allure.step("获取查询接口响应"):
            print(r.json())
        with allure.step("查询接口断言"):
            assert r.status_code == 200
            assert "id" in r.text

    @allure.story("新增宠物接口冒烟用例")
    def test_addpet(self):
        '''
        新增宠物信息
        :return:
        '''
        with allure.step("发出新增接口请求"):
            r = requests.post(self.url, json=self.add_data, verify=False)
        with allure.step("获取新增接口响应"):
            print(r.json())
        with allure.step("新增接口断言"):
            assert r.status_code == 200
            assert r.json() == self.add_data

    @allure.story("更新宠物接口冒烟用例")
    def test_updatepet(self):
        '''
        更新宠物信息
        :return:
        '''
        with allure.step("发出更新接口请求"):
            r = requests.put(self.url, json=self.update_data, verify=False)
        with allure.step("获取更新接口响应"):
            print(r.json())
        with allure.step("更新接口断言"):
            assert r.status_code == 200
            assert r.json() == self.update_data

    @allure.story("删除宠物接口冒烟用例")
    def test_deletepet(self):
        '''
        删除宠物信息
        :return:
        '''
        delete_url = self.url + "/" + str(self.pet_id)
        with allure.step("发出删除接口请求"):
            r = requests.delete(delete_url, verify=False)
        with allure.step("获取删除接口响应"):
            print(r.json())
        with allure.step("删除接口断言"):
            assert r.status_code == 200
            assert r.json()["message"] == str(self.pet_id)

总结

  • 掌握接口自动化测试体系。
  • 掌握接口自动化测试用例设计方法。