• 9
  • 9
分享

前言

HTTP接口测试很简单,不管工具、框架、还是平台,只要很的好的几个点就是好工具。

  1. 测试数据问题:比如删除接口,重复执行还能保持结果一致,必定要做数据初始化。

  2. 接口依赖问题:B接口依赖A的返回值,C接口依赖B接口的返回值。

  3. 加密问题:不同的接口加密规则不一样。有些用到时间戳、md5、base64、AES,如何提供种能力。

  4. 断言问题:有些接口返回的结构体很复杂,如何灵活的做到断言。

对于以上问题,工具和平台要么不支持,要么很麻烦,然而框架是最灵活的。

unittest/pytest + requests/https 直接上手写代码就好了,既简单又灵活。

那么同样是写代码,A框架需要10行,B框架只需要5行,然而又不失灵活性,那我当然是选择更少的了,毕竟,人生苦短嘛。

seldom适合个人接口自动化项目,它有以下优势。

  • 可以写更少的代码

  • 自动生成HTML/XML测试报告

  • 支持参数化,减少重复的代码

  • 支持生成随机数据

  • 支持har文件转case

  • 支持数据库操作

这些是seldom支持的功能,我们只需要集成HTTP接口库,并提供强大的断言即可。seldom 2.0 加入了HTTP接口自动化测试支持。

Seldom 兼容 Requests API 如下:

seldomrequests
self.get()requests.get()
self.post()requests.post()
self.put()
requests.put()
self.delete()requests.delete()

Seldom VS Request+unittest

先来看看unittest + requests是如何来做接口自动化的:

import unittest
import requests
 
class TestAPI(unittest.TestCase):
 
    def test_get_method(self):
        payload = {'key1': 'value1', 'key2': 'value2'}
        r = requests.get("http://httpbin.org/get", params=payload)
        self.assertEqual(r.status_code, 200)
 
if __name__ == '__main__':
    unittest.main()

这其实已经非常简洁了。同样的用例,用seldom实现。

# test_req.py
import seldom
 
class TestAPI(seldom.TestCase):
 
    def test_get_method(self):
        payload = {'key1': 'value1', 'key2': 'value2'}
        self.get("http://httpbin.org/get", params=payload)
        self.assertStatusCode(200)
 
if __name__ == '__main__':
    seldom.main()

主要简化点在,接口的返回数据的处理。当然,seldom真正的优势在断言、日志和报告。

har to case

对于不熟悉 Requests 库的人来说,通过Seldom来写接口测试用例还是会有一点难度。于是,seldom提供了har 文件转 case 的命令。

首先,打开fiddler 工具进行抓包,选中某一个请求。

然后,选择菜单栏:file -> Export Sessions -> Selected Sessions...

图片 1.png

选择导出的文件格式。

图片 2.png

点击next 保存为demo.har 文件。

最后,通过seldom -h2c 转为demo.py 脚本文件。

> seldom -h2c .\demo.har
.\demo.py
2021-06-14 18:05:50 [INFO] Start to generate testcase.
2021-06-14 18:05:50 [INFO] created file: D:\.\demo.py

demo.py 文件。

import seldom
 
class TestRequest(seldom.TestCase):
 
    def start(self):
        self.url = "http://httpbin.org/post"
 
    def test_case(self):
        headers = {"User-Agent": "python-requests/2.25.0", "Accept-Encoding": "gzip, deflate", "Accept": "application/json", "Connection": "keep-alive", "Host": "httpbin.org", "Content-Length": "36", "Origin": "http://httpbin.org", "Content-Type": "application/json", "Cookie": "lang=zh"}
        cookies = {"lang": "zh"}
        self.post(self.url, json={"key1": "value1", "key2": "value2"}, headers=headers, cookies=cookies)
        self.assertStatusCode(200)
 
if __name__ == '__main__':
    seldom.main()

运行测试

打开debug模式seldom.run(debug=True) 运行上面的用例。

