Download Behavior Driven Development – a hands on in Java
Document related concepts
no text concepts found
Transcript
Behavior Driven Development – a hands on in Java 1.1 Revisando la configuración del entorno de trabajo En esta sección ejecutaremos una serie de pasos para revisar y familiarizarnos con el ambiente de trabajo. Tareas Pasos Detallados Verificando la instalación de ConEmu 1) Abrir una Consola ConEmu Revisando la instalación de Java y Maven a) Doble click en el Ícono ConEmu 2) Ajustar el esquema de colores 1) Java: escribir el siguiente comando en la consola a) java -version 2) Maven: escribir el siguiente comando en la consola a) mvn -v Revisando el Editor de código 1) Abrir el editor: Brackets 2) Abrir el folder de nuestro ejemplo: a) Click en File b) Click en Open Folder c) Navegar hasta el folder creado para nuestro ejemplo Instalando la extensión para soporte Gherkin 1) Instalar la extensión para soporte de Sintaxis Gherkin a) Click en el Ícono de pieza de Lego (Extensión Manager) b) Escribir Gherkin en la caja de texto c) Enter d) Click en el botón ‘install’ del paquete brackets-cucumber e) Aceptar si el editor pide recargar para aplicar los cambios 1) Descargar el archivo bdd-a-hands-on-in-java.zip de la maquina servidor 2) Descomprimir el archivo en C:\code Autor: Raul Garvizu Descargando el proyecto -1- 1.2 Iteración 1: Primer Acceptance Test fallido En esta sección ejecutaremos una serie de pasos para Ejecutar nuestro primer Test de Aceptación e implementar la funcionalidad suficiente para satisfacer los requerimientos. Tareas Pasos Detallados Ejecutar el primer feature con cucumber 1) En la consola, navegar a first-iteration/starting/code-breakeracceptance Agregar la implementació n de los pasos 1) Abrir el código de la primera iteración: a) Ejecutar el comando mvn test a) En el editor de texto, seleccionar las siguientes opciones en el menú: i) File ii) Open folder b) Navegar hasta la carpeta donde esta descompreso el contenido de bddhands-on-java.zip, ej: c:/code/first-iteration c) Seleccionar el folder: starting d) El panel izquierdo del editor debería mostrar dos folders: i) code-breaker-acceptance ii) code-breaker-app 2) Crear el archivo StepDefinitions.java en el folder code-breakeracceptance/src/test/java/acceptance 3) Pegar el siguiente código package acceptance; import cucumber.api.java.en.Given; import cucumber.api.java.en.Then; import cucumber.api.java.en.When; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import java.util.Collection; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; private WebDriver browser; public StepDefinitions() { System.setProperty("webdriver.chrome.driver", "c:/app/chromedriver.exe"); browser = new ChromeDriver(); } @Given("^I am not yet playing$") -2- Autor: Raul Garvizu public class StepDefinitions { public void i_am_not_yet_playing() throws Throwable { assertNotNull(browser); } @When("^I start a game$") public void i_start_a_game() throws Throwable { browser.navigate().to("http://localhost:8080/"); } @Then("^I should see \"(.*?)\"$") public void i_should_see(String message) throws Throwable { String selector = String.format("//*[contains(., '%s')]", message); Collection<WebElement> foundElements = browser. findElements(By.xpath(selector)); assertNotEquals(0, foundElements.size()); } } 4) Ejecutar mvn test, en la consola de acceptance test 1) Abrir una nueva consola y navegar a la carpeta firstiteration/starting/code-breaker-app 2) Abrir el archivo code_breaker_app/src/test/java/com/jalasoft/techzone/CodeBreakerApplication Tests.java 3) Pegar el siguiente código, reemplazar todo el contenido package com.jalasoft.techzone; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.servlet.view.InternalResourceViewResolver; import static junit.framework.Assert.assertNotNull; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = CodeBreakerApplication.class) @WebAppConfiguration -3- Autor: Raul Garvizu Iniciar la implementació n de los unit tests public class CodeBreakerApplicationTests { private final MockMvc mockMvc; public CodeBreakerApplicationTests() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/jsp/view/"); viewResolver.setSuffix(".jsp"); mockMvc = standaloneSetup(new CodeBreakerController()) .setViewResolvers(viewResolver) .build(); } @Test public void contextLoads() { assertNotNull(mockMvc); } @Test public void startPageLoads() throws Exception { mockMvc.perform(get("/game")).andExpect(status().isOk()) .andExpect(view().name("game")); } } 4) Ejecutar mvn test, en la consola de la app 1) Crear el archivo: code_breaker_app/src/main/resources/templates/game.html 2) Pegar el siguiente contenido: <!DOCTYPE HTML> <html xmlns:th="http://thymeleaf.org"> <head> <title>Code Breaker</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <h2>Welcome to CodeBreaker!</h2> <p/> Enter guess: <input name='guess' type='text' placeholder='your guess here.'/> </body> </html> Nota: reemplazar todo el contenido -4- Autor: Raul Garvizu Implementar la pantalla inicial de la aplicación Ejecutar los Unit Tests y verificar que pasan 1) En la consola de la aplicación a) Ejecutar: mvn test b) Verificar que los tests pasan 2) Preparar el ejecutable de la aplicación a) Ejecutar: mvn package 3) Iniciar la aplicación a) Ejecutar: java –jar target\code-breaker-app-0.0.1-SNAPSHOT.jar Ejecutar los Acceptance Tests y verificar que pasan 1.3 1) En la consola de los Acceptance tests a) Ejecutar: mvn test b) Verificar que los tests pasan Iteración 2: Segundo Test de Aceptación En esta sección agregaremos nuestro segundo Test de Aceptación y la implementación necesaria para satisfacerlo. Tareas Pasos Detallados Agregar el Segundo Acceptance Test 1) Abrir el código de la segunda iteración: a) En el editor de texto, seleccionar las siguientes opciones en el menú: i) File ii) Open folder b) Navegar hasta la carpeta donde esta descompreso el contenido de bddhands-on-java.zip, ej: c:/code/second-iteration c) Seleccionar el folder: starting d) El panel izquierdo del editor debería mostrar dos folders: i) code-breaker-acceptance ii) code-breaker-app 2) Crear el archivo code_breaker_acceptance/src/test/resources/features/submit_gu ess.feature 3) Copiar el siguiente contenido. As a CodeBreaker player I should be able to submit a guess and get feedback So I can break the code Scenario: Submit a guess and get feedback Given I start a game When I enter 1234 as guess And I submit the guess Then I should get some feedback -5- Autor: Raul Garvizu Feature: CodeBreaker submits guess 1) Abrir una consola para ejecutar los tests de la segunda iteración: a) Abrir una nueva consola b) Navegar a la carpeta del projecto de acceptance tests de la segunda iteración: c:/code/bdd-a-hands-on-in-java/seconditeration/starting/code-breaker-acceptance/starting 2) Abrir una consola de la aplicación: a) Abrir una nueva consola b) Navegar hasta la carpeta: c:/code/bdd-a-hands-on-injava/second-iteration/starting/code-breaker-app/starting 3) En la consola de tests: a) Ejecutar: mvn test b) Verificar que todos los escenarios son ejecutados y los nuevos fallan c) Incluir la definición de los nuevos pasos i) Abrir el archivo: code-breakeracceptance/src/test/java/acceptance/StepDefinitions.java ii) Reemplazar el contenido con el siguiente listado: package acceptance; import com.google.inject.Inject; import cucumber.api.java.en.Given; import cucumber.api.java.en.Then; import cucumber.api.java.en.When; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import java.util.Collection; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.core.IsAnything.anything; import static org.junit.Assert.*; public class StepDefinitions { private String lastGuess = ""; @Inject private WebDriver browser; @Given("^I am not yet playing$") -6- Autor: Raul Garvizu Ejecutar el Segundo Acceptance test y verificar que falla public void i_am_not_yet_playing() throws Throwable { assertNotNull(browser); } @When("^I start a game$") public void i_start_a_game() throws Throwable { browser.navigate().to("http://localhost:8080/game"); assertNotEquals("", browser.getTitle()); } @Then("^I should see \"(.*?)\"$") public void i_should_see(String message) throws Throwable { String selector = String.format("//*[contains(., '%s')]", message); Collection<WebElement> foundElements = browser. findElements(By.xpath(selector)); assertNotEquals(0, foundElements.size()); } @When("^I enter (\\d+) as guess$") public void I_enter_as_guess(int guessValue) throws Throwable { WebElement guessTextField = browser.findElement(By.name("guess")); assertThat(guessTextField, notNullValue()); guessTextField.sendKeys(String.valueOf(guessValue)); } @When("^I submit the guess$") public void I_submit_the_guess() throws Throwable { WebElement guessTextField = browser.findElement(By.name("guess")); assertThat(guessTextField.getText(), anything()); this.lastGuess = guessTextField.getText(); } @Then("^I should get some feedback$") public void I_should_get_some_feedback() throws Throwable { // Express the Regexp above with the code you wish you had WebElement feedback = browser.findElement(By.className("feedbackMark")); assertThat(feedback.getText(), containsString(lastGuess)); -7- Autor: Raul Garvizu browser.findElement(By.name("submitGuess")).click(); } } iii) Ejecutar los acceptance tests y verificar que fallan 1) Actualizar el archivo CodeBreakerControllerTest.java, con el siguiente contenido: package com.jalasoft.techzone; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.servlet.view.InternalResourceViewResolver; import static junit.framework.Assert.assertNotNull; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get ; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.pos t; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSe tup; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = CodeBreakerApplication.class) @WebAppConfiguration public class CodeBreakerApplicationTests { private final MockMvc mockMvc; public CodeBreakerApplicationTests() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); -8- Autor: Raul Garvizu Implementar los unit tests para verificar el comportamiento del servidor viewResolver.setPrefix("/WEB-INF/jsp/view/"); viewResolver.setSuffix(".jsp"); mockMvc = standaloneSetup(new CodeBreakerController()) .setViewResolvers(viewResolver) .build(); } @Test public void contextLoads() { assertNotNull(mockMvc); } @Test public void startPageLoads() throws Exception { mockMvc.perform(get("/game")).andExpect(status().isOk()) .andExpect(view().name("game")); } @Test public void submitGuessAndGetFeedback() throws Exception { mockMvc.perform(post("/game").param("guess", "1234")) .andExpect(status().isOk()) .andExpect(model().attributeExists("attempt")); } } Nota: reemplazar todo el contenido. 1) Crear la carpeta model dentro de code-breakerapp/src/main/java/com/jalasoft/techzone 2) Crear el archivo: CodeBreakAttempt.java, dentro de la carpeta model 3) Copiar el siguiente contenido: -9- Autor: Raul Garvizu Agregar un clase de Modelo: CodeBreakAtte mpt package com.jalasoft.techzone.model; public class CodeBreakAttempt { private String mark; private String guess; public CodeBreakAttempt() { guess = ""; mark = ""; } public CodeBreakAttempt(String guess) { this.guess = guess; mark = "++--"; } public String getMark() { return mark; } public void setMark(String mark) { this.mark = mark; } public String getGuess() { return guess; } public void setGuess(String guess) { this.guess = guess; } } 1) Abrir el archivo: code-breakerapp/src/main/resources/templates/game.html 2) Introducir el siguiente contenido: Autor: Raul Garvizu Agregar el formulario en la vista y la lógica de manejo en el controlador -10- <!DOCTYPE HTML> <html xmlns:th="http://thymeleaf.org"> <head> <title>Code Breaker</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF8" /> </head> <body> <h2>Welcome to CodeBreaker!</h2> <p/> <form action="#" th:action="@{/game}" th:object="${attempt}" method="post"> Enter guess: <input th:field="*{guess}" type='text' placeholder='your guess here.'/> <input type="submit" name="submitGuess" value="Submit"/> </form> <div class="feedbackMark"> <p th:text="'Last attempt: ' + ${attempt.guess} + ', Mark: ' + ${attempt.mark}"></p> </div> </body> </html> 3) Abrir el archivo: code-breakerapp/src/main/java/com/jalasoft/techzone/CodeBreakerController .java 4) Reemplazar el contenido con: package com.jalasoft.techzone; import com.jalasoft.techzone.model.CodeBreakAttempt; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller @RequestMapping(value = "/game", produces = "text/html") public String getHomePage(Model model) { model.addAttribute("attempt", new CodeBreakAttempt()); return "game"; } @RequestMapping(value = "/game", method = RequestMethod.POST, produces = "text/html") public String submitGuess(@ModelAttribute CodeBreakAttempt -11- Autor: Raul Garvizu public class CodeBreakerController { breakAttempt, Model model) { model.addAttribute("attempt", new CodeBreakAttempt(breakAttempt.getGuess())); return "game"; } } Ejecutar los Unit Tests y verificar que pasan 1) En la consola de la aplicación, ejecutar el comando: mvn package Ejecutar los Acceptance Tests y verificar que pasan 1) En la consola de acceptance tests, ejecutar el comando: mvn test Si los tests pasan y el proceso termina satisfactoriamente, levantar la aplicación: java –jar target\code-breaker-app-0.0.1-SNAPSHOT.jar 2) Abrir un navegador e ir a la siguiente dirección: http://localhost:8080/game Referencias: Libros: The RSpec Book, David Chelimsky, Ed. The Pragmatic Bookshelf, 2010 The Cucumber for Java Book, by Seb Rose, Matt Wynne and Aslak Hellesøy, Ed. The Pragmatic Bookshelf, 2015 Páginas Web: http://www.disasterarea.co.uk/blog/mockmvc-to-test-spring-mvc-form-validation/ https://spring.io/guides/gs/handling-form-submission/ http://www.seleniumhq.org/docs/03_webdriver.jsp https://github.com/cucumber/cuke4duke/wiki/Guice http://zsoltfabok.com/blog/2012/01/cucumber-jvm-di/ Autor: Raul Garvizu -12-