¿Qué son las pruebas BDD? Ejemplo de marco

¿Qué son las pruebas BDD (desarrollo impulsado por el comportamiento)?

Pruebas BDD (desarrollo impulsado por el comportamiento) es una técnica de desarrollo ágil de software y es una extensión de TDD, es decir, Test Driven Development. En BDD, los casos de prueba se escriben en un lenguaje natural que incluso los no programadores pueden leer.

¿Cómo funcionan las pruebas BDD?

Considere que está asignado a crear un módulo de transferencia de fondos en una aplicación de Net Banking.

Hay varias formas de probarlo.

  1. La transferencia de fondos debe realizarse si hay suficiente saldo en la cuenta de origen
  2. La transferencia de fondos debe realizarse si los detalles de la cuenta de destino son correctos
  3. La transferencia de fondos debe realizarse si la contraseña de la transacción/código rsa/autenticación de seguridad para la transacción ingresada por el usuario es correcta
  4. La transferencia de fondos debe realizarse incluso si es un día festivo
  5. La transferencia de fondos debe realizarse en una fecha futura establecida por el titular de la cuenta.

El sistema Escenario de prueba se vuelven más elaborados y complejos a medida que consideramos características adicionales como la transferencia de un monto X por un intervalo de Y días/meses, detener la transferencia programada cuando el monto total llega a Z, etc.

La tendencia general de los desarrolladores es desarrollar funciones y escribir el código de prueba más tarde. Como se evidencia en el caso anterior, Caso de prueba El desarrollo de este caso es complejo y el desarrollador lo pospondrá. Pruebas hasta su lanzamiento, momento en el que realizará pruebas rápidas pero ineficaces.

Para superar este problema (Behavior Driven Development) se concibió BDD. Facilita todo el proceso de prueba para un desarrollador.

En BDD, todo lo que escriba debe ir a Dado-cuando-entonces pasos. Consideremos el mismo ejemplo anterior en 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

¿No es fácil escribir, leer y comprender? Cubre todos los casos de prueba posibles para el módulo de transferencia de fondos y se puede modificar fácilmente para dar cabida a más. Además, es más como escribir documentación para el módulo de transferencia de fondos.

¿Qué son las pruebas de API REST?

Dado que REST se ha convertido en un estilo bastante popular para crear API hoy en día, se ha vuelto igualmente importante automatizar los casos de prueba de API REST junto con los casos de prueba de UI. Básicamente, estos DESCANSO Pruebas de API Implica probar acciones CRUD (Crear-Leer-Actualizar-Eliminar) con los métodos POST, GET, PUT y DELETE respectivamente.

¿Qué es comportarse?

Comportarse es uno de los populares. Python Marcos de prueba BDD.

Veamos cómo funciona Behave:

Los archivos de características son escritos por su analista de negocios/patrocinador/cualquier persona que incluya sus escenarios de comportamiento. Tiene un formato de lenguaje natural que describe una característica o parte de una característica con ejemplos representativos de los resultados esperados.

Estos pasos del escenario están mapeados con implementaciones de pasos escritas en Python.

Y, opcionalmente, hay algunos controles ambientales (código para ejecutar antes y después de los pasos, escenarios, características o todo el tiroteo).

Comencemos con la configuración de nuestro marco de prueba de automatización con Behave:

Configuración del marco de pruebas BDD Comportarse en Windows

Instalación:

Configuración del proyecto:

  • Crear un nuevo proyecto
  • Cree la siguiente estructura de directorio:

Configuración del proyecto

Archivos de características:

Entonces, creemos nuestro archivo de funciones. Característica_muestra_REST_API_Testing. que tiene una función como Realizar operaciones CRUD en el servicio 'publicaciones'.

En nuestro ejemplo, he usado http://jsonplaceholder.typicode.com/ publica un servicio REST de muestra.

Ejemplo de escenario 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	

De manera similar, puedes escribir los Escenarios restantes de la siguiente manera:

Configuración del proyecto

Característica_muestra_REST_API_Testing.

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." 

Implementación de pasos

Ahora, para los pasos de funciones utilizados en los escenarios anteriores, puede escribir implementaciones en Python archivos en el directorio “pasos”.

El marco de comportamiento identifica la función Paso mediante decoradores que coinciden con el predicado del archivo de características. Por ejemplo, el predicado dado en el escenario del archivo de características busca una función de paso que tenga un decorador "dado". Se produce una coincidencia similar para Cuando y Entonces. Pero en el caso de "Pero", "Y", la función de paso toma el mismo decorador que el paso anterior. Por ejemplo, si 'Y' viene por Dado, el decorador de función de paso coincidente es @dado.

Por ejemplo, cuando el paso para POST se puede implementar de la siguiente manera:

@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

De manera similar, la implementación de otros pasos en el archivo de pasos de Python se verá así:

Implementación de pasos

ejemplo_paso_implementación.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

Ejecutando las pruebas

Ahora que hemos terminado con nuestra parte de desarrollo del script de prueba, ejecutemos nuestras pruebas:

Ejecute el siguiente comando en el símbolo del sistema para ejecutar nuestro archivo de funciones

C:\Programas\Python\Python37>comportarse -f bonita C:\\features\feature_files_folder\Característica_muestra_REST_API_Testing.

Esto mostrará los resultados de la ejecución de la prueba de la siguiente manera:

Ejecutando las pruebas

Visualización de informes en la consola.

Veamos una cosa interesante más aquí.

Como los usuarios siempre prefieren ver los resultados de las pruebas en un formato más legible y presentable, tengamos informes en formato HTML con la ayuda de Allure.

Informes

Primero, necesita instalar el formateador Allure Behave [https://docs.qameta.io/allure-report/]:

Y ahora ejecuta el siguiente comando:

Para informes

>comportarse -f json -o Característica_muestra_REST_API_Testing.

> servicio de encanto

Esto generará el informe de resultados de su prueba en un formato presentable e informativo como este:

Informes

Informe de prueba en formato HTML

Informe de prueba en formato HTML

Informe de prueba que muestra el resultado del escenario individual

Resumen

  • BDD es desarrollo impulsado por el comportamiento. Es una de las técnicas de desarrollo ágil de software.
  • REST se ha convertido en un estilo bastante popular para crear API hoy en día; se ha vuelto igualmente importante automatizar los casos de prueba de API REST junto con los casos de prueba de UI.
  • BDD tiene un formato de lenguaje natural que describe una característica o parte de una característica con ejemplos representativos de los resultados esperados.
  • El marco de comportamiento identifica la función Paso mediante decoradores que coinciden con el predicado del archivo de características
  • Ejemplos de marcos de prueba de BDD: 1) Cucumber 2) SpecFlow 3) Quantum 4) JBehave 5) Codecepción