Por que eu devo ler este artigo:Este artigo mostra como o Spock, um framework de especificações e testes para Java e Groovy, pode ajudá-lo na prática do BDD (Behavior-Driven Development), para o desenvolvimento e garantia da qualidade de software em seus projetos. No decorrer da leitura você também entenderá as diferenças entre os modos reativo e criativo de testes, qual a relação desse último com processos como TDD, ATDD e BDD e seu impacto sobre o papel do teste no desenvolvimento de software. O artigo apresenta, ainda, um projeto Maven de uma pequena aplicação Spring composta de serviços REST, onde se demonstra o uso do Spock na especificação e execução de testes, geração de relatórios com os resultados em HTML e sua integração tanto com a fase de testes do Maven, através do Surefire, quanto com a infraestrutura de testes do Spring.

A adoção de metodologias ágeis, como Extreme Programming (XP), Scrum e Kanban, reposiciona e redimensiona o teste a uma das atividades fundamentais no desenvolvimento de software, não só pela garantia de qualidade do produto final, mas também para a própria especificação do mesmo. Para melhor definir e suportar essa atividade foram sendo criadas novas práticas e métodos, das quais podemos destacar o TDD, ATDD e o BDD. Esses, por sua vez, impulsionaram o nascimento de frameworks de testes como o JUnit, RSpec, Cucumber e o Spock, sobre o qual discorremos aqui.

O Spock é um framework de especificação e testes para Java e Groovy. Através dele podemos aplicar em nosso desenvolvimento conceitos, notação e estilos do BDD, que, como será visto, definem requisitos de sistema de forma concisa, expressiva e bastante legível, mesmo para não programadores, através de especificações e cenários.

Neste artigo veremos como o Spock pode ser aplicado no desenvolvimento e teste de software utilizando um projeto para uma aplicação web composto de serviços REST que fornecem informações geoestatísticas de regiões, estados e municípios do Brasil a partir de dados do IBGE. Em sua implementação utilizaremos o Spring, mais especificamente o Spring Boot, como tecnologia base e o Maven como ferramenta de building e gerenciamento de dependências. Dessa forma, também exploraremos como o Spock pode ser naturalmente integrado tanto à fase de testes do Maven quanto aos recursos de testes do Spring.

Contudo, antes de abordarmos o desenvolvimento, vamos entender melhor o que se quer dizer com concisão, expressividade e legibilidade de testes, conforme mencionado anteriormente, para melhor avaliar o legado do BDD e do Spock. Para isso, vamos relembrar a necessidade, função e evolução do teste no desenvolvimento de software em Java, desde os simples unitários até as práticas de desenvolvimento orientado a testes, como o TDD, ATDD e o próprio BDD.

Testes unitários, integrados e o JUnit

Desde sempre houve a necessidade de se testar no desenvolvimento de software, seja em Java ou qualquer outra linguagem/ambiente. Testes visam assegurar que determinado requisito esteja implementado conforme o esperado após o desenvolvimento. Além disso, eles não precisam ser, necessariamente, artefatos construídos por desenvolvedores, podendo ser formulados e conduzidos por, ou com o auxílio, de uma equipe de testes. Neste artigo, entretanto, abordaremos o teste como uma das responsabilidades do desenvolvedor, o qual pode cumpri-la das seguintes formas:

  • Escrevendo testes ad hoc, ou seja, da forma e onde lhe parecer apropriado, o que em Java costuma resultar em um main() escrito na própria classe que se quer testar;
  • Escrevendo classes de teste que podem ser executadas de maneira automatizada a qualquer momento com a ajuda de um framework de testes como o JUnit e uma ferramenta de building, como o Ant, Maven, Gradle, entre outras.

Testes ad hoc atendem única e exclusivamente a necessidades pontuais de asserção de qualidade do desenvolvedor que os escreve, e não há como automatizá-los de uma forma simples. Para ilustrar, vamos imaginar que para implementar o requisito “fornecer um texto com a data e hora no formato DD/MM/YYYY HH:MM:SS”, tenha sido criada a classe Clock como apresentada na Listagem 1.

Listagem 1. Código da classe Clock.


  01 package br.com.devmedia.jm.woki.ibgez.misc;
  02
  03 import java.text.SimpleDateFormat;
  04 import java.util.Date;
  05 import java.util.Locale;
  06
  07 public final class Clock {
  08    private Clock() {
  09        // util
  10    }
  11
  12    public static final String DATEFORMAT = "dd/MM/yyyy HH:mm:ss";
  13
  14    public static String now() {
  15        return new SimpleDateFormat(DATEFORMAT, Locale.getDefault()).format(new Date());
  16    }
  17 }

Um teste ad hoc para o método Clock.now() poderia se resumir à inserção de um main() na classe, como mostra a Listagem 2.

Listagem 2. Código da classe Clock com um teste ad hoc.


  01  public final class Clock {
  02     ...
  03     public static void main(String[] args) {
  04        System.out.println(Clock.now());
  05     }
  06  }

Note que o método de asserção do desenvolvedor foi simplesmente checar se o resultado de System.out.println() corresponde ao esperado, ou seja, o teste é um artifício feito em tempo de desenvolvimento para ser executado manualmente — e essa é a natureza do teste ad hoc.

Agora, para ilustrar um teste utilizando o JUnit, observemos a classe de teste da Listagem 3.

Listagem 3. Uma classe de teste com JUnit para Clock.


  01 package br.com.devmedia.jm.woki.ibgez.misc;
  02
  03 import org.junit.Assert;
  04 import org.junit.Test;
  05
  06 import java.text.DateFormat;
  07 import java.text.SimpleDateFormat;
  08 import java.util.Date;
  09 import java.util.Locale;
  10
  11 public class ClockTest {
  12
  13    @Test
  14    public void testNow() throws Exception {
  15        DateFormat format = new SimpleDateFormat(Clock.DATEFORMAT, Locale.getDefault());
  16        String nowStr = Cl ... 

Quer ler esse conteúdo completo? Tenha acesso completo