Cucumber – Ejemplo práctico

Cucumber es una herramienta que soporta BDD y que nos ha permitido crear pruebas de fácil entendimiento para personas no técnicas, debido al uso del lenguaje Gherkin.

Esto permitió que el equipo del producto pueda validar rápidamente el output esperado de los escenarios dados y hasta atreverse a crear sus propias pruebas debido a la facilidad del lenguaje.

Recientemente hemos utilizado esta herramienta y nos ha ayudado mucho en la verificación de las funcionalidades de nuestro proyecto que eran complejas bajo ciertos escenarios.

En este artículo creamos un ejemplo práctico para gestionar inventarios donde podemos reubicar sus elementos entre diferentes ubicaciones destino.

Dependencias Maven

Agregamos las siguientes dependencias en nuestro archivo pom.xml

<dependency>
	<groupId>io.cucumber</groupId>
	<artifactId>cucumber-java</artifactId>
	<version>7.9.0</version>
</dependency>

<dependency>
	<groupId>io.cucumber</groupId>
	<artifactId>cucumber-junit</artifactId>
	<version>7.9.0</version>
</dependency>

La Clase

Para la gestión del inventario creamos la clase Inventory.java, InventoryLine.java e Item.java

La clase inventory contiene los inventory lines y el método relocate que se encarga de reubicar los items existentes a una nueva ubicación.

public class Inventory {
	private Set<InventoryLine> inventoryLines;

    public boolean relocate(String itemCode, Integer qty, String 
                            sourceLocation, String targetLocation) {

		var item = new Item(itemCode);

		InventoryLine line = inventoryLines
            .stream()
            .filter(l -> l.getItem().equals(item)
				&& StringUtils.equals(l.getLocation(), sourceLocation) 
                && l.getQuantity().compareTo(qty) >= 0)
			.findFirst().orElse(null);

		if (line == null) {
			return false;
		}

		if (line.getQuantity().compareTo(qty) == 0) {
			line.setLocation(targetLocation);

		} else {
			line.reduceQuantity(qty);

			var newLine = new InventoryLine();
			newLine.setItem(item);
			newLine.setLocation(targetLocation);
			newLine.setQuantity(qty);
			inventoryLines.add(newLine);
		}

		return true;
	}
}

La clase InventoryLine e Item son simples beans que representan a los objetos de la vida real.

public class Item {
    private String itemCode;
}
public class InventoryLine {
	private Item item;
	private Integer quantity;
	private String location;
}

El Escenario

Los escenarios son creados en archivos con extensión .feature y en lenguaje Gherkin como había sido mencionado anteriormente.

El siguiente escenario nos ayuda a validar los resultados esperados del inventario después de una reubicación de los items.

Se observan 3 pasos muy importantes,

Given.- describe el contexto inicial de la aplicación, en este caso el inventario inicial.

When.- describe el evento de reubicación del item del location 1 al location 5.

Then.- describe el resultado esperado.

Feature: Testing the relocation logic
  Users should be able to relocate the items of an inventory

  Scenario: Move items to other location
  	Given an inventory with the following items
  	| item code | qty | location |
  	| item-1 	| 10  | loc1  |
  	| item-2 	| 20  | loc2  |
  	| item-3 	| 30  | loc3  |
  	| item-4 	| 40  | loc4  |
    When users relocate the following inventory to the location "loc5"
    | item code | qty | location |
  	| item-1 	| 10  | loc1     |
    Then the expected inventory is the following
    | item code | qty | location |
  	| item-1 	| 10  | loc5     |
  	| item-2 	| 20  | loc2     |
  	| item-3 	| 30  | loc3     |
  	| item-4 	| 40  | loc4     |

Cuando ejecutemos el escenario, cucumber buscara la implementación del step en nuestras clases para saber que lógica se va a ejecutar, por ende necesitamos definir la lógica de cada paso usando diferentes métodos que harán match con el paso haciendo uso de las anotaciones.

Para este ejemplo usamos una clase donde se encuentran nuestras definiciones.

La clase stepDefinition que contiene la definición de todos los pasos.

public class StepDefinition {

	private Inventory inventory = new Inventory();

	@Given("an inventory with the following items")
	public void anInventoryWithTheFollowingItems(List<InventoryLine> inventoryLines) {
		inventory.setInventoryLines(new HashSet<>(inventoryLines));
	}

	@When("users relocate the following inventory to the location {string}")
	public void relocate(String targetLocation, List<InventoryLine> inventoryLines) {
		var inventoryLine = inventoryLines.get(0);
		inventory.relocate(inventoryLine.getItem().getItemCode(), inventoryLine.getQuantity(),
				inventoryLine.getLocation(), targetLocation);
	}
	
