Pepino 3 + Java

Hace unos meses, se lanzó Cucumber JVM 3.0.0. La nueva versión está diseñada para hacer que trabajar con este marco BDD sea más obvio y flexible. En este artículo hablaré sobre los cambios y las nuevas características, y daré ejemplos de su uso.

Implementación de expresiones de pepino


En la tercera versión de Cucumber JVM, Cucumber Expressions ahora está disponible, un lenguaje de expresión simple para encontrar subcadenas en el texto. A diferencia de las expresiones regulares, este lenguaje está optimizado para facilitar la lectura, lo que tiene más sentido en el contexto de Cucumber. Si necesita flexibilidad, aún puede usar expresiones regulares.

Por ejemplo, tenemos la siguiente característica:

# language: ru :     : *       15 *     "" *     hello 

Para obtener argumentos, puede usar la siguiente descripción de pasos:

  @("      {int}") public void giveInt(Integer int1) { System.out.println(int1); } @("    {string}") public void giveString(String string) { System.out.println(string); } @("    {word}") public void giveWord(String string) { System.out.println(string); } 

Como puede ver en el ejemplo, las expresiones de pepino consisten en dos llaves con el tipo del valor transmitido.

Fuera de la caja, están disponibles los siguientes tipos de equipo:

  • {int}
  • {flotador}
  • {string}
  • {palabra}
  • {biginteger}
  • {bigdecimal}
  • {byte}
  • {corto}
  • {largo}
  • {doble}

{string} corresponde a una cadena entre comillas, y {word} a una sola palabra sin comillas (al momento de la escritura, solo las palabras escritas en letras latinas se pueden transferir a la expresión {word}).

Puede crear su propio tipo de datos, por ejemplo, queremos transferir un objeto de clase LocalDate desde una característica:

 # language: ru :    : *     01.06.2018 

  @("    {localdate}") public void ___(LocalDate localdate) { System.out.println(localdate.format(DateTimeFormatter.ofPattern("dd-MM-yyyy"))); } 

