Сравнивая результат Json из функции в роботе Framework

Попытка создать тестовый пример в рамках робота.

У нас есть пара остальных apis, которая возвращает нам Json как результат. Чтобы вызвать такой случай, мы использовали следующий код в rest2.py

def restJSON():
    r = requests.get("http://httpbin.org/get")
#    print "Code" , r.status_code
#    print "Text " , r.text
    return r.json()

Мы сохранили JSON внутри файла вывода. И мы написали тестовый пример робота для оценки сравнения JSON, как показано ниже

*** Settings ***
 Library   rest2.py
 Library   OperatingSystem
*** Test Cases ***
 Example that calls a python keyword
  ${result}=   restJSON
  ${json}=   Get file   output
  Should be equal   ${result}   ${json}

Но когда мы запускаем тестовый пример Pybot, мы получаем ошибку, в которой говорится, что оба json не совпадают.

--------------------------------
pybot testSuite.txt
--------------------------------
==============================================================================
testSuite
==============================================================================
Example that calls a python keyword                                   | FAIL |
{u'origin': u'10.252.30.94, 69.241.25.16', u'headers': {u'Via': u'1.1 localhost (squid/3.1.14)', u'Accept-Encoding': u'gzip, deflate, compress', u'Accept': u'*/*', u'User-Agent': u'python-requests/2.2.1 CPython/2.7.6 Linux/3.16.0-30-generic', u'Host': u'httpbin.org', u'Cache-Control': u'max-age=259200'}, u'args': {}, u'url': u'http://httpbin.org/get'} != {u'origin': u'10.252.30.94, 69.241.25.16', u'headers': {u'Via': u'1.1 localhost (squid/3.1.14)', u'Accept-Encoding': u'gzip, deflate, compress', u'Accept': u'*/*', u'User-Agent': u'python-requests/2.2.1 CPython/2.7.6 Linux/3.16.0-30-generic', u'Host': u'httpbin.org', u'Cache-Control': u'max-age=259200'}, u'args': {}, u'url': u'http://httpbin.org/get'}
------------------------------------------------------------------------------
testSuite                                                             | FAIL |
1 critical test, 0 passed, 1 failed
1 test total, 0 passed, 1 failed
==============================================================================

Файл JSON одинаков. Но все-таки его тест Failing говорит о том, что оба они не одинаковы. Это правильный способ сравнения, или у нас есть какой-то другой способ сделать это в среде роботов.

3 ответа

Почему бы не использовать уже существующие библиотеки:

Пример кода:

*** Settings ***
Library                     RequestsLibrary
Library                     Collections
Library                     XML  use_lxml=True
Force Tags                  REST


*** Variables ***
${SERVICE_ROOT}  http://ip.jsontest.com/
${SERVICE_NAME}  testing

*** Keywords ***
json_property_should_equal
    [Arguments]  ${json}  ${property}  ${value_expected}
    ${value_found} =    Get From Dictionary  ${json}  ${property}
    ${error_message} =  Catenate  SEPARATOR=  Expected value for property "  ${property}  " was "  ${value_expected}  " but found "  ${value_found}  "
    Should Be Equal As Strings  ${value_found}  ${value_expected}  ${error_message}    values=false

*** Test Cases ***
Example REST JSON
  Create session  ${SERVICE_NAME}  ${SERVICE_ROOT}
  ${headers}=  Create Dictionary  Content-Type=application/json  Accept=application/json
  ${result}=  Get Request  ${SERVICE_NAME}  ${SERVICE_ROOT}  headers=${headers}
  Should Be Equal  ${result.status_code}  ${200}
  Log  ${result.content}
  ${json}=    To Json    ${result.content}
  ${pp}=  To Json  ${result.content}  pretty_print=True
  Log  ${pp}
  json_property_should_equal  ${json}  ip  [Your_IP]

Не забудьте установить все необходимые библиотеки:

pip install robotframework-requests
pip install requests

Get File читает содержимое файла и возвращает строку; в то же время функция python возвращает объект dict. Похоже, вы сравниваете dict со строкой - а они просто не могут вернуть равно.

Если вы преобразуете вывод файла в dict, то проверка, скорее всего, пройдет:

