2

You will get a small json response back when you go to this site https://reqres.in/api/users/2

I am saving the response in a variable(actual). I have also put the response in another variable(expected).Both responses are same. I am changing the values to test failed cases. The ultimate goal is to compare 2 and make sure they match.

I have 2 functions, 1 compares keys and value of both dictionaries and the other function sorts the dictionaries. Code below:

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)

Problem: The test passes when there is no difference.However if there is any difference the order goes crazy. Here is an example where I changed data to dat inside expected response:
Expected data but got dat

Expected id but got last_name

Expected 2 but got Weaver

Should the sort function be more specific rather than using sort_keys=True?By the way thought about **args but I don't think that is a good choice in this scenario.

Thank You for your expert comment and time.

Sheikh Rahman
  • 895
  • 3
  • 14
  • 29
  • 1
    Your `dict_sort` does not seem to be doing anything. You can't mutate input arguments by assigning them to a different (even if you use the same name) variable. You don't have to serialize to json to compare. See [this question](https://stackoverflow.com/questions/1165352/calculate-difference-in-keys-contained-in-two-python-dictionaries) for an example of `dict` comparison. – Selcuk Feb 13 '19 at 03:17
  • Besides, if they were changed, they would be _strings_. – Amadan Feb 13 '19 at 03:21
  • 1
    @Selcuk, Thanks. What a forum that is about comparison!. It helped solve my issue. – Sheikh Rahman Feb 13 '19 at 03:30

3 Answers3

0

Key order is not guaranteed in Python versions under 3.7; you should use collections.OrderedDict when you need to create an object that remembers key order.

In Python 3.7 the insertion ordered is preserved, so your keys will always match.

Obsidian Age
  • 41,205
  • 10
  • 48
  • 71
0

I advise to use unittest and avoid using so much nested for loops

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]


At this point, the mocked_server_response()will get you this :

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

Now, you can easily make test in a class.


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])




-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()
alok kumar
  • 67
  • 1
  • 5
  • While this code might answer the question, can you consider adding some explanation for what the problem was you solved, and how you solved it? This will help future readers to understand your answer better and learn from it. – dan1st Mar 04 '20 at 10:42