【Unittest】接口自动化测试框架设计

Api 自动化测试

源码:https://github.com/wupeng-pay...

一、Config 模块

|-- config.ini
|-- product-config.ini
|-- test-config.ini

在 config.ini 中的 [ENVIRONMENT] 块中定义环境、发件人、收件人、邮件主题,如:

[ENVIRONMENT]
environment=test

[SENDER]
smtpserver = mail.myhexin.com
user = [email protected]
password = xxxxxx
sender = [email protected]

[RECEIVER]
;receiver = [email protected], [email protected]
receiver = [email protected]

[MSG]
subject = 小象自动定时测试报告(生产api)

将会读取 test-config.ini 文件中的配置,由这种方式将配置文件与环境剥离开。

[HOST]
cn_https=https://xxx.10jqka.com.cn
cn_http=http://xxx.10jqka.com.cn
en_https=https://
en_http=http://

[HOST] 块中定义host,可以在 case.json 文件中使用,如:

{
  "request": {
    "host": "{{cn_https}}", 
    "api": "/info/api/v3/auth/post/login",
    "method": "POST", 
    "header": {
      "Content-Type": "application/x-www-form-urlencoded"
    }
  },
    ....
}

使用 {{}} 包裹,将会从config中解析。否则,当成字符串处理

二、case 定义形式

测试用例,以 json 文件的形式定义。主要包括一个 request 块,和多个 case 块。基本的形式如下:

{
  "request": {
    "host": "{{cn_https}}", 
    "api": "/info/api/v3/auth/post/login",
    "method": "POST", 
    "header": {
      "Content-Type": "application/x-www-form-urlencoded"
    }
  },
  "case_01": {
    "query":"test=1&test2=2",
    "data": [
      {
        "key": "useragent",
        "value": "android/1.5.3",
        "type": "text"
      }
    ],
    "assert": [
      {
        "type": "eq",
        "rules": "status",
        "expect": 0,
        "msg": "这里是报错显示的msg"
      }
    ],
    "set_result": [
      {
        "key": "cache_key",
        "value": "payload.id"
      }
    ]
  }
}

request 对象中包含:

  • host:在config 中定义
  • api:接口地址,与host组成完整url
  • method:请求方式,支持POST与GET
  • header:对象,可填写多个键值对

case_01 为用例名称,一个json文件中可以含有多个用例。同一个文件下所有的用例,请求的内容都相同。

  • query: 字符串,按照"field1=value1&field2=value2"规则,解析结果将于data合并
  • data: 数组,按照method内容,post则放在body中发送,get则放在url中。数组中可放入多个对象。

    • key: 必填,参数名称。
    • value:必填,请求内容。
    • type:必填,类型:text/array/json/file
    • file_name: 非必填,type 为 file 时需要参数。文件名称。
    • file_type: 非必填,type 为 file 时需要参数。文件类型。例子:text/plain
    • from:非必填,数据来源。当数据来源于cache时,填cache。目前只支持cache
  • assert:数组,定义请求结果断言。可以含有多个对象,定义不同的断言,

    • type:断言类型,eq/not_eq等
    • rules:取值规则,返回数据中的结构 例如 payload.group_id
    • expect: 预期值,对比用
  • set_result:非必填 数组,需要保存在cache中的数据

    • key: 名称,注意唯一性
    • result_field:返回数据的结构 例如:payload.group_id

三、定义单元测试

# -*- coding: utf-8 -*-
import unittest
from Common.BaseTest import BaseTest

# 定义测试类
class TestLogin(BaseTest):
    # 定义测试用例文件地址
    json_file = "/TestData"
    
    # 定义单个测试用例
    def test_01_login(self):
        # 定义需要执行的case名称
        self.run_case("case_01")

    def test_02_login(self):
        self.run_case("case_02")
        # 保存全部返回结果
        self.set_result("943189180")

    def test_03_create_group(self):
        # 在用例中定义测试用例文件地址
        self.set_json_file("/TestData")
        # 定义单个参数
        self.set_single_extra_body("code_list", "1050992,1050991")
        self.set_single_extra_body("code", "1050991")
        self.run_case("case_01")


if __name__ == '__main__':
    unittest.main()

四、Cache 模块

为了方便用例间上下文联动,引入cache模块。可以将接口返回的结果保存在cache中,也可以从cache中取出所需要的内容放入到请求体中。

但需要注意的是,cache模块受用例执行顺序的影响,必须保证当前取值的用例在存值用例的后面执行。

使用:

  • 配合 json 文件:

    • 存值,在 {case_name}.set_result 块中定义需要保存的数据

      例如:

      {
      "set_result": [
            {
              "key": "943189180_token",
              "result_field": "payload.token"
            },
            {
              "key": "943189180_all",
              "result_field": "*"
            }
          ]
      }
    • 取值,在 {case_name}.data 块中定义需要取值的数据

      例如:

{
    "data": [
          {
            "key": "token",
            "value": "{{943189180_token}}",
            "type": "text"
          }
    ]
}
 ```
data 中使用 `{{}}` 将会从cache中取值
  • 配合 test 类:

    • 存值:

      使用 set_result 方法保存全部数据。

      self.run_case("case_02")
      self.set_result("943189180")

      这两个方法会将 case_02 的所有返回结果保存在943189180 键中。set_result 方法 必须在 run_case 之后执行。

      也可以写成:

      self.run_case("case_02").set_result("943189180")
    • 取值:

      使用 get_result 方法从cache中取值。

      self.get_cache(key="943189180",r="")

      其中,r 为取值规则。如果为空,则将 943189180 键中所有数据取出,如果需要取出指定结构下的数据,只需要给 r 设定规则,例如:

      self.get_cache(key="943189180",r="payload.token")

五、给case请求体增加参数

  • 增加 header

    • set_extra_header

        self.set_extra_header({"test_header":"header","test_data2":"header"})
      
    • set_single_extra_header

      self.set_single_extra_header(key="test_header",value="header")
  • 增加 body(post):

    ​ 将在body体中传输

    • set_extra_body

      self.set_extra_body({"test_data":"data","test_data1":"data"})
    • set_single_extra_body

      self.set_single_body(key="test_data",value="1")
  • 增加 params (get):

    ​ 将在url中传输

    • set_extra_params

      self.set_extra_body({"test_data":"data","test_data1":"data"})
    • set_single_extra_params

      self.set_single_body(key="test_data",value="1")

      以上将被解析为: http://www.domian.com/some_ap...

六、执行顺序问题

​ 在 run_all_case.py 文件中定义测试用例执行:

suite = unittest.TestSuite()
suite.addTest(TestVanishLogin('test_1_login_01'))
suite.addTest(TestVanishLogin('test_1_login_02'))
suite.addTest(TestVanishLogin('test_2_create_01'))
runner = unittest.TextTestRunner(verbosity=2)

runner.run(suite)

使用 addTest 手动增加测试用例,设置执行顺序。在执行用例很多的情况下,比较麻烦,也可以使用:

discover = unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py')
#runner.run(discover)
runner = HTMLTestRunner(stream=fp, title=u'测试报告', description=u'用例执行情况:')
runner.run(discover)

使用自动 discover 功能,自动加载所有测试用例,但其加载执行的顺序是按照文件名和方法名排序的。

需要优先执行的文件可以将文件名命名为: test_1_1_1_vanish_account_login.py

文件内需要优先执行的用例可以将方法名命名为: test_1_1_account_login_01()

用名称中的数字用来控制用例执行顺序。

你可能感兴趣的:(自动化测试,接口)