Що таке тестування BDD? Приклад рамки

Що таке BDD (Behavior Driven Development) тестування?

BDD (Behavior-driven development) тестування це техніка гнучкої розробки програмного забезпечення, яка є розширенням 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 відповідно.

Що таке Behave?

Behave є одним із популярних Python Тестові рамки BDD.

Давайте подивимося, як працює Behave:

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

Ці кроки сценарію зіставляються із записаними реалізаціями кроків Python.

І, за бажанням, є деякі засоби контролю середовища (код для запуску до та після кроків, сценаріїв, функцій або всього матчу зі стрільбою).

Давайте почнемо з налаштування нашої системи тестування автоматизації за допомогою Behave:

Налаштування BDD Testing Framework Behave on Windows

Установка:

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

Налаштування проекту:

  • Створіть новий проект
  • Створіть таку структуру каталогу:

Налаштування проекту

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

Отже, давайте створимо наш файл функцій Зразок_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	

Подібним чином ви можете записати інші сценарії так:

Налаштування проекту

Зразок_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." 

Реалізація кроків

Тепер для функцій Steps, які використовуються в наведених вище сценаріях, ви можете писати реалізації Python файли в каталозі “steps”.

Структура Behave ідентифікує функцію Step за допомогою декораторів, що збігаються з предикатом файлу функції. Наприклад, предикат Given у файлі Feature Scenario шукає покрокову функцію, яка має «вказаний» декоратор. Подібне зіставлення відбувається для Коли і Тоді. Але у випадку "Але", "І" функція Step використовує декоратор так само, як і попередній крок. Наприклад, якщо для Given надійшло «І», відповідним декоратором крокової функції є @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 красиво C:\ \features\feature_files_папка\Зразок_REST_API_Testing.feature

Це відобразить результати виконання тесту таким чином:

Виконання тестів

Відображення звіту на консолі

Давайте подивимося ще на одну цікаву річ.

Оскільки користувачі завжди віддають перевагу перегляду результатів тестів у більш зрозумілому та презентабельному форматі, створимо звіти у форматі HTML за допомогою Allure.

Звіти

Спочатку вам потрібно встановити програму форматування Allure Behave [https://docs.qameta.io/allure-report/]:

А тепер виконайте таку команду:

Для звітів

>поводитися -f json -o Зразок_REST_API_Testing.feature

> привабливість служити

Це створить ваш звіт про результати тестування в презентабельному та інформативному форматі, як-от:

Звіти

Звіт про випробування у форматі HTML

Звіт про випробування у форматі HTML

Звіт про тестування, що відображає результати індивідуального сценарію

Підсумки

  • BDD – це розвиток, керований поведінкою. Це одна з технік гнучкої розробки програмного забезпечення.
  • Сьогодні REST став досить популярним стилем створення API, але не менш важливо автоматизувати тестові випадки REST API та тестові випадки інтерфейсу користувача.
  • BDD має формат природної мови, що описує функцію або частину функції з типовими прикладами очікуваних результатів
  • Структура Behave ідентифікує функцію Step за допомогою декораторів, що збігаються з предикатом файлу функції
  • Приклади структур тестування BDD: 1) Cucumber 2) SpecFlow 3) Quantum 4) JBehave 5) Кодування