【问题标题】:Compare expected vs actual json response for a get request in Python比较 Python 中 get 请求的预期与实际 json 响应
【发布时间】:2019-07-06 19:09:04
【问题描述】:

当您访问此站点https://reqres.in/api/users/2时,您将收到一个小的 json 响应

我将响应保存在一个变量(实际)中。我还将响应放入另一个变量(预期)中。两个响应​​都是相同的。我正在更改值以测试失败的案例。最终目标是比较 2 并确保它们匹配。

我有 2 个函数,1 个比较两个字典的键和值,另一个函数对字典进行排序。代码如下:

import json
import requests


response = requests.get('https://reqres.in/api/users/2')
#actual_response saves the json as we get it from url above
actual_response= json.loads(response.text)

#expected response is saved after using pretty json that will be used to testing/comparing actual vs expected
expected_response={
    "data": {
        "id": 2,
        "first_name": "Janet",
        "last_name": "Weaver",
        "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"
    }
}

# sort the key values before comparing
def dict_sort(dictA,dictB):
    dictA, dictB = json.dumps(dictA, sort_keys=True), json.dumps(dictB, sort_keys=True)
    dictA == dictB

#if there are any failure due to mismatch in key value the function below will show that
def key_diff(dictA,dictB):
    for key,value in dictA.items():
        for keyB,valueB in dictB.items():
            for k,v in value.items():
                for k2,v2 in valueB.items():
                    if(key!= keyB):
                        print('Expected',key,' but got',keyB)
                    if(k!=k2):
                        print('Expected', k, ' but got', k2)
                    if(v!=v2):
                        print('Expected', v, ' but got', v2)
                    else:
                        print()

dict_sort(actual_response,expected_response)

if(actual_response==expected_response):
    print('Passed')
else:
    print('Failed')
    key_diff(actual_response,expected_response)

问题:没有差异时测试通过。但是,如果有任何差异,订单就会变得疯狂。这是我在预期响应中将数据更改为 dat 的示例:
预期的数据,但得到了数据

预期的 id 但得到了 last_name

预期为 2,但得到了 Weaver

排序函数是否应该更具体,而不是使用 sort_keys=True?顺便考虑一下 **args,但我认为在这种情况下这不是一个好的选择。

感谢您的专家评论和时间。

【问题讨论】:

  • 您的dict_sort 似乎没有做任何事情。您不能通过将输入参数分配给不同的(即使您使用相同的名称)变量来改变输入参数。您不必序列化为 json 进行比较。有关dict 比较的示例,请参见this question
  • 此外,如果它们被更改,它们将是 strings
  • @Selcuk,谢谢。这是一个关于比较的论坛!它帮助解决了我的问题。

标签: python json


【解决方案1】:
import requests
import json

# Here I am converting the expected payload in dictionary
expected_payload = json.loads("""[
    {
        "key": "data-center",
        "value": "All",
        "values": [
            "1",
            "2"
        ]
    },
    {
        "key": "router",
        "value": "All",
        "values": [
            "cisco",
            "juniper"
        ]
    },
    {
        "key": "virtual-machine",
        "value": "All",
        "values": [
            "dell",
            "hp",
            "None"
        ]
    },

]""")


def test_get_all_system_attributes():
    url = "http://" + str(ipaddr) + ":" + str(port) + "/Service/" + "system_attribute/"
    payload = {}
    headers = {
        'Content-Type': 'application/json'
    }
    actual_response = requests.request("GET", url, headers=headers, data=payload)
    assert json.loads(actual_response.text) == expected_payload

# json.loads(actual_response.text) will convert the response in dictionary
# using assert I am comparing the actual_response with exepcted_response

if __name__ == '__main__':
    test_get_all_system_attributes()

【讨论】:

  • 虽然这段代码可能会回答这个问题,但您是否可以考虑添加一些解释来说明您解决了什么问题,以及您是如何解决的?这将有助于未来的读者更好地理解您的答案并从中学习。
【解决方案2】:

我建议使用 unittest 并避免使用太多嵌套的 for 循环

from unittest import TestCase

import pandas as pd
import requests


def mocked_server_response():
    expected = {"data": {"id": 2, "first_name": "Janet", "last_name": "Weaver",
                         "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"}}
    data = expected['data']
    df = pd.DataFrame(my_dict['data'], index=[0])
    return [expected, data, df]


此时,mocked_server_response()将为您提供:

Out[27]:
   id first_name last_name                                             avatar
0   2      Janet    Weaver  https://s3.amazonaws.com/uifaces/faces/twitter...

现在,您可以轻松地在课堂上进行测试。


class TestServerResponse(TestCase):
    real_response = requests.get('https://reqres.in/api/users/2')

    def setUp(self):
        self.actual_response = real_response

    def response(self):
        self.assertEqual(self.actual_response, mocked_server_response()[0])

    def test_data_in_response(self):
        self.assertEqual(self.actual_response['data'], mocked_server_response()[1])

    def test_dataframe(self):
        self.assertEqual(pd.DataFrame(self.actual_response['data'], index=[0]), mocked_server_response()[2])




【讨论】:

    【解决方案3】:

    3.7 以下的 Python 版本不保证键顺序;当您需要创建一个记住键顺序的对象时,您应该使用collections.OrderedDict

    在 Python 3.7 中,插入顺序被保留,因此您的键将始终匹配。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-14
      • 2014-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多