PageSourceSearch

https://serenity-bdd.github.io/es/assets/js/2c65a7c4.7f9d8b51.js

js serenity-bdd.github.io collected 2026-10-03 09:58:12 UTC 26,977 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkserenity_users_guide=globalThis.webpackChunkserenity_users_guide||[]).push([[2268],{4184(e,n,a){a.d(n,{A:()=>s});const s=a.p+"assets/images/rest-report-http-requests-69463f8dc1251640a8c70994e2500b81.png"},7444(e,n,a){a.d(n,{A:()=>s});const s=a.p+"assets/images/rest-report-stories-67c1feb64856b4eb56f3490782e91a7e.jpg"},7589(e,n,a){a.r(n),a.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"tutorials/rest","title":"Tu Primera Prueba de API","description":"En el tutorial anterior vimos c\xf3mo escribir una prueba web simple con Serenity BDD. Pero Serenity no es solo para pruebas web: Serenity BDD tambi\xe9n proporciona una integraci\xf3n estrecha con Rest Assured, una popular biblioteca de c\xf3digo abierto para probar APIs REST.","source":"@site/i18n/es/docusaurus-plugin-content-docs/current/tutorials/rest.md","sourceDirName":"tutorials","slug":"/tutorials/rest","permalink":"/es/docs/tutorials/rest","draft":false,"unlisted":false,"editUrl":"https://github.com/serenity-bdd/serenity-bdd.github.io/blob/master/docs/tutorials/rest.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"id":"rest","sidebar_position":3},"sidebar":"tutorialSidebar","previous":{"title":"Tu Primer Escenario con Screenplay","permalink":"/es/docs/tutorials/screenplay"},"next":{"title":"Comenzando con Cucumber usando Serenity BDD y Screenplay","permalink":"/es/docs/tutorials/cucumber-screenplay"}}');var t=a(4848),r=a(8453);const i={id:"rest",sidebar_position:3},o="Tu Primera Prueba de API",c={},l=[{value:"Prerrequisitos",id:"prerrequisitos",level:2},{value:"Creando tu proyecto",id:"creando-tu-proyecto",level:2},{value:"Eliminando los archivos innecesarios",id:"eliminando-los-archivos-innecesarios",level:2},{value:"Agregando la Dependencia de Serenity RestAssured",id:"agregando-la-dependencia-de-serenity-restassured",level:2},{value:"Habilitando Reportes HTML Detallados",id:"habilitando-reportes-html-detallados",level:2},{value:"La estructura de directorios del proyecto",id:"la-estructura-de-directorios-del-proyecto",level:2},{value:"Escribiendo una prueba de API",id:"escribiendo-una-prueba-de-api",level:2},{value:"Estructura b\xe1sica de la prueba",id:"estructura-b\xe1sica-de-la-prueba",level:3},{value:"Creando Action Classes",id:"creando-action-classes",level:3},{value:"Completando nuestro caso de prueba",id:"completando-nuestro-caso-de-prueba",level:3},{value:"Reportes y Documentaci\xf3n Viva",id:"reportes-y-documentaci\xf3n-viva",level:2},{value:"Conclusi\xf3n",id:"conclusi\xf3n",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"tu-primera-prueba-de-api",children:"Tu Primera Prueba de API"})}),"\n",(0,t.jsxs)(n.p,{children:["En el tutorial anterior vimos c\xf3mo escribir una prueba web simple con Serenity BDD. Pero Serenity no es solo para pruebas web: Serenity BDD tambi\xe9n proporciona una integraci\xf3n estrecha con ",(0,t.jsx)(n.a,{href:"https://rest-assured.io/",children:"Rest Assured"}),", una popular biblioteca de c\xf3digo abierto para probar APIs REST."]}),"\n",(0,t.jsx)(n.h2,{id:"prerrequisitos",children:"Prerrequisitos"}),"\n",(0,t.jsx)(n.p,{children:"Para ejecutar este tutorial, necesitar\xe1s tener instalado en tu m\xe1quina:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Java"}),": Serenity BDD es una biblioteca de Java, as\xed que necesitar\xe1s un JDK reciente instalado. JDK 17 o superior deber\xeda funcionar bien."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Maven"}),": Necesitar\xe1s Maven 3 o superior instalado en tu computadora. Este act\xfaa como una herramienta de construcci\xf3n que tambi\xe9n descarga las dependencias durante la compilaci\xf3n."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Un IDE de Java"}),": Tambi\xe9n necesitar\xe1s un Entorno de Desarrollo de Java como IntelliJ o Eclipse (y conocimiento pr\xe1ctico de Java)."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Git"}),": Usaremos un proyecto inicial de GitHub, y el c\xf3digo de ejemplo para este proyecto tambi\xe9n est\xe1 en GitHub, as\xed que asumir\xe9 que tienes un conocimiento b\xe1sico de Git."]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"creando-tu-proyecto",children:"Creando tu proyecto"}),"\n",(0,t.jsxs)(n.p,{children:["Usaremos la plantilla de proyecto ",(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.a,{href:"https://github.com/serenity-bdd/serenity-junit-starter",children:"Serenity BDD Junit Starter"})})," para tener un proyecto simple funcionando r\xe1pidamente."]}),"\n",(0,t.jsx)(n.p,{children:"Este proyecto viene con una prueba de ejemplo basada en Junit 5 ya implementada para nuestra referencia. Por ah
1ora, vamos a ignorarla y comenzar a escribir una nueva prueba desde cero."}),"\n",(0,t.jsxs)(n.p,{children:["Ve a la ",(0,t.jsx)(n.a,{href:"https://github.com/serenity-bdd/serenity-junit-starter",children:"p\xe1gina de la plantilla del proyecto en GitHub"})," y haz clic en ",(0,t.jsx)(n.a,{href:"https://github.com/serenity-bdd/serenity-junit-starter/generate",children:"Use This Template"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"eliminando-los-archivos-innecesarios",children:"Eliminando los archivos innecesarios"}),"\n",(0,t.jsxs)(n.p,{children:["Solo para asegurarnos de que los archivos de ejemplo de la plantilla inicial no interfieran con nuestra experiencia en este tutorial, ",(0,t.jsx)(n.strong,{children:"elimina"})," el directorio ",(0,t.jsx)(n.code,{children:"src/test/java/starter/wikipedia"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"agregando-la-dependencia-de-serenity-restassured",children:"Agregando la Dependencia de Serenity RestAssured"}),"\n",(0,t.jsxs)(n.p,{children:["Abre el archivo ",(0,t.jsx)(n.code,{children:"pom.xml"})," en el directorio ra\xedz y agrega las siguientes l\xedneas en la secci\xf3n ",(0,t.jsx)(n.code,{children:"<dependencies>"}),", similar a las que ya est\xe1n en el archivo."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-xml",children:" <dependency>\n      <groupId>net.serenity-bdd</groupId>\n      <artifactId>serenity-rest-assured</artifactId>\n      <version>${serenity.version}</version>\n      <scope>test</scope>\n  </dependency>\n"})}),"\n",(0,t.jsx)(n.h2,{id:"habilitando-reportes-html-detallados",children:"Habilitando Reportes HTML Detallados"}),"\n",(0,t.jsxs)(n.p,{children:["Cuando usamos la configuraci\xf3n predeterminada de la plantilla, obtenemos solo un reporte HTML de una sola p\xe1gina. Queremos generar un reporte HTML detallado en este tutorial. As\xed que, ",(0,t.jsx)(n.strong,{children:"elimina"})," la siguiente l\xednea del archivo ",(0,t.jsx)(n.code,{children:"pom.xml"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-xml",children:"  <reports>single-page-html</reports>\n  \x3c!-- ELIMINA la l\xednea de arriba. \xa1S\xed, elim\xednala! --\x3e\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Puedes encontrar esto en la secci\xf3n de configuraci\xf3n del plugin ",(0,t.jsx)(n.code,{children:"serenity-maven-plugin"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"la-estructura-de-directorios-del-proyecto",children:"La estructura de directorios del proyecto"}),"\n",(0,t.jsx)(n.p,{children:"Usaremos algunas convenciones simples para organizar nuestros archivos Feature y las clases Java de soporte, basadas en la estructura est\xe1ndar de proyectos Maven descrita a continuaci\xf3n:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"\u251c\u2500\u2500\u2500src\n\u2502   \u251c\u2500\u2500\u2500main\n\u2502   \u2502   \u2514\u2500\u2500\u2500java\n\u2502   \u2502       \u2514\u2500\u2500\u2500starter\n\u2502   \u2514\u2500\u2500\u2500test\n\u2502       \u251c\u2500\u2500\u2500java\n\u2502       \u2502   \u2514\u2500\u2500\u2500starter\n\u2502       \u2502       \u2514\u2500\u2500\u2500petstore\n\u2502       \u2514\u2500\u2500\u2500resources\n"})}),"\n",(0,t.jsx)(n.p,{children:"Aqu\xed hay algunos puntos a tener en cuenta sobre la estructura de directorios:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["Como probaremos la ",(0,t.jsx)(n.a,{href:"https://petstore.swagger.io/",children:"API de Pet Store"})," disponible p\xfablicamente, no tendremos c\xf3digo en el directorio ",(0,t.jsx)(n.code,{children:"src/main"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:["Reutilizaremos (de la plantilla) los contenidos que ya est\xe1n en el directorio ",(0,t.jsx)(n.code,{children:"src/test/resources/"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:["Crearemos un nuevo directorio ",(0,t.jsx)(n.code,{children:"petstore"})," bajo el directorio ",(0,t.jsx)(n.code,{children:"src/test/java/starter"})," para almacenar nuestra clase de prueba y sus auxiliares."]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"escribiendo-una-prueba-de-api",children:"Escribiendo una prueba de API"}),"\n",(0,t.jsxs)(n.p,{children:["Comencemos escribiendo nuestra prueba de API. En esta prueba, probaremos la API ",(0,t.jsx)(n.a,{href:"https://petstore.swagger.io/#/pet/getPetById",children:(0,t.jsx)(n.code,{children:"GET /pet/{petId}"})}),". Esta API retornar\xe1 una mascota cuando le des su ",(0,t.jsx)(n.code,{children:"id"})," en la URL."]}),"\n",(0,t.jsxs)(n.p,{children:["Sin embargo, no podemos llamar a esta API directamente sin ning\xfan ",(0,t.jsx)(n.code,{children:"id"}),". Por lo tanto, nuestra prueba necesita primero crear una mascota y obtener su ",(0,t.jsx)(n.code,{children:"id"})," antes de llamar al endpoint de API ",(0,t.jsx)(n.code,{children:"GET /pet/{petId}"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["En otras palabras, podr\xedamos escribir nuestra prueba en el formato ",(0,t.jsx)(n.code,{children:"Given-When-Then"})," (Dado-Cuando-Entonces) de la siguiente manera:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-Gherkin",children:"Given Kitty is available in the pet store\nWhen I ask for a pet using Kitty's ID\nThen I get Kitty as result\n"})}),"\n",(0,t.jsx)(n.h3,{id:"estructura-b\xe1sica-de-la-prueba",children:"Estructura b\xe1sica de la prueba"}),"\n",(0,t.jsxs)(n.p,{children:["Ahora creamos una nueva clase de prueba (llam\xe9mosla ",(0,t.jsx)(n.code,{children:"WhenFetchingAlreadyAvailablePet"}),"), y un caso de prueba vac\xedo (podemos llamarlo ",(0,t.jsx)(n.code,{children:"fetchAlreadyAvailablePet"}),")."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"package starter.petstore;\n\nimport net.serenitybdd.junit5.SerenityJUnit5Extension;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\n\n\n@ExtendWith(SerenityJUnit5Extension.class)\npublic class WhenFetchingAlreadyAvailablePet {\n\n  @Test\n  public void fetchAlreadyAvailablePet() {\n\n  }\n}\n"})}),"\n",(0,t.jsxs)(n.admonition,{type:"caution",children:[(0,t.jsx)(n.p,{children:"Hay algunas cosas a tener en cuenta aqu\xed:"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["La anotaci\xf3n ",(0,t.jsx)(n.code,{children:"@ExtendWith"})," le dice a JUnit que esta prueba usa Serenity - no olvides esta anotaci\xf3n o tu prueba no ser\xe1 reconocida como una prueba de Serenity"]}),"\n",(0,t.jsxs)(n.li,{children:["La anotaci\xf3n ",(0,t.jsx)(n.code,{children:"@Test"})," usa la clase ",(0,t.jsx)(n.code,{children:"org.junit.jupiter.api.Test"}),", de JUnit 5. Ten cuidado de no confundirla con la anotaci\xf3n de JUnit 4 del mismo nombre (",(0,t.jsx)(n.code,{children:"org.junit.Test"}),"), de lo contrario tu prueba no se ejecutar\xe1."]}),"\n",(0,t.jsxs)(n.li,{children:["Nota que el nombre de la clase de prueba comienza con ",(0,t.jsx)(n.code,{children:"When"}),". Esta es una de las formas de asegurar que sea reconocida como una prueba a ejecutar en el proceso de compilaci\xf3n de Maven. Consulta la secci\xf3n ",(0,t.jsx)(n.code,{children:"configuration"})," del ",(0,t.jsx)(n.code,{children:"maven-failsafe-plugin"})," en el archivo ",(0,t.jsx)(n.code,{children:"pom.xml"})," para m\xe1s detalles."]}),"\n"]})]}),"\n",(0,t.jsx)(n.h3,{id:"creando-action-classes",children:"Creando Action Classes"}),"\n",(0,t.jsxs)(n.p,{children:["Podr\xedamos simplemente comenzar a escribir todo el c\xf3digo de la prueba dentro de nuestro m\xe9todo ",(0,t.jsx)(n.code,{children:"fetchAlreadyAvailablePet()"}),". Eso funcionar\xeda bien. Pero mantener el c\xf3digo de prueba bien organizado y bien estructurado es esencial para mantener bajos los costos de mantenimiento. Y Serenity BDD nos da varias formas de hacer esto."]}),"\n",(0,t.jsxs)(n.p,{children:["Una de las formas m\xe1s simples de hacerlo se llama ",(0,t.jsx)(n.em,{children:"Action Classes"}),". Las Action Classes son clases peque\xf1as y reutilizables con m\xe9todos que encapsulan acciones clave del usuario. Usaremos estas clases para llamar a las APIs HTTP."]}),"\n",(0,t.jsxs)(n.p,{children:["Por ejemplo, podr\xedamos dividir nuestra prueba ",(0,t.jsx)(n.code,{children:"fetchAlreadyAvailablePet()"})," en tres pasos:"]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Preparar (Given):"})," Preparar el escenario para llamar a la API GET pre-cargando la mascota llamada 'Kitty' usando una llamada HTTP POST documentada ",(0,t.jsx)(n.a,{href:"https://petstore.swagger.io/#/pet/addPet",children:"aqu\xed"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Actuar (When):"})," Llamar a la API bajo prueba usando el ID de 'Kitty'"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Verificar (Then):"})," Comprobar que la API retorna una mascota con nombre 'Kitty'"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Creemos una Action Class llamada ",(0,t.jsx)(n.code,{children:"PetApiActions"})," con el siguiente c\xf3digo esqueleto, en el mismo paquete ",(0,t.jsx)(n.code,{children:"petstore"})," donde vive la prueba."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'package starter.petstore;\n\nimport io.cucumber.java.en.Given;
1\nimport io.cucumber.java.en.Then;\nimport io.cucumber.java.en.When;\nimport net.serenitybdd.core.steps.UIInteractions;\n\n\npublic class PetApiActions extends UIInteractions {\n\n    @Given("Kitty is available in the pet store")\n    public Long givenKittyIsAvailableInPetStore() {\n\n    }\n\n    @When("I ask for a pet using Kitty\'s ID: {0}")\n    public void whenIAskForAPetWithId(Long id) {\n\n    }\n\n    @Then("I get Kitty as result")\n    public void thenISeeKittyAsResult() {\n\n    }\n}\n\n'})}),"\n",(0,t.jsxs)(n.admonition,{type:"caution",children:[(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Puntos a tener en cuenta"})}),(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Como queremos usar el ID generado por la API en nuestro siguiente paso, retornamos el ID como un valor de retorno Long."}),"\n",(0,t.jsxs)(n.li,{children:["Extendemos la clase ",(0,t.jsx)(n.code,{children:"UIInteractions"})," que viene con Serenity BDD para ayudarnos a interactuar con APIs."]}),"\n"]})]}),"\n",(0,t.jsxs)(n.p,{children:["Comencemos implementando la primera acci\xf3n: Preparar el escenario pre-creando una mascota con nombre ",(0,t.jsx)(n.code,{children:'"Kitty"'})," llamando a la API POST."]}),"\n",(0,t.jsxs)(n.p,{children:["Como necesitamos crear un objeto Java para almacenar la ",(0,t.jsx)(n.code,{children:"Pet"}),", podemos crear una clase ",(0,t.jsx)(n.code,{children:"Pet.java"})," bajo el paquete ",(0,t.jsx)(n.code,{children:"starter.petstore"})," con el siguiente c\xf3digo:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"package starter.petstore;\n\npublic class Pet {\n    private String name;\n    private String status;\n    private Long id;\n\n    public Pet(String name, String status, Long id) {\n        this.name = name;\n        this.status = status;\n        this.id = id;\n    }\n\n    public Pet(String name, String status) {\n        this.name = name;\n        this.status = status;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String getStatus() {\n        return this.status;\n    }\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public void setStatus(String status) {\n        this.status = status;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Ahora que tenemos una forma de representar una mascota en nuestro c\xf3digo, escribamos nuestra primera acci\xf3n en la funci\xf3n ",(0,t.jsx)(n.code,{children:"givenKittyIsAvailableInPetStore()"})," de la clase ",(0,t.jsx)(n.code,{children:"PetApiActions"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'package starter.petstore;\n\nimport io.cucumber.java.en.Given;\nimport io.cucumber.java.en.Then;\nimport io.cucumber.java.en.When;\nimport io.restassured.http.ContentType;\nimport io.restassured.mapper.ObjectMapperType;\nimport static net.serenitybdd.rest.SerenityRest.given;\nimport net.serenitybdd.core.steps.UIInteractions;\n\n\nimport static net.serenitybdd.rest.SerenityRest.*;\n\npublic class PetApiActions extends UIInteractions {\n\n    @Given("Kitty is available in the pet store")\n    public Long givenKittyIsAvailableInPetStore() {\n\n        Pet pet = new Pet("Kitty", "available");\n\n        Long newId = given()\n                .baseUri("https://petstore.swagger.io")\n                .basePath("/v2/pet")\n                .body(pet, ObjectMapperType.GSON)\n                .accept(ContentType.JSON)\n                .contentType(ContentType.JSON).post().getBody().as(Pet.class, ObjectMapperType.GSON).getId();\n        return newId;\n    }\n\n    @When("I ask for a pet using Kitty\'s ID: {0}")\n    public void whenIAskForAPetWithId(Long id) {\n\n    }\n\n    @Then("I get Kitty as result")\n    public void thenISeeKittyAsResult() {\n\n    }\n}\n\n'})}),"\n",(0,t.jsxs)(n.p,{children:["A continuaci\xf3n, escribamos la implementaci\xf3n para la funci\xf3n ",(0,t.jsx)(n.code,{children:"whenIAskForAPetWithId"}),". Esto incluir\xe1 simplemente llamar a la API GET que necesita ser probada."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'    @When("I ask for a pet using Kitty\'s ID: {0}")\n    public void whenIAskForAPetWithId(Long id) {\n        when().get("/" + id);\n    }\n'})}),"\n",(0,t.jsxs)(n.admonition,{type:"caution",children:[(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Puntos a tener en cuenta"})}),(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["En la llamada al m\xe9todo ",(0,t.jsx)(n.code,{children:"get"})," anterior, se reutilizan el ",(0,t.jsx)(n.code,{children:"baseUri"})," y ",(0,t.jsx)(n.code,{children:"basePath"})," de la secci\xf3n ",(0,t.jsx)(n.code,{children:"given()"}),". Por eso no tuviste que repetir esos detalles en este m\xe9todo."]}),"\n",(0,t.jsxs)(n.li,{children:["Como estamos usando el ",(0,t.jsx)(n.code,{children:"id"})," como par\xe1metro de entrada, usamos ",(0,t.jsx)(n.code,{children:"{0}"})," en la descripci\xf3n para que pueda aparecer en nuestros reportes."]}),"\n"]})]}),"\n",(0,t.jsxs)(n.p,{children:["A continuaci\xf3n, escribamos la implementaci\xf3n para el m\xe9todo ",(0,t.jsx)(n.code,{children:"thenISeeKittyAsResult"})," de la siguiente manera:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'    @Then("I get Kitty as result")\n    public void thenISeeKittyAsResult() {\n        then().body("name", Matchers.equalTo("Kitty"));\n    }\n\n'})}),"\n",(0,t.jsxs)(n.p,{children:["Juntando todo, el archivo ",(0,t.jsx)(n.code,{children:"PetApiActions.java"})," se ve as\xed:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'package starter.petstore;\n\nimport io.cucumber.java.en.Given;
1\nimport io.cucumber.java.en.Then;\nimport io.cucumber.java.en.When;\nimport io.restassured.http.ContentType;\nimport io.restassured.mapper.ObjectMapperType;\nimport static net.serenitybdd.rest.SerenityRest.then;\nimport static net.serenitybdd.rest.SerenityRest.when;\nimport static net.serenitybdd.rest.SerenityRest.given;\nimport net.serenitybdd.core.steps.UIInteractions;\nimport org.hamcrest.Matchers;\n\nimport static net.serenitybdd.rest.SerenityRest.*;\n\npublic class PetApiActions extends UIInteractions {\n\n    @Given("Kitty is available in the pet store")\n    public Long givenKittyIsAvailableInPetStore() {\n\n        Pet pet = new Pet("Kitty", "available");\n\n        Long newId = given()\n                .baseUri("https://petstore.swagger.io")\n                .basePath("/v2/pet")\n                .body(pet, ObjectMapperType.GSON)\n                .accept(ContentType.JSON)\n                .contentType(ContentType.JSON).post().getBody().as(Pet.class, ObjectMapperType.GSON).getId();\n        return newId;\n    }\n\n    @When("I ask for a pet using Kitty\'s ID: {0}")\n    public void whenIAskForAPetWithId(Long id) {\n        when().get("/" + id);\n    }\n\n    @Then("I get Kitty as result")\n    public void thenISeeKittyAsResult() {\n        then().body("name", Matchers.equalTo("Kitty"));\n    }\n\n}\n\n\n'})}),"\n",(0,t.jsx)(n.h3,{id:"completando-nuestro-caso-de-prueba",children:"Completando nuestro caso de prueba"}),"\n",(0,t.jsxs)(n.p,{children:["Ahora que nuestra clase Actions est\xe1 lista, terminemos de escribir nuestro caso de prueba en la clase ",(0,t.jsx)(n.code,{children:"WhenFetchingAlreadyAvailablePet"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"package starter.petstore;\n\nimport net.serenitybdd.junit5.SerenityJUnit5Extension;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\n\n@ExtendWith(SerenityJUnit5Extension.class)\npublic class WhenFetchingAlreadyAvailablePet {\n\n    Long newPetId = null;\n    PetApiActions petApi;\n\n    @Test\n    public void fetchAlreadyAvailablePet() {\n        newPetId = petApi.givenKittyIsAvailableInPetStore();\n        petApi.whenIAskForAPetWithId(newPetId);\n        petApi.thenISeeKittyAsResult();\n    }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Intentemos ejecutar la compilaci\xf3n de Maven para ver el resultado. Si la API funciona como se espera, esperamos que la prueba pase y se genere un reporte HTML detallado."}),"\n",(0,t.jsx)(n.p,{children:"Ejecuta el siguiente comando en una terminal o l\xednea de comandos:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"mvn clean verify\n"})}),"\n",(0,t.jsx)(n.p,{children:"Una vez que el comando termine, ver\xe1s una salida similar a la siguiente:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.009 s - in starter.petstore.WhenFetchingAlreadyAvailablePet\n[INFO]\n[INFO] Results:\n[INFO]\n[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0\n\n...\n...\n...\n\n[INFO] -----------------------------------------\n[INFO]  SERENITY TESTS: SUCCESS\n[INFO] -----------------------------------------\n[INFO] | Test cases executed    | 1\n[INFO] | Tests executed         | 1\n[INFO] | Tests passed           | 1\n[INFO] | Tests failed           | 0\n[INFO] | Tests with errors      | 0\n[INFO] | Tests compromised      | 0\n[INFO] | Tests aborted          | 0\n[INFO] | Tests pending          | 0\n[INFO] | Tests ignored/skipped  | 0\n[INFO] ------------------------ | --------------\n[INFO] | Total Duration         | 9s 212ms\n[INFO] | Fastest test took      | 9s 212ms\n[INFO] | Slowest test took      | 9s 212ms\n[INFO] -----------------------------------------\n[INFO]\n[INFO] SERENITY REPORTS\n[INFO]   - Full Report: file:///C:/Users/calib/source-codes/temp/serenity-junit-starter/target/site/serenity/index.html\n[INFO]\n[INFO] --- maven-failsafe-plugin:3.0.0-M5:verify (default) @ serenity-junit-starter ---\n[INFO] ------------------------------------------------------------------------\n[INFO] BUILD SUCCESS\n[INFO] ------------------------------------------------------------------------\n[INFO] Total time:  39.104 s\n[INFO] Finished at: 2022-09-02T17:33:14+05:30\n[INFO] ------------------------------------------------------------------------\n\n"})}),"\n",(0,t.jsx)(n.p,{children:"\xa1S\xed, la prueba pas\xf3 y la compilaci\xf3n fue exitosa! Hemos logrado probar nuestra API exitosamente \ud83c\udf89"}),"\n",(0,t.jsx)(n.h2,{id:"reportes-y-documentaci\xf3n-viva",children:"Reportes y Documentaci\xf3n Viva"}
1),"\n",(0,t.jsxs)(n.p,{children:["Si observas cuidadosamente, la salida del comando ",(0,t.jsx)(n.code,{children:"mvn clean verify"})," nos inform\xf3 que se cre\xf3 un reporte en ",(0,t.jsx)(n.code,{children:"target/site/serenity/index.html"})]}),"\n",(0,t.jsx)(n.p,{children:"Cuando abres este archivo en un navegador web, ves un hermoso reporte como este:"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"P\xe1gina Principal del Reporte",src:a(8222).A+"",width:"1231",height:"939"})}),"\n",(0,t.jsxs)(n.p,{children:["Tambi\xe9n puedes encontrar los resultados por prueba detallando los pasos en la pesta\xf1a ",(0,t.jsx)(n.code,{children:"Stories"}),", detallando las llamadas a la API REST."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"Reporte",src:a(7444).A+"",width:"1258",height:"850"})}),"\n",(0,t.jsx)(n.p,{children:"Si quieres ver los detalles exactos usados en las solicitudes HTTP, puedes hacer clic en el enlace marcado en la captura de pantalla anterior. Esto te mostrar\xe1 los detalles como se muestra a continuaci\xf3n:"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"Reporte con solicitudes HTTP",src:a(4184).A+"",width:"1213",height:"957"})}),"\n",(0,t.jsx)(n.p,{children:"Si\xe9ntete libre de navegar los enlaces en este reporte y explorar."}),"\n",(0,t.jsx)(n.h2,{id:"conclusi\xf3n",children:"Conclusi\xf3n"}),"\n",(0,t.jsx)(n.p,{children:"En este tutorial, creaste tus propios casos de prueba de API y los ejecutaste usando Serenity BDD para generar un hermoso reporte."})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8222(e,n,a){a.d(n,{A:()=>s});const s=a.p+"assets/images/rest-report-home-a2aa1a51d9d3c6af7f8263bf8021803a.png"},8453(e,n,a){a.d(n,{R:()=>i,x:()=>o});var s=a(6540);const t={},r=s.createContext(t);function i(e){const n=s.useContext(r);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.