接口自动化中的jsonSchema及契约测试

目录

  • 场景介绍:接口自动化及契约测试
  • jsonschema介绍
  • 契约测试实现步骤及Demo
  • jsonschema编写规则及例子-swagger
  • 接口实战的例子
  • 契约测试应用

场景应用

一个 基于saas的跨境电商ERP系统的物流模块,要对接了多个物流公司,不同的物流公司有不同的IT团队,使用不同的技术实现方法和不同的接口提供方式。而测试人员在每一次发版之前和之后几乎都是崩溃的,因为至少需要对30多家物流公司上百种物流方式进行全覆盖测试。
解决方案:接口的自动化测试
接口的变更来源于对方修改了他们之前和我们说好的接口而没有通知到我们。由此引起了无数的血雨腥风和线上缺陷
接口的变更应对方案:契约测试

1、契约测试

契约测试是验证服务的Provider是否按照期望的方式与服务的Consumer进行交互,简单的说是Consumer与Provider两者之间的集成。
通俗一点的说法就是在以上我们公司遇到的场景里面,我们和物流公司之间先定一个契约,然后我们可以定期的发送请求去检查这个契约,如果发送的请求不通过就表示契约有变。
鉴于现在好多的系统利用Json数据格式来进行数据的传输,考虑用jsonschema来解决这个问题。

2、jsonschema介绍

  • JSON Schema指的是数据交换中的一种虚拟的“合同”。
  • https://pypi.org/project/jsonschema/
  • JSON验证器负责验证语法错误,JSON Schema负责提供一致性检验。
  • 完全支持 Draft 7Draft 6Draft 4Draft 3
  • 延迟验证,可以迭代地报告所有验证错误。
  • 可以以编程方式查询哪些属性或项验证失败。

2.1、jsonschema相关资料

3、契约测试实现步骤

pip install jsonschema

申明一个Schema(此处的Schema可由上面的在线转换而来)
调用Valid函数,如果得到的值不出错,则运行时不会抛出异常
导入jsonschema及验证:

pip install jsonschema
from jsonschema import validate

声明你接口的schema(规范合同):类型,属性,属性的限制等

schema = {"type": "object", "properties": {"price": {"type": "number"}, "name": {"type": "string"}}}

验证你要传递的数据(实例)是否符合要求

validate(instance={"name": "Eggs", "price": 34.99}, schema=schema)
validate(instance={"name": "Eggs", "price": "34.99"}, schema=schema)

例1

from jsonschema import validate
schema = {"items": {"type": "boolean"},  "minItems": 2}
validate([True,False],schema=schema)

例2

from jsonschema.validators import Draft4Validator
# schema = {"items": {"type": "boolean"},  "minItems": 2}
schema = {'format': 'date', 'type': 'string', 'maxLength': 10}
validator = Draft4Validator(schema=schema)
validator.validate('2019-05-01')
validator.validate('2019/05/01')
validator.validate('2019050100')
validator.validate('2019年5月29日')
validator.validate('2019-05sf')
validator.validate(2019050100000)

接口自动化代码

schema2.json文件来自swagger官网导出的
可以自行裁剪

{
  "definitions": {},
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/root.json",
  "type": "object",
  "title": "The Root Schema",
  "required": [
    "id",
    "category",
    "name",
    "photoUrls",
    "tags",
    "status"
  ],
  "properties": {
    "id": {
      "$id": "#/properties/id",
      "type": "string",
      "title": "The Id Schema",
      "default": 0,
      "examples": [
        2
      ]
    },
    "category": {
      "$id": "#/properties/category",
      "type": "object",
      "title": "The Category Schema",
      "required": [
        "id",
        "name"
      ],
      "properties": {
        "id": {
          "$id": "#/properties/category/properties/id",
          "type": "integer",
          "title": "The Id Schema",
          "default": 0,
          "examples": [
            2
          ]
        },
        "name": {
          "$id": "#/properties/category/properties/name",
          "type": "string",
          "title": "The Name Schema",
          "default": "",
          "examples": [
            "Something2"
          ],
          "pattern": "^(.*)$"
        }
      }
    },
    "name": {
      "$id": "#/properties/name",
      "type": "string",
      "title": "The Name Schema",
      "default": "",
      "examples": [
        "Something2"
      ],
      "pattern": "^(.*)$"
    },
    "photoUrls": {
      "$id": "#/properties/photoUrls",
      "type": "array",
      "title": "The Photourls Schema",
      "items": {
        "$id": "#/properties/photoUrls/items",
        "type": "string",
        "title": "The Items Schema",
        "default": "",
        "examples": [
          ""
        ],
        "pattern": "^(.*)$"
      }
    },
    "tags": {
      "$id": "#/properties/tags",
      "type": "array",
      "title": "The Tags Schema",
      "items": {
        "$id": "#/properties/tags/items",
        "type": "object",
        "title": "The Items Schema",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "$id": "#/properties/tags/items/properties/id",
            "type": "integer",
            "title": "The Id Schema",
            "default": 0,
            "examples": [
              2
            ]
          },
          "name": {
            "$id": "#/properties/tags/items/properties/name",
            "type": "string",
            "title": "The Name Schema",
            "default": "",
            "examples": [
              "Something2"
            ],
            "pattern": "^(.*)$"
          }
        }
      }
    },
    "status": {
      "$id": "#/properties/status",
      "type": "string",
      "title": "The Status Schema",
      "default": "",
      "examples": [
        "123"
      ],
      "pattern": "^(.*)$"
    }
  }
}

测试代码:
第一个方法是验证契约的
第二个是正常的业务接口

import requests
import pytest
import json
from jsonschema.validators import Draft7Validator


def addviladator(respose_data):
    with open("schema2.json", 'r') as f:
        dict_schema = json.load(f)
    va = Draft7Validator(dict_schema)
    va.validate(respose_data)


def test_search_by_id():
    url = 'https://petstore.swagger.io/v2/pet/1'
    res = requests.get(url=url)
    respose_data = res.json()
    print(respose_data)
    assert res.status_code == 200
    assert respose_data['name'] == '9YZQCGVJM8'
    assert res.elapsed.total_seconds() <= 3
    addviladator(respose_data)


if __name__ == '__main__':
    pytest.main(['-s', 'test_swaggeruidemo6.py'])
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,427评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,551评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,747评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,939评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,955评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,737评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,448评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,352评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,834评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,992评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,133评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,815评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,477评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,022评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,147评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,398评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,077评论 2 355

推荐阅读更多精彩内容