Para hacer esto, en el paquete especificado en el pegamento, debe crear una clase que implemente la interfaz TypeRegistryConfigurer y, a través de ella, agregar su tipo de datos al registro:

 public class TypeRegistryConfiguration implements TypeRegistryConfigurer { @Override public Locale locale() { //        float  double return new Locale("ru"); } @Override public void configureTypeRegistry(TypeRegistry typeRegistry) { //       typeRegistry.defineParameterType(new ParameterType<>( //  ,    : "localdate", // ,      : "[0-9]{2}.[0-9]{2}.[0-9]{4}", //  : LocalDate.class, // ,       (Transformer<LocalDate>) s -> { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy"); return LocalDate.parse(s, formatter); } )); } } 

La clase que implementa la interfaz TypeRegistryConfigurer debe ser una en el proyecto; de lo contrario, se generará una excepción.

Las expresiones de pepino también le permiten especificar texto opcional entre paréntesis:

  @("Hello, world(s)!") public void getHello() { System.out.println("Hello world!"); } 

No puede usar espacios entre corchetes (al momento de escribir, solo se admite el alfabeto latino).

El texto alternativo se especifica mediante una barra inclinada:

  @("/ ") public void getAlternative() { System.out.println("Hello world!"); } 

 # language: ru :     : *   *   

Puede escapar {} y () con una barra invertida.

No puede usar expresiones regulares y expresiones de pepino en la misma definición de paso.

Abandono XStream


En la primera y segunda versión de Cucumber, se utilizaron expresiones regulares y la biblioteca XStreamsConverters para determinar el tipo de datos transmitidos. En la tercera versión de Cucumber, los desarrolladores abandonaron el uso de la biblioteca XStreamsConverters.

La razón para abandonar XStreamConverters fue una documentación deficiente, la incapacidad de usar mapeadores de objetos de terceros y la falta de soporte para Java 9.
Delimitador de Anotaciones, Formato, Transformador y otras anotaciones de XStream ya no funcionan. En cambio, ahora necesita usar ParameterType o DataTableType.

DataTable


El tipo de datos DataTable también ha sufrido cambios.

Como en versiones anteriores, Cucumber 3 maneja la conversión de una DataTable con una columna a Lista, dos columnas a Mapa, etc. sin ningún problema. Pero esto solo funciona si convierte los datos a uno de los siguientes tipos: String, Integer, Float, Double, Byte, Short, Long, BigInteger o BigDecimal.

Si desea crear un objeto de alguna otra clase a partir de una DataTable, entonces, como en el caso de un tipo de datos personalizado, debe escribir su propio convertidor:

 # language: ru :     DataTable :      |  |  | 09.02.1887 | |  |  | 23.02.1890 | 

User.java
 import java.time.LocalDate; public class User { private String firstName; private String lastName; private LocalDate birthDay; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public LocalDate getBirthDay() { return birthDay; } public void setBirthDay(LocalDate birthDay) { this.birthDay = birthDay; } @Override public String toString() { return "User{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", birthDay=" + birthDay + '}'; } } 


  @("   ") public void ___(List<User> users) { System.out.println(users); } 

El convertidor se agrega al registro de la misma manera que en el ejemplo con el tipo de datos de usuario:

 public class TypeRegistryConfiguration implements TypeRegistryConfigurer { @Override public Locale locale() { return new Locale("ru"); } @Override public void configureTypeRegistry(TypeRegistry typeRegistry) { //       DataTableType typeRegistry.defineDataTableType(new DataTableType( User.class, (TableRowTransformer<User>) list -> { User user = new User(); user.setFirstName(list.get(0)); user.setLastName(list.get(1)); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy"); user.setBirthDay(LocalDate.parse(list.get(2), formatter)); return user; } )); } } 

Ganchos de paso antes y después


Otra innovación es pre y post paso. Ahora puede definir ganchos que se llamarán antes y / o después de cada paso del guión.

Los ganchos de paso siguen las mismas reglas que los ganchos de nivel de script:

  • las etiquetas se pueden colgar en ganchos para ejecutarlas solo en ciertos escenarios;
  • Puede establecer el orden de ejecución de los ganchos;
  • AfterStep se ejecutará incluso si se rompe el paso después del cual se suponía que debía ejecutarse.

 # language: ru :  @hooks :      ,                 @only_scenario_hooks :                 @only_step_hooks :                  

 //  not     //       hooks  only_scenario_hooks @Before(value = "(@hooks or @only_scenario_hooks) and not @only_step_hooks") public void before() { System.out.println("before scenario"); } //         only_step_hooks @BeforeStep(value = "@only_step_hooks") public void beforeStep() { System.out.println("before step"); } //         only_step_hooks @AfterStep(value = "not(@hooks or @only_scenario_hooks) and @only_step_hooks") public void afterStep() { System.out.println("after step"); } //       hooks  only_scenario_hooks @After(value = "@hooks or @only_scenario_hooks") public void after() { System.out.println("after scenario"); } 

En conclusión, me gustaría decir que incluso si utilizó las capacidades de XStream en sus proyectos y con la transición a la nueva versión de Cucumber, será necesario realizar pequeñas mejoras, lo recomiendo. Cucumber es compatible y se desarrolla activamente, y las nuevas características hacen que su uso sea más flexible y comprensible.

Actualización 23/09/2018
Hoy se ha lanzado Cucumber 4.0.0. No describiré todos los cambios, solo diré que ahora el idioma ruso normalmente es compatible con las expresiones de pepino, también que el ejemplo que escribí con {string} y {word} ya no funcionará. El hecho es que {word} ahora puede contener cualquier carácter que no sea un espacio en blanco, lo que causa un conflicto al buscar un paso de implementación:

 # language: ru :     : *     "" *     hello 


  @("    {string}") public void giveString(String string) { System.out.println(string); } @("    {word}") public void giveWord(String string) { System.out.println(string); } 


Referencias

Ejemplos del artículo
Mi artículo sobre la primera versión de Cucumber JVM

Source: https://habr.com/ru/post/es422651/


All Articles