> python .\test_req.py
2021-04-29 18:19:39 [INFO] A run the test in debug mode without generating HTML report!
2021-04-29 18:19:39 [INFO]
              __    __
   ________  / /___/ /___  ____ ____
  / ___/ _ \/ / __  / __ \/ __ ` ___/
 (__  )  __/ / /_/ / /_/ / / / / / /
/____/\___/_/\__,_/\____/_/ /_/ /_/
-----------------------------------------
                             @itest.info
 
test_get_method (test_req.TestAPI) ...
----------- Request ? ---------------
url: http://httpbin.org/get         method: GET
----------- Response ?️ -------------
type: json
{'args': {'key1': 'value1', 'key2': 'value2'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.22.0', 'X-Amzn-Trace-Id': 'Root=1-608a883c-7b355ba81fcd0d287566405a'}, 'origin': '183.178.27.36', 'url': 'http://httpbin.org/get?key1=value1&key2=value2'}
ok
 
----------------------------------------------------------------------
Ran 1 test in 0.619s
 
OK

通过日志/报告都可以清楚的看到。

  • 请求的方法

  • 请求url

  • 响应的类型

  • 响应的数据

更强大的断言

断言接口返回的数据是我们在做接口自动化很重要的工作。

assertJSON

接口返回结果如下:

{
  "args": {
    "hobby": [
      "basketball",
      "swim"
    ],
    "name": "tom"
  }
}

我的目标是断言name 和 hobby 部分的内容。seldom可以针对JSON文件进行断言。

import seldom
 
class TestAPI(seldom.TestCase):
 
    def test_assert_json(self):
        payload = {'name': 'tom', 'hobby': ['basketball', 'swim']}
        self.get("http://httpbin.org/get", params=payload)
        assert_json = {'args': {'hobby': ['swim', 'basketball'], 'name': 'tom'}}
        self.assertJSON(assert_json)

运行日志

test_get_method (test_req.TestAPI) ...
----------- Request ? ---------------
url: http://httpbin.org/get         method: GET
----------- Response ?️ -------------
type: json
{'args': {'hobby': ['basketball', 'swim'], 'name': 'tom'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.22.0', 'X-Amzn-Trace-Id': 'Root=1-608a896d-48fac4f6139912ba01d2626f'}, 'origin': '183.178.27.36', 'url': 'http://httpbin.org/get?name=tom&hobby=basketball&hobby=swim'}
? Assert data has not key: headers
? Assert data has not key: origin
? Assert data has not key: url
ok
 
----------------------------------------------------------------------
Ran 1 test in 1.305s
 
OK

seldom还会提示你还有哪些字段没有断言。

assertPath

接口返回数据如下:

{
  "args": {
    "hobby":
      ["basketball", "swim"], 
    "name": "tom"
  }
}
seldom中可以通过path进行断言:
import seldom
 
 
class TestAPI(seldom.TestCase):
 
    def test_assert_path(self):
        payload = {'name': 'tom', 'hobby': ['basketball', 'swim']}
        self.get("http://httpbin.org/get", params=payload)
        self.assertPath("name", "tom")
        self.assertPath("args.hobby[0]", "basketball")

assertSchema

有时并不关心数据本身是什么,而是需要断言数据的类型。 assertSchema 是基于 jsonschema 实现的断言方法。

jsonschema: https://json-schema.org/learn/

接口返回数据如下:

{
  "args": {
    "hobby":
      ["basketball", "swim"], 
    "name": "tom", 
    "age": "18"
  }
}

seldom中可以通过利用jsonschema 进行断言:

import seldom
 
class TestAPI(seldom.TestCase):
 
    def test_assert_schema(self):
        payload = {"hobby": ["basketball", "swim"], "name": "tom", "age": "18"}
        self.get("/get", params=payload)
        schema = {
            "type": "object",
            "properties": {
                "args": {
                    "type": "object",
                    "properties": {
                        "age": {"type": "string"},
                        "name": {"type": "string"},
                        "hobby": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            },
                        }
                    }
                }
            },
        }
        self.assertSchema(schema)

是否再次感受到了seldom提供的断言非常灵活,强大。

接口数据依赖

在场景测试中,我们需要利用上一个接口的数据,调用下一个接口。

import seldom
 
class TestRespData(seldom.TestCase):
 
    def test_data_dependency(self):
        """
        Test for interface data dependencies
        """
        headers = {"X-Account-Fullname": "bugmaster"}
        self.get("/get", headers=headers)
        self.assertStatusCode(200)
 
        username = self.response["headers"]["X-Account-Fullname"]
        self.post("/post", data={'username': username})
        self.assertStatusCode(200)

seldom提供了self.response用于记录上个接口返回的结果,直接拿来用即可。

数据驱动

seldom本来就提供的有强大的数据驱动,拿来做接口测试非常方便。

@data

import seldom
from seldom import data
 
 
class TestDDT(seldom.TestCase):
 
    @data([
        ("key1", 'value1'),
        ("key2", 'value2'),
        ("key3", 'value3')
    ])
    def test_data(self, key, value):
        """
        Data-Driver Tests
        """
        payload = {key: value}
        self.post("/post", data=payload)
        self.assertStatusCode(200)
        self.assertEqual(self.response["form"][key], value)

@file_data

创建data.json数据文件

{
 "login":  [
    ["admin", "admin123"],
    ["guest", "guest123"]
 ]
}

通过file_data实现数据驱动。

import seldom
from seldom import file_data
 
 
class TestDDT(seldom.TestCase):
 
    @file_data("data.json", key="login")
    def test_data(self, username, password):
        """
        Data-Driver Tests
        """
        payload = {username: password}
        self.post("http://httpbin.org/post", data=payload)
        self.assertStatusCode(200)
        self.assertEqual(self.response["form"][username], password)

更过数据文件(csv/excel/yaml),参考

随机生成测试数据

seldom提供随机生成测试数据方法,可以生成一些常用的数据。

import seldom
from seldom import testdata
 
 
class TestAPI(seldom.TestCase):
 
    def test_data(self):
        phone = testdata.get_phone()
        payload = {'phone': phone}
        self.get("http://httpbin.org/get", params=payload)
        self.assertPath("args.phone", phone)

更过类型的测试数据,参考

数据库操作

seldom 支持sqlite3、MySQL数据库操作。

sqlite3MySQL
delete_data()delete_data()
insert_data()insert_data()
select_data()select_data()
update_data()update_data()
init_table()init_table()
close()close()

连接数据库

连接sqlit3数据库

from seldom.db_operation import SQLiteDB
 
db = SQLiteDB(r"D:\learnAPI\db.sqlite3")

连接MySQL数据库(需要)

1、安装pymysql驱动

> pip install pymysql

2、链接

from seldom.db_operation import MySQLDB
 
db = MySQLDB(host="127.0.0.1", 
             port="3306", 
             user="root", 
             password="123", 
             database="db_name")

操作方法

  • delete_data

删除表数据。

db.delete_data(table="user", where={"id":1})
  • insert_data

插入一条数据。

data = {'id': 1, 'username': 'admin', 'password': "123"},
db.insert_data(table="user", data=data)
  • select_data

查询表数据。

result = db.select_data(table="user", where={"id":1, "name": "tom"})
print(result)
  • update_data

更新表数据。

db.update_data(table="user", data={"name":"new tom"}, where={"name": "tom"})
  • init_table

批量插入数据,在插入之前先清空表数据。 

datas = {
    'api_event': [
        {'id': 1, 'name': '红米Pro发布会'},
        {'id': 2, 'name': '可参加人数为0'},
        {'id': 3, 'name': '当前状态为0关闭'},
        {'id': 4, 'name': '发布会已结束'},
        {'id': 5, 'name': '小米5发布会'},
    ],
    'api_guest': [
        {'id': 1, 'real_name': 'alen'},
        {'id': 2, 'real_name': 'has sign'},
        {'id': 3, 'real_name': 'tom'},
    ]
}
 
db.init_table(datas)
  • close

关闭数据库连接。

db.close()


作者:虫师

原文链接:https://www.cnblogs.com/fnng/p/14887574.html

  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          •  Apifox 自动化测试模块新升级,在流程测试原有功能上新增了测试步骤循环、判断、等待时间的流程控制条件,以及测试步骤分组管理等能力。当业务需要多种判断时,流程控制可用于控制测试步骤的复杂执行顺序,更能模拟用户真实的使用场景,提升测试人员对复杂测试场景的工作效率。循环当测试步骤需要重复执行时,可以通过设置固定数量的有限循环来快速实现。同时支持设置中止条件或遇错处理的逻辑判断,以保证循环能按需运行。注意:右侧运行参数设置模块也有循环功能,但该功能是针对的是整个测试用例。场景实例宠物店需要在当天营业结束后,对今日售出的每个宠物进行信息查询并将「在售」状态变更为「已售出」。假设今日售出 ...
            0 0 1334
            分享
          • 上周分享了[Kafka性能测试初探](https://mp.weixin.qq.com/s/6zU36udvFpt-2ijfNtSJUA)的Java版本,有读者留言说太简单,内容比较水。这里澄清一下,是我学得比较水。文章定位就是一篇使用Java语言的Kafka Client客户端进行简单操作演示,然后模拟一下简单场景的性能测试。其中深入学习Kafka的可以随处搜到很权威实用的资料,有深入学习需求的可以自行寻找。好久没有写Go了,这才突然觉察到,又重新复习了一波Go语言的基础语法。顺带着之前留下的好习惯,每个学习的框架和工具都用Java和Go写一遍。这次也分享一下Go语言的Kafka基础入门,以...
            0 0 1057
            分享
          •   摘要:随着金融行业信息化程度的不断提高,银行业务系统面临着前所未有的复杂性和安全性挑战。为了确保系统稳定运行,银行必须在软件开发生命周期中实施严格的测试流程。本文将探讨如何基于Jacoco框架进行二次开发,从而实现银行交易的精准测试工作。通过这种方式,不仅可以提高测试可信度和测试充分性、还能协助定位缺陷、识别冗余代码,进而保证金融服务的质量与安全。  一、背景介绍  在银行业务核心系统中,程序类型分为两类,联机交易和批量交易。联机交易一般都是供其他系统或者柜面前台调用的接口,批量交易则往往是日间或者日终银行跑批用的,用来集中处理账务加工、计提结息、账务核对、监管报送等内容。银行系统对于测试...
            0 0 258
            分享
          •   谷歌云服务近期发生了一起重大配置错误事故,导致澳大利亚UniSuper基金的云订阅账户被意外删除,造成了超过50万UniSuper基金会员在一周内无法访问自己的退休金账户,涉及的资产高达1250亿澳元(约合9037.5亿元人民币)。这次服务中断始于5月2日,直到5月9日相关服务才基本恢复,但部分账户信息未能完全更新。幸运的是,尽管账户被删除,UniSuper基金投资者账户中的资金未遭受影响。  谷歌云首席执行官托马斯·库里安(Thomas Kurian)表示,此次服务中断是由一系列前所未见的事件引起的,在配置UniSuper的私有云服务期间,一个不经意的错误配置最终导致UniSuper的私...
            0 0 715
            分享
          • 测试人员进行的测试活动,不是仅限于版本上线前的测试,版本上线后,我们的测试工作依然在继续,只不过测试环境变成了线上环境,测试力度变为走查形式,一些异常或者特殊场景等会相应减少,但是常用功能和正向流程一个都不能少。以下来简单拆解下线上走查的一些注意事项。~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~测试走查,是我们每个测试工程师的日常工作:版本迭代前,通过需求评审,发现现有功能的已知问题;版本进行中,通过测试设计,审视当前测试方案存在的没考虑全的问题;或者开发的设计方案漏洞版本开发时,通过用例评审和迭代测试,审...
            1 0 6405
            分享
      • 51testing软件测试圈微信