Pepino 3 + Java

Alguns meses atrás, o Cucumber JVM 3.0.0 foi lançado. A nova versão foi projetada para tornar o trabalho com essa estrutura do BDD mais óbvio e flexível. Neste artigo, falarei sobre mudanças e novos recursos, além de dar exemplos de seu uso.

Implementação de expressões de pepino


Na terceira versão da JVM Cucumber, Expressões de pepino agora está disponível, uma linguagem de expressão simples para localizar substrings no texto. Diferentemente das expressões regulares, esse idioma é otimizado para facilitar a leitura, o que faz mais sentido no contexto do Pepino. Se você precisar de flexibilidade, ainda poderá usar expressões regulares.

Por exemplo, temos o seguinte recurso:

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

Para obter argumentos, você pode usar a seguinte descrição das etapas:

  @("      {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 você pode ver no exemplo, Expressões de pepino consiste em dois colchetes com o tipo do valor transmitido.

Fora da caixa, os seguintes tipos de equipamento estão disponíveis:

  • {int}
  • {flutuar}
  • {string}
  • {word}
  • {biginteger}
  • {bigdecimal}
  • {byte}
  • {short}
  • {long}
  • {double}

{string} corresponde a uma string entre aspas e {word} a uma única palavra sem aspas (no momento da redação, somente palavras escritas em letras latinas podem ser transferidas para a expressão {word}).

Você pode criar seu próprio tipo de dados, por exemplo, queremos transferir um objeto de classe LocalDate de um recurso:

 # language: ru :    : *     01.06.2018 

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

Para fazer isso, no pacote especificado em cola, você precisa criar uma classe que implemente a interface TypeRegistryConfigurer e, por meio dela, adicione seu tipo de dados ao 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); } )); } } 

A classe que implementa a interface TypeRegistryConfigurer deve ser uma no projeto, caso contrário, uma exceção será lançada.

Expressões de pepino também permite especificar texto opcional entre colchetes:

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

Você não pode usar espaços entre colchetes (no momento da escrita, apenas o alfabeto latino é suportado).

O texto alternativo é especificado através de uma barra:

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

 # language: ru :     : *   *   

Você pode escapar {} e () com uma barra invertida.

Você não pode usar expressões regulares e expressões de pepino na mesma definição de etapa.

Abandono do XStream


Na primeira e na segunda versões do Cucumber, expressões regulares e a biblioteca XStreamsConverters foram usadas para determinar o tipo de dados transmitidos. Na terceira versão do Cucumber, os desenvolvedores abandonaram o uso da biblioteca XStreamsConverters.

A justificativa para o abandono do XStreamConverters foi a documentação pobre, a incapacidade de usar mapeadores de objetos de terceiros e a falta de suporte ao Java 9.
O delimitador de anotações, o formato, o transformador e outras anotações do XStream não funcionam mais. Em vez disso, agora você precisa usar ParameterType ou DataTableType.

DataTable


O tipo de dados DataTable também sofreu alterações.

Como nas versões anteriores, o Pepino 3 lida com a conversão de uma DataTable com uma coluna em Lista, duas colunas em Mapa, etc. sem problemas. Mas isso só funciona se você converter os dados para um dos seguintes tipos: String, Inteiro, Flutuante, Duplo, Byte, Curto, Longo, BigInteger ou BigDecimal.

Se você deseja criar um objeto de alguma outra classe a partir de uma DataTable, então, como no caso de um tipo de dados personalizado, você precisa escrever seu próprio conversor:

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

O conversor é adicionado ao registro da mesma maneira que no exemplo com o tipo de dados do usuário:

 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 antes e depois da etapa


Outra inovação é pré e pós etapa. Agora você pode definir ganchos que serão chamados antes e / ou após cada etapa do script.

Os ganchos de etapa seguem as mesmas regras que os ganchos de nível de script:

  • as tags podem ser penduradas em ganchos para executá-las somente em determinados cenários;
  • Você pode definir a ordem de execução dos ganchos;
  • O AfterStep será executado mesmo se a etapa após a qual ela deveria ser executada for interrompida.

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

Concluindo, gostaria de dizer que, mesmo que você tenha usado os recursos do XStream em seus projetos e com a transição para a nova versão do Cucumber, será necessário fazer pequenas melhorias, eu recomendo isso. O pepino é suportado e desenvolvido ativamente, e novos recursos tornam seu uso mais flexível e compreensível.

Atualização 23/09/2018
Hoje, o Pepino 4.0.0 foi lançado. Não descreverei todas as alterações, apenas direi que agora o idioma russo é normalmente suportado nas Expressões de pepino, e também que o exemplo que escrevi com {string} e {word} não funcionará mais. O fato é que {word} agora pode conter qualquer caractere que não seja um espaço em branco, o que causa um conflito ao procurar uma etapa de implementação:

 # language: ru :     : *     "" *     hello 


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


Referências:

Exemplos do artigo
Meu artigo sobre a primeira versão da JVM de pepino

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


All Articles