	@Then("the expected inventory is the following")
	public void ss(List<InventoryLine> expectedInventoryLines) {
		
		assertNotNull(inventory.getInventoryLines());
		assertEquals(expectedInventoryLines.size(),inventory.getInventoryLines().size());
		for(var line : inventory.getInventoryLines()) {
			
			var expectedLine = expectedInventoryLines.stream().filter(l-> StringUtils.equals(l.getLocation(), line.getLocation())).findFirst().orElse(null);
			assertNotNull(expectedLine);
			
			assertEquals(expectedLine.getItem(), line.getItem());
			assertEquals(expectedLine.getQuantity(), line.getQuantity());
		}
		
	}
	
	@DataTableType
	public InventoryLine mapInventoryLine(Map<String, String> data) {
		var line = new InventoryLine();
		line.setItem(new Item(data.get("item code")));
		line.setQuantity(Integer.valueOf(data.get("qty")));
		line.setLocation(data.get("location"));
		return line;
	}

}

Ejecutamos los escenarios y obtenemos la siguiente salida en la consola, que como se observa las pruebas fueron ejecutadas satisfactoriamente.

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.indevsolutions.example.cucumber.CucumberIntegrationTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.807 s - in com.indevsolutions.example.cucumber.CucumberIntegrationTest
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

Como se observa, el uso de cucumber puede ser de mucha ayuda y al ser entendible por personas no técnicas podemos involucrar al equipo del producto para realizar las validaciones y hasta crear más escenarios.

Como siempre puedes encontrar el código del ejemplo aquí.

Con esto nos despedimos y esperamos que hayamos podido contribuir en algo compartiendo nuestro conocimiento.

Leave a comment

Tu dirección de correo electrónico no será publicada.

