seldom 2.0 让接口自动化测试更简单

发表于:2023-11-16 09:18

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:虫师    来源:博客园

  前言
  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 如下:
  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...
  选择导出的文件格式。
  点击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)
  随机生成测试数据
  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数据库操作。
  连接数据库
  连接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()
  最后,基于seldom 实现接口自动化测试的项目:https://github.com/defnngj/pyrequest2
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号