Concombre 3 + Java

Il y a quelques mois, la JVM 3.0.0 de Cucumber est sortie. La nouvelle version est conçue pour rendre le travail avec ce cadre BDD plus évident et plus flexible. Dans cet article, je parlerai des changements et des nouvelles fonctionnalités, ainsi que des exemples de leur utilisation.

Mise en œuvre d'expressions de concombre


Dans la troisième version de la machine virtuelle Java Cucumber, Cucumber Expressions est désormais disponible, un langage d'expression simple pour rechercher des sous-chaînes dans du texte. Contrairement aux expressions régulières, ce langage est optimisé pour la lisibilité, ce qui est plus logique dans le contexte de Cucumber. Si vous avez besoin de flexibilité, vous pouvez toujours utiliser des expressions régulières.

Par exemple, nous avons la fonctionnalité suivante:

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

Pour en obtenir des arguments, vous pouvez utiliser la description suivante des étapes:

  @("      {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); } 

Comme vous pouvez le voir dans l'exemple, Cucumber Expressions se compose de deux accolades avec le type de la valeur transmise.

Hors de la boîte, les types d'équipement suivants sont disponibles:

  • {int}
  • {float}
  • {chaîne}
  • {mot}
  • {biginteger}
  • {bigdecimal}
  • {byte}
  • {court}
  • {long}
  • {double}

{chaîne} correspond à une chaîne entre guillemets et {mot} à un seul mot sans guillemets (au moment de la rédaction, seuls les mots écrits en lettres latines peuvent être transférés vers l'expression {mot}).

Vous pouvez créer votre propre type de données, par exemple, nous voulons transférer un objet de classe LocalDate à partir d'une fonctionnalité:

 # language: ru :    : *     01.06.2018 

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

Pour ce faire, dans le package spécifié dans glue, vous devez créer une classe qui implémente l'interface TypeRegistryConfigurer et, à travers elle, ajouter votre type de données au registre:

 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 classe qui implémente l'interface TypeRegistryConfigurer doit être une dans le projet, sinon une exception sera levée.

Cucumber Expressions vous permet également de spécifier du texte optionnel entre crochets:

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

Vous ne pouvez pas utiliser d'espaces entre crochets (au moment de la rédaction, seul l'alphabet latin est pris en charge).

Le texte alternatif est spécifié par une barre oblique:

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

 # language: ru :     : *   *   

Vous pouvez échapper {} et () avec une barre oblique inverse.

Vous ne pouvez pas utiliser d'expressions régulières et d'expressions de concombre dans la même définition d'étape.

Abandon de XStream


Dans les première et deuxième versions de Cucumber, des expressions régulières et la bibliothèque XStreamsConverters ont été utilisées pour déterminer le type de données transmises. Dans la troisième version de Cucumber, les développeurs ont abandonné l'utilisation de la bibliothèque XStreamsConverters.

La raison de l'abandon de XStreamConverters était une mauvaise documentation, l'incapacité d'utiliser des mappeurs d'objets tiers et le manque de prise en charge de Java 9.
Annotations Delimiter, Format, Transformer et autres annotations de XStream ne fonctionnent plus. Au lieu de cela, vous devez maintenant utiliser ParameterType ou DataTableType.

DataTable


Le type de données DataTable a également subi des modifications.

Comme dans les versions précédentes, Cucumber 3 gère sans problème la conversion d'un DataTable avec une colonne en List, deux colonnes en Map, etc. Mais cela ne fonctionne que si vous convertissez les données dans l'un des types suivants: String, Integer, Float, Double, Byte, Short, Long, BigInteger ou BigDecimal.

Si vous souhaitez créer un objet d'une autre classe à partir d'un DataTable, alors, comme dans le cas d'un type de données personnalisé, vous devez écrire votre propre convertisseur:

 # 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); } 

Le convertisseur est ajouté au registre de la même manière que dans l'exemple avec le type de données utilisateur:

 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; } )); } } 

Crochets de marche avant et après


Une autre innovation est l'étape pré et post. Vous pouvez maintenant définir des hooks qui seront appelés avant et / ou après chaque étape du script.

Les hooks d'étape suivent les mêmes règles que les hooks de niveau script:

  • les balises peuvent être accrochées aux crochets pour les exécuter uniquement dans certains scénarios;
  • Vous pouvez définir l'ordre d'exécution des hooks;
  • AfterStep sera exécuté même si l'étape après laquelle il était censé être exécuté est interrompue.

 # 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 conclusion, je voudrais dire que même si vous avez utilisé les capacités de XStream dans vos projets et avec la transition vers la nouvelle version de Cucumber, il faudra apporter de petites améliorations, je le recommande. Le concombre est pris en charge et activement développé, et de nouvelles fonctionnalités rendent son utilisation plus flexible et plus compréhensible.

Mise à jour 23/09/2018
Aujourd'hui, Cucumber 4.0.0 est sorti. Je ne décrirai pas tous les changements, je dirai seulement que maintenant la langue russe est normalement prise en charge dans les expressions de concombre, et aussi que l'exemple que j'ai écrit avec {string} et {word} ne fonctionnera plus. Le fait est que {word} peut désormais contenir n'importe quel caractère non blanc, ce qui provoque un conflit lors de la recherche d'une étape d'implémentation:

 # language: ru :     : *     "" *     hello 


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


Références:

Exemples de l'article
Mon article sur la première version de la JVM Cucumber

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


All Articles