slot gacorslot gacorMurah4dtotoslot88Horas88Slot PulsaSlot DanaSpboNowSkorWomen In The WorldSlot88rubiesandradishesorganicnewsroomvirante seocloud spectatorVainglory Forumamerican gathering of jewish holocaust survivorsRumah Pejuang Kanker Ambuoutside foundWetpaintcwhonorsSlot GacorJudi BolaDemo SlotDemo SlotSlot GacorSlot GacorJudi BolaJudi Bolaomo77omo77omo777omo777UnogoalSPBOATLASBET88CUANWIN138MACANASIA88https://direct.lc.chat/14614518/https://secure.livechatinc.com/licence/14614518/v2/open_chat.cgihttps://direct.lc.chat/15014550/https://secure.livechatinc.com/licence/15014550/v2/open_chat.cgihttps://direct.lc.chat/15314022/https://secure.livechatinc.com/licence/15314022/v2/open_chat.cgihttps://ibrapchs.net/https://atox.in/
https://slot77.amikmahaputra.ac.id/products/slot77/https://gacor4d.amikmahaputra.ac.id/products/gacor4d/https://infini88.amikmahaputra.ac.id/products/infini88/https://sv388.amikmahaputra.ac.id/products/sv388/https://pay4d.amikmahaputra.ac.id/products/pay4d/https://parlay-bola.amikmahaputra.ac.id/products/mix-parlay/https://idn-slot.amikmahaputra.ac.id/products/idn-slot/https://mpo-slot.amikmahaputra.ac.id/products/mpo-slot/https://nexus-slot.amikmahaputra.ac.id/products/nexus-slot/https://mahjong-ways.amikmahaputra.ac.id/products/slot-mahjong/https://akun-pro-jepang.amikmahaputra.ac.id/products/slot-jepang/https://akun-pro-kamboja.amikmahaputra.ac.id/products/slot-kamboja/https://akun-pro-malaysia.amikmahaputra.ac.id/products/slot-malaysia/https://akun-pro-myanmar.amikmahaputra.ac.id/products/slot-myanmar/https://akun-pro-rusia.amikmahaputra.ac.id/products/slot-rusia/https://akun-pro-singapore.amikmahaputra.ac.id/products/slot-singapore/https://akun-pro-taiwan.amikmahaputra.ac.id/products/slot-taiwan/https://akun-pro-thailand.amikmahaputra.ac.id/products/slot-thailand/https://akun-pro-thailand.amikmahaputra.ac.id/products/slot-thailand/https://akun-pro-vietnam.amikmahaputra.ac.id/products/slot-vietnam/
https://slot-bonus.amikmahaputra.ac.id/products/slot-bonus/https://slot-demo.amikmahaputra.ac.id/products/slot-demo/https://slot-dana.amikmahaputra.ac.id/products/slot-dana/https://slot-depo-10k.amikmahaputra.ac.id/products/slot-10k/https://slot-depo-25k.amikmahaputra.ac.id/products/slot-25k/https://slot-garansi-kekalahan.amikmahaputra.ac.id/products/slot-garansi-kekalahan/https://slot-habanero.amikmahaputra.ac.id/products/slot-habanero/https://slot-hoki.amikmahaputra.ac.id/products/slot-hoki/https://slot-jp.amikmahaputra.ac.id/products/slot-jp/https://slot-maxwin.amikmahaputra.ac.id/products/slot-maxwin/https://bocoran-admin-slot.amikmahaputra.ac.id/products/bocoran-admin-slot/https://casino-online.amikmahaputra.ac.id/products/casino-online/https://bet88.amikmahaputra.ac.id/products/bet88/https://bandarqq.amikmahaputra.ac.id/products/bandarqq/https://baccarat-online.amikmahaputra.ac.id/products/baccarat-online/https://asia88.amikmahaputra.ac.id/products/asia88/https://asia4d.amikmahaputra.ac.id/products/asia4d/https://anti-rungkad.amikmahaputra.ac.id/products/anti-rungkad/https://akun-vip.amikmahaputra.ac.id/products/akun-vip/https://akun-gacor.amikmahaputra.ac.id/products/akun-gacor/
https://slot-receh.journal.poltekanika.ac.id/products/slot-receh/https://slot-pulsa.journal.poltekanika.ac.id/products/slot-depo-pulsa/https://slot-maxwin.journal.poltekanika.ac.id/products/slot-maxwin/https://slot-hoki.journal.poltekanika.ac.id/products/slot-hoki/https://slot-garansi-kekalahan.journal.poltekanika.ac.id/products/slot-garansi-kekalahan/https://slot-depo-25k.journal.poltekanika.ac.id/products/slot-25k/https://slot-depo-10k.journal.poltekanika.ac.id/products/slot-10k/https://slot-demo.journal.poltekanika.ac.id/products/slot-demo/https://slot-dana.journal.poltekanika.ac.id/products/slot-depo-dana/https://slot-bonus.journal.poltekanika.ac.id/products/bonus-new-member/
https://www.angkolabarat.tapselkab.go.id/products/slot-zeus/https://www.angkolabarat.tapselkab.go.id/products/slot-10k/https://www.angkolabarat.tapselkab.go.id/products/slot-25k/https://www.angkolabarat.tapselkab.go.id/products/slot-garansi-kekalahan/https://www.angkolabarat.tapselkab.go.id/products/slot-hoki/https://www.angkolabarat.tapselkab.go.id/products/slot-maxwin/https://www.angkolabarat.tapselkab.go.id/products/slot-pulsa/https://www.angkolabarat.tapselkab.go.id/products/slot-receh/https://www.angkolabarat.tapselkab.go.id/products/slot-toto/https://www.angkolabarat.tapselkab.go.id/products/slot-demo/>
https://www.jurnal.poltekanika.ac.id/products/asia4d/https://www.jurnal.poltekanika.ac.id/products/bet88/https://www.jurnal.poltekanika.ac.id/products/idn-slot/https://www.jurnal.poltekanika.ac.id/products/mpo-slot/https://www.jurnal.poltekanika.ac.id/products/nexus-slot/https://www.jurnal.poltekanika.ac.id/products/pay4d/https://www.jurnal.poltekanika.ac.id/products/sbobet88/https://www.jurnal.poltekanika.ac.id/products/slot77/https://www.jurnal.poltekanika.ac.id/products/slot88/https://www.jurnal.poltekanika.ac.id/products/sv388/
https://slot-bonus.pn-subang.go.id/products/bonus-new-member/https://slot-dana.pn-subang.go.id/products/slot-dana/https://slot-demo.pn-subang.go.id/products/slot-demo/https://slot-garansi-kekalahan.pn-subang.go.id/products/slot-garansi-kekalahan/https://slot-hoki.pn-subang.go.id/products/slot-hoki/https://slot-maxwin.pn-subang.go.id/products/slot-maxwin/https://slot-pulsa.pn-subang.go.id/products/slot-pulsa/https://slot-receh.pn-subang.go.id/products/slot-receh/https://slot-toto.pn-subang.go.id/products/slot-toto/https://slot-zeus.pn-subang.go.id/products/slot-zeus/https://unogoal.pn-subang.go.id/products/unogoal/https://toto-togel.pn-subang.go.id/products/toto-togel/https://spbo.pn-subang.go.id/products/spbo/https://pkv-games.pn-subang.go.id/products/pkv-games/https://parlay-bola.pn-subang.go.id/products/parlay-bola/https://nowgoal.pn-subang.go.id/products/nowgoal/https://judi-bola.pn-subang.go.id/products/judi-bola/https://idn-poker.pn-subang.go.id/products/idn-poker/https://dominoqq.pn-subang.go.id/products/dominoqq/https://bet88.pn-subang.go.id/products/bet88/
https://ppid.dpubinmarcipka.jatengprov.go.id/dokumen/link-gacor/https://ppid.dpubinmarcipka.jatengprov.go.id/dokumen/link-demo/https://ppid.dpubinmarcipka.jatengprov.go.id/dokumen/situs-thailand/https://ppid.dpubinmarcipka.jatengprov.go.id/dokumen/situs-kamboja/https://ppid.dpubinmarcipka.jatengprov.go.id/dokumen/sbobet/https://sdi.babelprov.go.id/publikasi/link-demo/https://sdi.babelprov.go.id/publikasi/situs-thailand/https://sdi.babelprov.go.id/publikasi/situs-kamboja/https://sdi.babelprov.go.id/publikasi/sbobet88/https://akun-pro-hongkong.amikmahaputra.ac.id/products/slot-hongkong/