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-