Что такое BDD-тестирование? Пример платформы

Что такое BDD-тестирование (разработка, основанная на поведении)?

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

Как работает BDD-тестирование?

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

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

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

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

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

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

В BDD все, что вы пишете, должно войти в Дано-Когда-Тогда шаги. Давайте рассмотрим тот же пример выше в 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?

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

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

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

Давайте посмотрим, как работает функция Behave:

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

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

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

Давайте начнем с настройки нашей среды автоматизированного тестирования с помощью Behave:

Настройка платформы тестирования BDD Windows

Установка:

  • Загрузить и установить Python 3 из https://www.python.org/
  • Выполните следующую команду в командной строке, чтобы установить поведение
  • pip install ведет себя
  • IDE: я использовал PyCharm Community Edition. https://www.jetbrains.com/pycharm/download

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

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

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

Функциональные файлы:

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

В нашем примере я использовал http://jsonplaceholder.typicode.com/ публикует пример 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».

Платформа Behave идентифицирует функцию 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

Аналогично реализация других шагов в файле Step 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:\Программы\Python\Python37>вести себя -f красиво С:\ \features\папка_feature_files\Sample_REST_API_Testing.feature

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

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

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

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

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

Согласно отчетам

Сначала вам необходимо установить форматтер Allure Behave [https://docs.qameta.io/allure-report/]:

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

Для отчетов

>вести себя -f json -o Sample_REST_API_Testing.feature

> очарование подачи

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

Согласно отчетам

Отчет об испытаниях в формате HTML

Отчет об испытаниях в формате HTML

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

Итого

  • BDD — это разработка, основанная на поведении. Это один из методов гибкой разработки программного обеспечения.
  • В настоящее время REST стал довольно популярным стилем создания API, поэтому стало одинаково важно автоматизировать тестовые сценарии REST API наряду с тестовыми примерами пользовательского интерфейса.
  • BDD имеет формат естественного языка, описывающий функцию или часть функции с репрезентативными примерами ожидаемых результатов.
  • Платформа Behave определяет функцию Step путем сопоставления декораторов с предикатом файла объекта.
  • Примеры сред тестирования BDD: 1) Cucumber 2) SpecFlow 3) Quantum 4) JBehave 5) Codeception