Учебники

7) BDD тестирование API REST

Что такое тестирование BDD?

BDD (разработка на основе поведения) Тестирование — это метод гибкой разработки программного обеспечения, являющийся расширением TDD, т. Е. Разработка через тестирование. В BDD тестовые случаи написаны на естественном языке, который могут читать даже непрограммисты.

В этом уроке по BDD мы увидим BDD-тестирование REST API с Behave и Python.

Как работает BDD Testing?

Предположим, вы назначены для создания модуля «Перевод средств» в приложении Net Banking.

Есть несколько способов проверить это

  1. Перевод средств должен осуществляться, если на исходном счете достаточно средств.
  2. Перечисление средств должно быть выполнено, если информация о пункте назначения правильна
  3. Перевод средств должен выполняться, если пароль транзакции / код RSA / аутентификация безопасности для транзакции, введенной пользователем, верны
  4. Перевод средств должен осуществляться, даже если это банковский выходной
  5. Перевод средств должен состояться в будущем, как это установлено владельцем счета

Тестовый сценарий стал более сложным и сложным , как мы считаем , дополнительные функции , такие как суммы перевода X для интервала Y дней / месяцев, передачи по расписанию остановки , когда общая сумма достигает Z, и так далее

Общая тенденция разработчиков — разрабатывать функции и писать тестовый код позже. Как видно из приведенного выше случая, разработка Test Case для этого случая сложна, и разработчик отложит тестирование до выпуска, после чего он проведет быстрое, но неэффективное тестирование.

Чтобы преодолеть эту проблему (Behavior Driven Development) BDD был задуман. Это делает весь процесс тестирования простым для разработчика

В BDD все, что вы пишете, должно идти в  шаги Given-When-Then . Давайте рассмотрим тот же пример выше в BDD

Given that a fund transfer module in net banking application has been developed
And I am accessing it with proper authentication
WhenI shall transfer with enough balance in my source account
Or I shall transfer on a Bank Holiday
Or I shall transfer on a future date
And destination a/c details are correct
And transaction password/rsa code / security authentication for the transaction is correct
And press or click send button
Then amount must be transferred
And the event will be logged in log file

Разве это не легко писать, читать и понимать? Он охватывает все возможные тестовые примеры для модуля перевода средств и может быть легко изменен, чтобы вместить больше. Кроме того, это больше похоже на написание документации для модуля перевода средств.

Что такое REST API Testing?

Поскольку в настоящее время REST стал довольно популярным стилем для создания API, стало одинаково важно автоматизировать тестовые случаи REST API вместе с тестовыми примерами пользовательского интерфейса. Таким образом, в основном, это тестирование REST API включает тестирование действий CRUD (Create-Read-Update-Delete) с методами POST, GET, PUT и DELETE соответственно.

Что такое поведение?

Behave — одна из популярных платформ Python BDD для тестирования.

Давайте посмотрим, как работает Behave:

Файлы компонентов пишутся вашим бизнес-аналитиком / спонсором / кем-либо, кто имеет ваши сценарии поведения. Он имеет формат на естественном языке, описывающий функцию или часть функции с характерными примерами ожидаемых результатов.

Эти шаги сценария отображаются с реализациями шагов, написанными на Python

И, опционально, есть некоторые элементы управления средой (код для запуска до и после шагов, сценарии, функции или весь матч по стрельбе).

Давайте начнем с настройки нашей инфраструктуры тестирования автоматизации с Behave:

Настройка Behave Test Framework в Windows:

Установка:

Настройка проекта:

  • Создать новый проект
  • Создайте следующую структуру каталогов:

Особые файлы:

Итак, давайте создадим наш функциональный файл Sample_REST_API_Testing.feature, имеющий функцию, выполняющую операции CRUD на службе «posts».

В нашем примере я использовал http://jsonplaceholder.typicode.com/ posts пример службы REST.

Пример сценария POST:

Scenario: POST post example ->Here we are considering creating new post item using 'posts' service
Given: I set post posts API endpoint ->This is prerequisite for the test which is setting URL of posts service
When: I set HEADER param request content type as "application/json."
And set request body
And send POST HTTP request ->This is actual test step of sending a post request
Then: Then I receive valid HTPP response code 201 
And Response body "POST" is non-empty-> This is verification of response body	

Точно так же вы можете написать оставшиеся сценарии следующим образом:

