ruby - restassured - bdd for web services
REST API prueba pepino pasos mejor práctica (8)
Aquí hay un ejemplo (lo suficientemente cerca) de lo que dice el "Libro del Pepino" del Programador Pragmático acerca de las pruebas de API REST a través de Cuke, y parece estar más relacionado con su segundo ejemplo:
Feature: Addresses
In order to complete the information on the place
I need an address
Scenario: Addresses
Given the system knows about the following addresses:
[INSERT TABLE HERE or GRAB FROM DATABASE]
When client requests GET /addresses
Then the response should be JSON:
"""
[
{"venue": "foo", "address": "bar"},
{ more stuff }
]
"""
STEP DEFINITION:
Given(/^the system knows about the following addresses:$/) do |addresses|
# table is a Cucumber::Ast::Table
File.open(''addresses.json'', ''w'') do |io|
io.write(addresses.hashes.to_json)
end
end
When(/^client requests GET (.*)$/) do |path|
@last_response = HTTParty.get(''local host url goes here'' + path)
end
Then /^the response should be JSON:$/ do |json|
JSON.parse(@last_response.body).should == JSON.parse(json)
end
ENV File:
require File.join(File.dirname(__FILE__), ''..'', ''..'', ''address_app'')
require ''rack/test''
require ''json''
require ''sinatra''
require ''cucumber''
require ''httparty''
require ''childprocess''
require ''timeout''
server = ChildProcess.build("rackup", "--port", "9000")
server.start
Timeout.timeout(3) do
loop do
begin
HTTParty.get(''local host here'')
break
rescue Errno::ECONNREFUSED => try_again
sleep 0.1
end
end
end
at_exit do
server.stop
end
Intentando escribir los pasos de la característica de pepino para la prueba API REST.
No estoy seguro de cuál es el mejor enfoque:
Given I log in with username and password
When I add one "tv" into my cart
And I check my cart
Then I should see the item "tv" is in my cart
o
Given the client authenticate with username and password
When the client send POST to "/cart/add" with body "{item: body}"
Then the response code should be "200"
And the response body should expect "{success: true}"
When the client send GET to "/cart"
Then the response code should be "200"
And the response body should expect "{"items": ["tv"]}"
¿Hay alguna convención que seguir cuando las personas que intentan escribir los pasos de pepino para la API REST?
Consulte aquí: https://github.com/ctco/cukes-rest . Proporciona un DSL de pepino para probar las API RESTful.
Creo que el primero es mejor. Pondría lo técnico en las clases y módulos rubí. Por ejemplo, como el módulo cart.add (elementos) en el paso cuándo y en el paso siguiente, ponga expect (carrito.item) .para incluir (''elementos'' => a_string_matching (elemento))
Por esto, las clases y módulos ruby se pueden reutilizar en otros pasos de características. Por ejemplo, tal vez tenga otro escenario que agregaría múltiples artículos al carrito y luego validaría la cantidad total.
Sin embargo, el segundo 1 creo que puede hacerlo como características técnicas. Por ejemplo, el encabezado común / global o la solicitud de cuerpo se espera en toda la API.
Hay algunas bibliotecas ahora para pruebas REST del lado del servidor con pepino en Ruby . Aquí hay una pareja:
- cucumber-api-steps . (Recomendado)
- Cucumber-API . Un pequeño tutorial para eso está here .
La biblioteca que he estado usando para las pruebas de REST del lado del servidor con pepino es cucumber-api-steps .
cucumber-api-steps
Así es como escribiría su prueba usando ''pepinos-api-pasos'' (Recomendado):
@success
Scenario: Successfully add to cart
Given I am logged in
When I send a POST request to “/cart/add” with the following:
| item | body |
Then the response status should be “200”
And the JSON response should have "success" with the text "true"
When I send a GET request to “/cart”
Then the response status should be “200”
And the JSON response should be "{''items'': [''tv'']}"
Y así es como se ven mis pruebas usando ''pepinos-api-pasos'' :
@success
Scenario: Successfully log in
Given I am logged out
When I send a POST request to “/login” with:
| username | [email protected] |
| password | mypassword |
Then the response status should be “200”
And the JSON response should have "firstName" with the text "Katie"
Cucumber-API
Así es como escribiría tu prueba usando ''pepino-api'' :
@success
Scenario: Successfully add to cart
Given I am logged in
When I send a POST request to “/cart/add”
And I set JSON request body to ''{item: body}''
Then the response status should be “200”
And the response should have key “success” with value “true”
When I send a GET request to “/cart”
Then the response status should be “200”
And the response should follow "{''items'': [''tv'']}"
Y así es como se ven mis pruebas usando ''pepino-api'' :
@success
Scenario: Successfully log in
Given I am logged out
When I send a POST request to “/login” with:
| username | [email protected] |
| password | mypassword |
Then the response status should be “200”
And the response should have key “firstName”
- Nota sobre la API de pepino: actualmente no hay forma de hacerlo,
should have key “firstName” with value “Katie”
. La parte "con valor" no se ha hecho todavía. - También "Seguir" espera un archivo JSON
Otro recurso está here , pero es viejo (2011).
He estado usando pepino para probar y, lo que es más importante, documentar la API que creé utilizando rails-api
en mi proyecto actual. Busqué algunas herramientas para usar y terminé usando una combinación de cucumber-api-steps y json_spec . Funciono bien para mi.
No hay ninguna convención sobre cómo escribir los pasos de pepino. La forma en que escribas tus pasos depende de cómo quieras usar tu suite de pepinos. Utilicé la salida de pepino como referencia para nuestros desarrolladores de cliente Angular JS para implementar el cliente API. Así que mis pasos de pepino contenían las solicitudes y respuestas reales de JSON junto con el código de estado para cada escenario. Esto hizo que fuera realmente fácil comunicarse con un equipo del lado del cliente cuando algo cambiaba (especialmente cuando el equipo del lado del cliente no estaba físicamente presente en mi lugar de trabajo).
Cada vez que creaba o actualizaba una API, el servidor de CI ejecutaba cucumber como parte de la compilación y movía la salida con formato HTML a una ubicación "build_artifacts" que se puede abrir en el navegador. Los desarrolladores del lado del cliente siempre obtendrían la referencia más reciente de esa manera.
He escrito todo esto en una publicación de blog sobre la creación de una API JSON probada, documentada y versionada , espero que te ayude de alguna manera.
Me topé con este artículo útil: http://gregbee.ch/blog/effective-api-testing-with-cucumber
Para resumir...
Scenario: List fruit
Given the system knows about the following fruit:
| name | color |
| banana | yellow |
| strawberry | red |
When the client requests a list of fruit
Then the response is a list containing 2 fruits
And one fruit has the following attributes:
| attribute | type | value |
| name | String | banana |
| color | String | yellow |
And one fruit has the following attributes:
| attribute | type | value |
| name | String | strawberry |
| color | String | red |
La validación de un resultado contra JSON es un asunto delicado porque si el resultado es una matriz, los elementos pueden no ser el mismo orden en que se está validando en la prueba.
Uno de los intentos originales de Cucumber, que contribuye a su diseño, es cerrar la brecha entre la implementación técnica y las personas que conocen las necesidades del negocio, de modo que las descripciones de las pruebas puedan ser escritas y / o comprendidas por los no desarrolladores. Como tal, no es un gran ajuste para especificaciones técnicas detalladas, o pruebas de unidad de golpe por golpe.
Así que eso me indicaría su primera descripción de prueba, si esa es también la razón por la que está usando Cucumber.
No hay ningún problema importante con la implementación de pruebas como la segunda versión, Cucumber puede admitirlo. Probablemente no haya una gran cantidad de tipos de instrucciones que necesitaría analizar tampoco. Pero podrías terminar peleando un poco con el marco de prueba, o ir en contra de tus razones para usar Cucumber en primer lugar.
En cuanto a una convención, no conozco suficientes pruebas de API REST en la práctica para comentar, y ninguna de las que he visto probadas ha usado Cucumber como marco.
Actualización: Buscando en el tema, encontré un enlace a este: cucumber-api-steps que es más similar a su segundo formato.
Yo recomendaría tu primer escenario.
Desde mi propia experiencia, personalmente siento que el mayor valor que obtiene al utilizar BDD como método de entrega de software es cuando pone énfasis en el valor comercial.
En otras palabras, los escenarios deben ser ejemplos del comportamiento que desea el negocio, en lugar de la implementación técnica. Esto asegura que el desarrollo esté impulsado por los objetivos de la empresa y que los entregables coincidan con sus expectativas.
Esto se conoce como desarrollo externo.
Se pueden y se deben usar pruebas adicionales del comportamiento del sistema para cubrir los requisitos técnicos, pero creo que hay menos valor en gastar esfuerzos en redactarlas en lenguaje natural, que a menudo requiere mucho tiempo y es laborioso en una gran cantidad de escenarios.
Recomiendo el siguiente enfoque:
1) Trabaje con los OA y las OP para desarrollar ejemplos del comportamiento que desean utilizando un lenguaje específico que no sea de implementación (como su primer ejemplo).
2) Los ingenieros los utilizan para impulsar el desarrollo desde un enfoque de prueba primero, automatizándolos como pruebas de integración, con la mayoría debajo del navegador (por ejemplo, contra su API REST) y los escenarios más importantes también a través del navegador (si está desarrollando uno). ).
3) Ingenieros TDD: el código de característica con pruebas de unidad hasta que se superan las pruebas de unidad y los ejemplos de BDD.