接口测试系列① | 接口测试入门

接口测试讲义

1. 接口测试的类型

主要包含三种测试:

  1. Web接口测试,
  2. 应用程序接口(API, application programming interface)测试,
  3. 数据库测试。

实际上意义就是UI界面到数据库之间,数据流经过的所有过程。

LAMP(Linux Apache MySQL PHP)/LNMP(Linux Nginx MySQL PHP):只有 Web 服务器,没有应用服务器。

  • Web 浏览器 到 Web 服务器: Web 接口测试,测试 请求和响应。
  • Web 服务器 到 数据库服务器:应用接口测试,测试 PHP。

Linux / Windows + Java / Asp.net(C#) + Apache/Nginx + Tomcat/IIS + MySQL/Oracle/SQL server

  • Web 浏览器 到 Web 服务器: Web 接口测试,测试 请求和响应。
  • Web 服务器 到 应用服务器:契约服务,WebService,JavaAPI,WebAPI,WCF,.net Remoting:测试 Java 或者 C# 处理业务逻辑(JavaEE/ ASP.NET MVC),通俗讲测试 Service。
  • 应用服务器 到 数据库服务器:数据处理服务,测试 Java 或者 C# 处理数据,把数据读取到数据库。

我们需要关注的是 Web 接口测试。

Web 接口测试的方法:

  • Python 或者 Java,C# 编程,触发请求,读取响应,分析得到的响应数据进行与源数据的对比。
  • 用工具:Postman 或者 SoapUI(不推荐)

Postman 原本是一个 Chrome 浏览器的插件,现在已经提供了 Windows、MacOS 和Linux 的独立安装版本。接下来用Windows的版本来进行安装和使用。

2. Postman 的安装

  1. 下载 Postman 的安装包,分为 32位 和 64位。https://www.getpostman.com

  2. 安装 Postman

  3. 注册用户(Sign Up) 并登录 (Sign In)

    Snap23.png
  4. 可以在多台电脑登录,做过的测试会自动同步。

    Snap24.png
  5. 安装完并且登录以后可以开始测试。

    Snap25.png

3. Web 接口的测试点

Web 接口通过 HTTP(S)请求,是一个URL,URL请求结果,会得到数据,数据的格式主要有两种,一种JSON,一种 XML。主要用JSON演示。

  • JSON,是JavaScript Object Notation,JavaScript 对象表示法。是用来表示JavaScript的对象,或者JavaScript数据等。因为JavaScript广泛的应用在 Web的前端页面,所以 JSON 主要应用在 Web 接口中。主要的应用场景:
    • APP移动端和服务器的通信。用应用层 HTTP 协议,通过 Web接口读取数据和处理(提交)数据。
    • Web前端与服务器的通信,往往服务器是第三方的,主要的场景就是 支付和第三方登录。
      • 京东 web端 调用 微信支付、财付通支付、支付宝支付、银联支付、网银支付。。。
      • 京东 web端 支持 微信登录、QQ登录、微博登录
      • 京东 web端 显示 第三方的的物流信息(顺丰、申通、圆通。。。)
      • 公共数据,在web端/APP端的天气预报 是由第三方接口提供。
  • XML,Extensible Markup Language,可扩展的标记语言,HTML就是XML的一种形式,通过 标签的成对出现,以及标签的层次,来决定数据的内容。XML 主要用在后端的 应用程序接口的数据传递,比如 Java,C#等。XML 比较旧的格式。

接下来用一个例子,来分别JSON和XML表示以下的表格数据。

employee_id first_name last_name email phone_number hire_date job_id salary
100 Steven King SKING 515.123.4567 6/17/1987 AD_PRES 24000
101 Neena Kochhar NKOCHHAR 515.123.4568 9/21/1989 AD_VP 17000

首先用 JSON的形式,JSON是“键值对”(Key Value)的形式

{
  "employees": [{
    "employee_id": 100,
    "first_name": "Steven",
    "last_name": "King",
    "email": "SKING",
    "phone_number": "515.123.4567",
    "hire_date": "6/17/1987",
    "job_id": "AD_PRES",
    "salary": 24000
  },
  {
    "employee_id": 101,
    "first_name": "Neena",
    "last_name": "Kochhar",
    "email": "NKOCHHAR",
    "phone_number": "515.123.4568",
    "hire_date": "9/21/1989",
    "job_id": "AD_VP",
    "salary": 17000
  }]
}

对应的 XML 格式:

<?xml version="1.0" encoding="UTF-8" ?>
<employees>
    <employee>
        <employee_id>100</employee_id>
        <first_name>Steven</first_name>
        <last_name>King</last_name>
        <email>SKING</email>
        <phone_number>515.123.4567</phone_number>
        <hire_date>6/17/1987</hire_date>
        <job_id>AD_PRES</job_id>
        <salary>24000</salary>
    </employee>
    <employee>
        <employee_id>101</employee_id>
        <first_name>Neena</first_name>
        <last_name>Kochhar</last_name>
        <email>NKOCHHAR</email>
        <phone_number>515.123.4568</phone_number>
        <hire_date>9/21/1989</hire_date>
        <job_id>AD_VP</job_id>
        <salary>17000</salary>
    </employee>
</employees>

Web 接口的定义来决定测试内容

  1. Method:GET POST PUT DELETE
  2. URL: 接口的地址
  3. 请求参数:每个参数名字,参数的类型,参数的范围,参数是否可选,参数是否有默认值
  • 等价类:有效等价的参数,无效等价的参数
  • 边界值:离点,上点,内点
  • 正交试验法:×因子 ×状态
  • 有的时候,参数之间关联:省,市,县(区),尤其注意非法(无效)的关联
  1. 断言:检查响应的内容
  • 正文:正文是否包含某些字符
  • 正文:JSON 或者 XML 的键值对检查,数量检查 xx.length
  • 响应的状态码:200, 403
  • 响应的时间: 100ms, 200ms
    *5. 认证:你是否有权限访问接口
  1. 接口的实质对象:数据

    1. 数据的格式
    2. 数据的内容

4. Postman 的使用

  1. 测试 心知天气 API:https://www.seniverse.com/

    1. 登录 心知天气 (先注册)

    2. 读 接口的 API 文档

      • API的定义: API 的URL的组成 和请求方法
      • API的参数
        • 请求参数
        • 响应参数
    3. 以 获取实时天气作为示例:

      1. API的方法和URL:GET, https://api.seniverse.com/v3/weather/now.json

      2. API的参数:

        1. 请求参数:

          参数名 参数类型 参数意义 是否必选
          key string 你的API密钥 true
          location string 查询的地理位置 true
          language string 结果表示的语言 false,默认简体中文
          unit string 结果表示的单位(华氏度,摄氏度) false,默认摄氏度
        2. 响应参数:

          参数名 参数类型 参数意义
          location 对象:包括id, name, country, time_zone, time_zone_offset
          now 对象:包括 text,code, temperature, feel_like...
          last_update 日期
        3. 用Postman开始测试

          1. new tab 中输入 方式,和URL

          2. 点击 Params 设置参数

          3. 点击 send 开始发送请求

          4. 查看请求结果是否有输出,格式是否和上述的响应参数对应

            {
              "results": [
                {
                  "location": {
                    "id": "WS10730EM8EV",
                    "name": "Shenzhen",
                    "country": "CN",
                    "path": "Shenzhen,Shenzhen,Guangdong,China",
                    "timezone": "Asia/Shanghai",
                    "timezone_offset": "+08:00"
                  },
                  "now": {
                    "text": "Cloudy",
                    "code": "4",
                    "temperature": "25"
                  },
                  "last_update": "2017-05-09T10:05:00+08:00"
                }
              ]
            }
            

          5. 编辑 Tests 页面,添加断言。

            var jsonData = JSON.parse(responseBody);
            tests["检查城市名称"] = jsonData.results[0].location.name === "Shenzhen";
            
  2. 使用Postman 登录然之系统,测试登录接口

    1. 使用然之 4.2 或者以上版本

    2. 修改然之系统 配置文件 C:\xampp5\htdocs\ranzhi\config\my.php,在最后添加一行配置,如下图:

      修改 然之 配置文件
      $config->notEncryptedPwd = true;
      
    3. 重启 Apache

    4. 打开 Chrome,输入然之的网址,打开登录页面

      Chrome 打开登录页面
    5. 打开 Fiddler,并设置 Chrome 进行抓包

    6. 在 Chrome 中进行登录,提交用户名和密码

    7. 在 Fiddler 中捕获刚刚的登录 POST 请求

      Fiddler 抓包登录 POST
    8. 打开 Postman,新建 URL,POST方法。

      需要设置 Postman,点击 File | Settings,进行设置

      settings
      Setting 2
    9. 在 Postman 输入刚刚 Fiddler 请求的 POST 的 URL

      Fiddler 抓包分析

      输入上述 URL

      URL
    10. 在 Fiddler 中复制请求的第二行到空行之间的 消息报头(Head),Postman 输入 Head

    Head 1
    Head2.png
    1. 在 Fiddler 中复制请求的正文,在 Postman 中 body 选择 raw,并输入

      输入 Body
    2. 在 Postman 的test 中输入以下测试内容:

      输入断言
      var jsonData = JSON.parse(responseBody);
      tests["检查locate"] = jsonData.locate === "\/sys\/index.html";
      tests["检查result"] = jsonData.result === "success";
      tests["Status code is 200"] = responseCode.code === 200;
      
    3. 在 Chrome 中退出登录,注意此步骤很重要,退出以后才能够进行 Postman 登录

      退出 然之
    4. 在 Postman 中点击 Send,进行测试

      测试结果
    5. 查看 Postman 的运行结果。

      result.png

5. Web 接口的认证

Web 接口测试的准备

  1. HTTP协议的请求和响应
    请求:GET/POST
    响应:html/JSON/XML/CSS/JavaScript/png..
  2. 测试的概念
    断言:检查返回的响应里面的内容。
    测试设计:根据请求的参数来设计用例
  3. 读懂接口的文档
    请求的方式和URL
    请求的参数和响应的参数
  4. 在请求接口时使用认证
    basic authorization 基础认证,输入用户名和密码

在上面四个的基础上,注意Web 接口需要认证,尤其是支付业务,这里用一个例子,并且是POST请求 + Basic Auth 认证,来阐述此部分。

示例的步骤:

  1. 打开 https://www.pingxx.com/ Ping++ 在线支付网站,注册一个账号,并登录,会自动创建一个应用。

    Snap27.png
  2. 进入自动创建的应用,进入应用的控制面板界面。

  3. 获取 APP[id],按如图的方式获取到,并等下使用

    Snap28.png
  4. 获取 Test Secret Key,按照如图的方式获取到,并依旧等下使用

    Snap29.png
    Snap30.png
  5. 按照下操作,查阅 API 文档,并开始测试。

    Snap31.png

    Snap32.png

    Snap33.png
  6. 选择 Charge,创建一个 支付订单,查阅 API 文档的请求参数,响应参数,依旧 方法和URL

    Snap34.png
  7. 在Postman 中创建新的测试,输入 POST 和 URL

    Snap35.png
  8. 设置参数,其中需要用到 APP[id],为之前步骤获取到的。

    Snap36.png
  9. 在 请求中使用 认证,Basic Auth,输入 之前步骤获取到的 Test Secret Key,作为用户名。

    Snap37.png

    Snap38.png
  10. 添加测试断言。

用 JavaScript脚本,查询 JSON 对象的值,并做检查。点击右侧的现成菜单,会自动生成检查 JSON 的框架。

var jsonData = JSON.parse(responseBody);
tests["检查object值"] = jsonData.object === "charge";
tests["检查order_no值"] = jsonData.order_no === "99887766554433221100";
tests["检查amount值"] = jsonData.amount === 9900;

Snap39.png
  1. 点击 Send 开始测试。

    Snap40.png
  • 示例2:创建红包的Web 接口测试
  1. 微信红包支付接口测试的接口描述

    创建红包的Web接口描述
  2. 在 Postman 中输入 POST 方法和 URL

    Paste_Image.png
  3. 在 Postman 中 使用 Http Basic Auth 认证。输入之前获取的 Secret_test_key。根据 API文档进行的操作

    Paste_Image.png

    在 Postman 中操作

    Paste_Image.png
    Paste_Image.png
  4. 输入 请求的参数,注意 POST 请求的请求参数,输入到 Body 中

    输入正文
  5. 在 Test 设置断言,刚才说要设置 Object 的验证。

    输入以下内容:

    断言
    var jsonData = JSON.parse(responseBody);
    tests["检查 Object 属性"] = jsonData.object === "red_envelope";
    tests["检查 金额 属性"] = jsonData.amount === 6000;
    

  6. 点击Send,检查。

    结果
  7. 到管理平台查看订单结果。

    Paste_Image.png

6. Postman 的其他功能

Postman 支持导出用例以及账户的同步功能。

Snap41.png

7. Python requests 的使用

Postman 作为工具,有UI的工具可以完整的操作 Web API(Application Programming Interface),有些场景,还需要在自动化测试方案中操作 Web API。对于 Python 来说有两种主流的工具操作 HTTP Web API。

  • urllib (python 自带的,但是语法反人类)
  • requests (第三方的,但是 HTTP Request for human),我们推荐这个 requests 工具。

和 Selenium 一样,requests 也是第三方的工具库。类比 Selenium 操作浏览器,requests 操作 HTTP 请求。

部署 requests 的过程

pip install requests

requests 有两个常见的方法

  1. requests.get()
  2. requests.post()

上面两个方法都会返回一个 Response 类的对象。注意 Response 类 属于 requests。

作为自动化接口测试工具,类似于 Selenium,我们需要 用 Page-Object 方式进行设计

  • 每个 Page 写一个 URL 的功能。
    • get_realtime_weather_by_ip
    • get_realtime_weather_by_city
    • get_realtime_weather_by_location
    • ... 单位
    • ... 语言
  • 每个 page 都不可以 直接用 requests
    • 封装 requests 到 box_requests.py
    • 创建一个类,用来从封装的 box_requests.py 中返回我们定制的 结果(响应)
  • 在每个用例中,继承 unittest.TestCase,调用 Page,进行测试
    • 测试用的数据还是应该抽出来,放到 csv 或者 数据库中

8. 简单的GET请求实例

  • 天气实况

GET /weather/now.json

获取指定城市的天气实况。付费用户可获取全部数据,免费用户只返回天气现象文字、代码和气温3项数据。注:中国城市暂不支持云量和露点温度。

请求地址示例

https://api.seniverse.com/v3/weather/now.json?key=MJX11XSAPG&location=beijing&language=zh-Hans&unit=c

参数

  • key

    你的API密钥

  • location

    所查询的位置参数值范围:城市ID 例如:location=WX4FBXXFKE4F城市中文名 例如:location=北京省市名称组合 例如:location=辽宁朝阳、location=北京朝阳城市拼音/英文名 例如:location=beijing(如拼音相同城市,可在之前加省份和空格,例:shanxi yulin)经纬度 例如:location=39.93:116.40(纬度前经度在后,冒号分隔)IP地址 例如:location=220.181.111.86(某些IP地址可能无法定位到城市)“ip”两个字母 自动识别请求IP地址,例如:location=ip

  • language

    语言 (可选)参数值范围:点此查看

  • unit

    单位 (可选)参数值范围:c 当参数为c时,温度c、风速km/h、能见度km、气压mbf 当参数为f时,温度f、风速mph、能见度mile、气压inch默认值:c

返回结果 200

{
  "results": [{
  "location": {
      "id": "C23NB62W20TF",
      "name": "西雅图",
      "country": "US",
      "timezone": "America/Los_Angeles",
      "timezone_offset": "-07:00"
  },
  "now": {
      "text": "多云", //天气现象文字
      "code": "4", //天气现象代码
      "temperature": "14", //温度,单位为c摄氏度或f华氏度
      "feels_like": "14", //体感温度,单位为c摄氏度或f华氏度
      "pressure": "1018", //气压,单位为mb百帕或in英寸
      "humidity": "76", //相对湿度,0~100,单位为百分比
      "visibility": "16.09", //能见度,单位为km公里或mi英里
      "wind_direction": "西北", //风向文字
      "wind_direction_degree": "340", //风向角度,范围0~360,0为正北,90为正东,180为正南,270为正西
      "wind_speed": "8.05", //风速,单位为km/h公里每小时或mph英里每小时
      "wind_scale": "2", //风力等级,请参考:http://baike.baidu.com/view/465076.htm
      "clouds": "90", //云量,范围0~100,天空被云覆盖的百分比 #目前不支持中国城市#
      "dew_point": "-12" //露点温度,请参考:http://baike.baidu.com/view/118348.htm #目前不支持中国城市#
  },
  "last_update": "2015-09-25T22:45:00-07:00" //数据更新时间(该城市的本地时间)
  }]
}

具体的步骤:

  • 封装 requests 到 box_requests.py

    import requests
    from model.http_response import HttpResponse
    
    class BoxRequests:
        def get(self, url, param):
            """
            用 Get 的方式请求 URL
            :param url: 
            :param param: 参数
            :return: model 中的 HttpResponse 类的对象
            """
            r = requests.get(url, param)
            http_response = HttpResponse()
            http_response.status_code = r.status_code
            http_response.json_dict = r.json()
            return http_response
    
    

  • 创建一个文件夹 model,在里面创建一个类 HttpResponse

    class HttpResponse:
        status_code = None
        json_dict = None
    

  • 创建一个 page :senivers_realtime_weather_page.py

    from base.box_requests import BoxRequests
    
    class SeniversRealtimeWeatherPage:
    
        base_url = "/weather/now.json"
    
        def get_weather_by_ip(self, host, api_key):
            """
            根据IP地址所在的地方查询天气
            :param host:
            :param api_key:
            :return: 自定义的 HttpResponse 类的对象
            """
            br = BoxRequests()
    
            # 创建一个字典,用来传参数
            param = {
                "key": api_key,
                "location": "ip"
            }
    
            # 用 host 和 全局 base_url 拼成 URL
            http_response = br.get(host + self.base_url, param)
            return http_response
    
    

  • 创建一个 case :seniverse_api_tests.py

    import unittest
    
    from pages.api.senivers_realtime_weather_page import SeniversRealtimeWeatherPage
    

class SeniverseApiTests(unittest.TestCase):
api_key = None
page = None
host = None

  def setUp(self):
      self.api_key = "MJX11XSAPG"
      self.host = "https://api.seniverse.com/v3"
      self.page = SeniversRealtimeWeatherPage()

  def test_query_realtime_weather_by_ip(self):
      r = self.page.get_weather_by_ip(self.host, self.api_key)
      self.assertEqual(200, r.status_code, "状态码返回不正确!")
      expected_city = "深圳"
      actual_city = r.json_dict["results"][0]["location"]["name"]
      self.assertEqual(expected_city, actual_city, "城市名称与ip不相符合")

if name == "main":
unittest.main()


​

## 9. 简单的 POST 请求实例

1. 封装 Requests.post()方法
   1. 传递 url
   2. 传递 data
   3. 传递 headers
2. 创建 PingChargeCreatePage 类
   1. create()
   2. ...
3. 创建 用例

示例如下:

### 创建 Charge 对象

请求:POST `https://api.pingxx.com/v1/charges`

发起一次支付请求时需要创建一个新的 `charge` 对象,获取一个可用的支付凭据用于客户端向第三方渠道发起支付请求。如果使用测试模式的 API Key,则不会发生真实交易。当支付成功后,Ping++ 会发送 Webhooks 通知。

| 请求参数                                 |                                          |
| ------------------------------------ | ---------------------------------------- |
| order_no**REQUIRED**                 | 商户订单号,适配每个渠道对此参数的要求,必须在商户系统内唯一。( `alipay` : 1-64 位, `wx` : 2-32 位, `bfb` : 1-20 位, `upacp` : 8-40 位, `yeepay_wap` :1-50 位, `jdpay_wap` :1-30 位, `qpay` :1-30 位, `cmb_wallet` :10 位纯数字字符串。注:除 `cmb_wallet` 外的其他渠道推荐使用 8-20 位,要求数字或字母,不允许特殊字符)。 |
| app [ id ]**EXPANDABLE****REQUIRED** | 支付使用的 `app` 对象的 `id` , `expandable` 可展开,查看 [如何获取App ID](https://help.pingxx.com/article/198599) 。 |
| channel**REQUIRED**                  | 支付使用的第三方支付渠道。参考 [支付渠道属性值](https://www.pingxx.com/api#%E6%94%AF%E4%BB%98%E6%B8%A0%E9%81%93%E5%B1%9E%E6%80%A7%E5%80%BC) 。 |
| amount**REQUIRED**                   | 订单总金额(必须大于0),单位为对应币种的最小货币单位,人民币为分。如订单总金额为 1 元, `amount` 为 100,么么贷商户请查看申请的借贷金额范围。 |
| client_ip**REQUIRED**                | 发起支付请求客户端的 IPv4 地址,如: 127.0.0.1。         |
| currency**REQUIRED**                 | 三位 ISO 货币代码,目前仅支持人民币 `cny` 。             |
| subject**REQUIRED**                  | 商品的标题,该参数最长为 32 个 Unicode 字符,银联全渠道( `upacp` / `upacp_wap` )限制在 32 个字节。 |
| body**REQUIRED**                     | 商品的描述信息,该参数最长为 128 个 Unicode 字符,yeepay_wap 对于该参数长度限制为 100 个 Unicode 字符。 |
| extra*optional*                      | 特定渠道发起交易时需要的额外参数,以及部分渠道支付成功返回的额外参数,详细参考 [支付渠道 extra 参数说明](https://www.pingxx.com/api#%E6%94%AF%E4%BB%98%E6%B8%A0%E9%81%93-extra-%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E) 。 |
| time_expire*optional*                | 订单失效时间,用 Unix 时间戳表示。时间范围在订单创建后的 1 分钟到 15 天,默认为 1 天,创建时间以 Ping++ 服务器时间为准。 微信对该参数的有效值限制为 2 小时内;银联对该参数的有效值限制为 1 小时内。 |
| metadata*optional*                   | 参考 [元数据](https://www.pingxx.com/api#%E5%85%83%E6%95%B0%E6%8D%AE) 。 |
| description*optional*                | 订单附加说明,最多 255 个 Unicode 字符。              |

**返回**

返回一个支付凭据 `charge` 对象。鉴于支付渠道对 `order_no` 的合法性要求,为了保证支付请求的正确处理,请务必保证对于同一支付渠道下,不同支付产品间 `order_no` 的唯一性。例如:已在微信公众号下使用的 `order_no` 则无法在微信支付以及微信公众号扫码下重复使用,该规则同样适用于其他同类渠道。如果发生错误,则会返回错误码和错误详情,详见 [错误](https://www.pingxx.com/api#%E9%94%99%E8%AF%AF)。

根据 Postman 执行这个测试的情况。选择以下的数据:

- headers
- data:params

把上述的两个数据,变成Python 的字典传递到 requests.post() 中,

检查得到的响应中的 Json 对象的值。

1. 修改 box_requests,添加 post_json方法

   ```python
   def post_json(self, url, data=None, json=None, **kwargs):
       """
           用 POST 的方式请求 URL
           :param url:
           :param data: 提交的数据
           :param json: 提交的 json (可选)
           :param kwargs: 额外的参数
           :return:
           """
       r = requests.post(url, data, json, **kwargs)
       http_response = HttpResponse()
       http_response.status_code = r.status_code
       http_response.json_dict = r.json()
       return http_response
  1. 创建 page,为测试用例服务

    class PingxxChargeCreatePage:
        base_url = "/charges"
    
        def create_charge(self, host, data, headers):
            br = BoxRequests()
    
            # 用 host 和 全局 base_url 拼成 URL
            http_response = br.post_json(host + self.base_url,
                                         data=data,
                                         headers=headers)
            return http_response
    

  2. 创建 test_case

    import unittest
    from pages.api.pingxx_charge_create_page import PingxxChargeCreatePage
    
    class PingxxApiTests(unittest.TestCase):
        test_secret_key = None
        app_id = None
        page = None
        host = None
    
        def setUp(self):
            self.app_id = "app_rfv1SGmPKijLnPef"
            self.test_secret_key = "c2tfdGVzdF80bXpqelRpenpQQ0NqVEt5VEN5VGVqYlA6"
            self.host = "https://api.pingxx.com/v1"
            self.page = PingxxChargeCreatePage()
    
        def test_create_charge_by_wechat(self):
            data = {
                "order_no": "88888888666666664444444422222222",
                "app[id]": self.app_id,
                "channel": "wx",
                "amount": 10000000,
                "client_ip": "192.168.1.202",
                "currency": "cny",
                "subject": "iphone 999 正品行货",
                "body": "正规的水货 iphone 8 1000台",
                "description": "iphone 8   一打。。。。订单附加说明,最多 255 个 Unicode 字符。"
            }
    
            headers = {"Authorization": "Basic %s" % self.test_secret_key}
    
            r = self.page.create_charge(self.host, data, headers)
            self.assertEqual(200, r.status_code, "状态码返回不正确!")
            expected_object = "charge"
            actual_object = r.json_dict["object"]
            self.assertEqual(expected_object, actual_object, "对象是否为支付检查失败!")
    
 if __name__ == "__main__":
     unittest.main()

 ```

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

推荐阅读更多精彩内容