Sample_REST_API_Testing.feature

Feature: Test CRUD methods in Sample REST API testing framework

Background:
	Given I set sample REST API url

Scenario: POST post example
  Given I Set POST posts api endpoint
 When I Set HEADER param request content type as "application/json." 
    And Set request Body
 And Send a POST HTTP request 
 Then I receive valid HTTP response code 201
    And Response BODY "POST" is non-empty. 


Scenario: GET posts example
  Given I Set GET posts api endpoint "1"
  When I Set HEADER param request content type as "application/json." 
	And Send GET HTTP request
  Then I receive valid HTTP response code 200 for "GET." 
	And Response BODY "GET" is non-empty


Scenario: UPDATE posts example
  Given I Set PUT posts api endpoint for "1"
  When I Set Update request Body
	And Send PUT HTTP request
  Then I receive valid HTTP response code 200 for "PUT." 
	And Response BODY "PUT" is non-empty


Scenario: DELETE posts example
  Given I Set DELETE posts api endpoint for "1"
  When I Send DELETE HTTP request
  Then I receive valid HTTP response code 200 for "DELETE." 

Шаги реализации

Теперь для функциональных шагов, используемых в вышеупомянутых сценариях, вы можете написать реализации в файлах Python в каталоге «steps».

Структура поведения идентифицирует функцию Step с помощью декораторов, соответствующих предикату файла функций. Например, данный предикат в Сценарии файла объектов выполняет поиск функции шага, имеющей декоратор «задано». Подобное совпадение происходит для Когда и Тогда. Но в случае «Но», «И» функция Step принимает декоратор так же, как и предыдущий шаг. Например, если для заданного дано «И», соответствующий декоратор пошаговой функции — @given.

Например, когда шаг для POST может быть реализован следующим образом:

@when (u'I Set HEADER param request content type as "{header_conent_type}"')
Mapping of When, here notice “application/json” is been passed from feature file for "{header_conent_type}” . This is called as parameterization


def step_impl (context, header_conent_type):
This is step implementation method signature

request_headers['Content-Type'] = header_conent_type
Step implementation code, here you will be setting content type for request header

Аналогично, реализация других шагов в файле шага python будет выглядеть так:

sample_step_implementation.py

from behave import given, when, then, step
import requests

api_endpoints = {}
request_headers = {}
response_codes ={}
response_texts={}
request_bodies = {}
api_url=None

@given(u'I set sample REST API url')
def step_impl(context):
    global api_url
    api_url = 'http://jsonplaceholder.typicode.com'

# START POST Scenario
@given(u'I Set POST posts api endpoint')
def step_impl(context):
    api_endpoints['POST_URL'] = api_url+'/posts'
    print('url :'+api_endpoints['POST_URL'])

@when(u'I Set HEADER param request content type as "{header_conent_type}"')
def step_impl(context, header_conent_type):
    request_headers['Content-Type'] = header_conent_type

#You may also include "And" or "But" as a step - these are renamed by behave to take the name of their preceding step, so:
@when(u'Set request Body')
def step_impl(context):
    request_bodies['POST']={"title": "foo","body": "bar","userId": "1"}

#You may also include "And" or "But" as a step - these are renamed by behave to take the name of their preceding step, so:
@when(u'Send POST HTTP request')
def step_impl(context):
    # sending get request and saving response as response object
    response = requests.post(url=api_endpoints['POST_URL'], json=request_bodies['POST'], headers=request_headers)
    #response = requests.post(url=api_endpoints['POST_URL'], headers=request_headers) #https://jsonplaceholder.typicode.com/posts
    # extracting response text
    response_texts['POST']=response.text
    print("post response :"+response.text)
    # extracting response status_code
    statuscode = response.status_code
    response_codes['POST'] = statuscode

@then(u'I receive valid HTTP response code 201')
def step_impl(context):
    print('Post rep code ;'+str(response_codes['POST']))
    assert response_codes['POST'] is 201
# END POST Scenario

# START GET Scenario
@given(u'I Set GET posts api endpoint "{id}"')
def step_impl(context,id):
    api_endpoints['GET_URL'] = api_url+'/posts/'+id
    print('url :'+api_endpoints['GET_URL'])