# your other code
${json_file}=   Get file   output
${json_file}=   Evaluate   json.loads("""${json_file}""")    json     # use the json module to transform str->dict

Should Be Equal    ${result}    ${json_file}

# even better - more verbose logging if values differ, or there are missing keys:
Dictionaries Should Be Equal    ${result}    ${json_file}

Каков ответ, когда вы делаете:

Should Be Equal As Strings    ${result}   ${json}

Я нахожу ваш метод достижения того, что вы хотите, немного странным, на вашем месте я бы использовал http-библиотеку или библиотеку запросов

https://github.com/peritus/robotframework-httplibrary https://github.com/bulkan/robotframework-requests

Рабочие примеры

поместите это в файл.robot

*** Settings ***
Library    jsonlib.py

*** Variables ***
${response_json}    {"key1": 33, "key2": "string", "key3": [1,2,3,"sring"], "name": "hans"}
${expected_json}    {"key1": 77, "key2": "string", "key3": [1,2,3,"sring"], "name": "OTTO", "age": 33}

*** Test Cases ***
response meets expectation
    &{json1}=    Evaluate    json.loads('''${response_json}''')    json
    &{json2}=    Evaluate    json.loads('''${expected_json}''')    json
    Log Dictionary    ${json1}
    Log Dictionary    ${json2}
    # ${type}=    evaluate    type(${json1}).__name__
    # ${type}=    evaluate    type(&{json2})
    response_meets_expectation  ${json1}  ${json2}

compare json payloads
    &{json1}=    Evaluate    json.loads('''${response_json}''')    json
    &{json2}=    Evaluate    json.loads('''${expected_json}''')    json
    compare_json_payloads  ${json1}  ${json2}

json payloads should match
    &{json1}=    Evaluate    json.loads('''${response_json}''')    json
    &{json2}=    Evaluate    json.loads('''${expected_json}''')    json
    json_paylodas_should_match  ${json1}  ${json2}

поместите это в jsonlib.py в той же папке, что и файл.robot

# -*- coding: utf-8 -*-

import json
import jsondiff
from deepdiff import DeepDiff
# from deepdiff import DeepSearch, grep
from pprint import pprint
from robot.api import logger


class JsonCompareError(Exception):
    pass

def response_meets_expectation(response, expectation):
    union = jsondiff.patch(response, expectation)
    difference = jsondiff.diff(response, union)
    if difference:
            raise JsonCompareError("Diff found: {}".format(difference))
    else:
        return True

def compare_json_payloads(response_json, expected_json):
    logger.debug("Compare JSON payloads")
    diff = DeepDiff(response_json, expected_json, ignore_order=True, verbose_level=2)
    logger.debug("Values changed: {}".format(diff['values_changed']))
    return diff.to_dict()

def json_paylodas_should_match(response_json, expected_json):
    diff = DeepDiff(response_json, expected_json, verbose_level=2)
    if diff != {}:
        raise JsonCompareError("Payloads do not match! Differences: {}".format(diff))
    else:
        return True

Используя https://github.com/Accruent/robotframework-zoomba это будет примерно так:

Library         Zoomba.APILibrary

*** Test Cases ***
Example Test
   ${headers}=  Create Dictionary  Content-Type=application/json  Accept=application/json
   ${actual_response}=   Call Get Request   ${headers}    http://httpbin.org/get
   Validate Response Contains Expected Response     ${actual_response}    ${expected_response}

Это будет проходить ключ за ключом для проверки результатов, все, что не получится, будет выглядеть так:

Key(s) Did Not Match:
------------------
Key: pear
Expected: fish
Actual: bird
------------------
Full List Breakdown:
Expected: [{'apple': 'cat', 'banana': 'dog', 'pear': 'fish'}, {'apple': 'cat', 'banana': 'mice', 'pear': 'bird'}, {'apple': 'dog', 'banana': 'mice', 'pear': 'cat'}]
Actual: [{'apple': 'cat', 'banana': 'dog', 'pear': 'bird'}]

Please see differing value(s)"

Документы здесь: https://accruent.github.io/robotframework-zoomba/docs/APILibraryDocumentation.html

Другие вопросы по тегам