#You may also include "And" or "But" as a step - these are renamed by behave to take the name of their preceding step, so:
@when(u'Send GET HTTP request')
def step_impl(context):
    # sending get request and saving response as response object
    response = requests.get(url=api_endpoints['GET_URL'], headers=request_headers) #https://jsonplaceholder.typicode.com/posts
    # extracting response text
    response_texts['GET']=response.text
    # extracting response status_code
    statuscode = response.status_code
    response_codes['GET'] = statuscode

@then(u'I receive valid HTTP response code 200 for "{request_name}"')
def step_impl(context,request_name):
    print('Get rep code for '+request_name+':'+ str(response_codes[request_name]))
    assert response_codes[request_name] is 200

@then(u'Response BODY "{request_name}" is non-empty')
def step_impl(context,request_name):
    print('request_name: '+request_name)
    print(response_texts)
    assert response_texts[request_name] is not None
# END GET Scenario

#START PUT/UPDATE
@given(u'I Set PUT posts api endpoint for "{id}"')
def step_impl(context,id):
    api_endpoints['PUT_URL'] = api_url + '/posts/'+id
    print('url :' + api_endpoints['PUT_URL'])

@when(u'I Set Update request Body')
def step_impl(context):
    request_bodies['PUT']={"title": "foo","body": "bar","userId": "1","id": "1"}

@when(u'Send PUT HTTP request')
def step_impl(context):
    # sending get request and saving response as response object  # response = requests.post(url=api_endpoints['POST_URL'], headers=request_headers) #https://jsonplaceholder.typicode.com/posts
    response = requests.put(url=api_endpoints['PUT_URL'], json=request_bodies['PUT'], headers=request_headers)
    # extracting response text
    response_texts['PUT'] = response.text
    print("update response :" + response.text)
    # extracting response status_code
    statuscode = response.status_code
    response_codes['PUT'] = statuscode
#END PUT/UPDATE

#START DELETE
@given(u'I Set DELETE posts api endpoint for "{id}"')
def step_impl(context,id):
    api_endpoints['DELETE_URL'] = api_url + '/posts/'+id
    print('url :' + api_endpoints['DELETE_URL'])

@when(u'I Send DELETE HTTP request')
def step_impl(context):
    # sending get request and saving response as response object
    response = requests.delete(url=api_endpoints['DELETE_URL'])
    # response = requests.post(url=api_endpoints['POST_URL'], headers=request_headers) #https://jsonplaceholder.typicode.com/posts
    # extracting response text
    response_texts['DELETE'] = response.text
    print("DELETE response :" + response.text)
    # extracting response status_code
    statuscode = response.status_code
    response_codes['DELETE'] = statuscode
#END DELETE

Запуск тестов:

Теперь мы закончили с нашей частью разработки тестового скрипта, поэтому давайте запустим наши тесты:

Выполните следующую команду в командной строке, чтобы запустить наш файл функций

C: \ Programs \ Python \ Python37> ведут себя -f довольно C: \ <путь к вашему проекту> \ features \ feature_files_folder \ Sample_REST_API_Testing.feature

Это отобразит результаты выполнения теста следующим образом:

Отображение отчета на консоли

Давайте посмотрим еще одну классную вещь здесь.

Поскольку пользователи всегда предпочитают видеть результаты тестов в более удобочитаемом и презентабельном формате, давайте создадим отчеты в формате HTML с помощью Allure.

Отчеты

Во-первых, вам необходимо установить форматер Allure Behave [ https://docs.qameta.io/allure/ ]:

А теперь выполните следующую команду:

Для отчетов

> вести себя -f json -o <путь-к-папке-отчету> Sample_REST_API_Testing.feature

<путь к папке allure-bin >> allure serve <путь к папке отчета>

Это сгенерирует ваш отчет о результатах теста в презентабельном и информативном формате, например:

Протокол испытаний в формате HTML

Отчет о тестировании, отображающий индивидуальный результат сценария

Резюме:

  • BDD — это развитие, основанное на поведении. Это один из методов гибкой разработки программного обеспечения.
  • В настоящее время REST стал довольно популярным стилем для создания API, и в равной степени важно автоматизировать тестовые случаи REST API вместе с тестовыми примерами пользовательского интерфейса.
  • BDD имеет формат на естественном языке, описывающий функцию или часть функции с типичными примерами ожидаемых результатов
  • Behave Framework идентифицирует функцию Step с помощью декораторов, соответствующих предикату файла функций.