quinta-feira, 29 de novembro de 2012

Specification By Example


Terminologia e Definição



O termo Specification by Example (Especificação por Exemplos) surgiu segundo seu criador Gojko Adzik (2011) com o intuíto de unificar em um só termo as seguintes técnicas, metodologias e práticas ágeis:



  • Agile acceptance testing
  • Test-Driven Development
  • Acceptance Test-Driven Development
  • Example-Driven Development
  • Story testing
  • Behavior-Driven Development



Segundo Gojko o fato de as mesmas práticas possuírem tantos nomes diferentes reflete o grande número de inovações nesse campo no cenário atual da industria de software. Sobre essas diferentes nomenclaturas Gojko afirma:



Se queremos os usuários finais (stakeholders) mais envolvidos, o que é o principal objetivo dessas práticas, precisamos usar os nomes corretos para as coisas corretas e parar de confundir as pessoas.



O autor decidiu por tanto simplificar essa terminologia na comunidade de software para que as pessoas possam usufruir de seus benefícios sem entrarem em discuções improdutivas sobre terminologias. Specification by Example é o resultado de um conjunto de estudos de caso realizados por Gojko com mais de 50 projetos de desenvolvimento de software do mundo real. Projetos que variam em tecnologia (de websites a softwares para desktop) e em metodologias (Extreme Programing, Scrum, Kanban e outras metodologias normalmente agrupadas sobre os termos agile e lean). Specification by Example pode ser definido como um suplemento de práticas que podem ser incorporadas a qualquer metodologia de desenvolvimento atual.





Necessidade


Construir o produto certo e construir certo o produto são dois objetivos distindos. Porém os dois são necessários para se obter sucesso. Segundo Gojko tradicionalmente, construir o produto certo requeria enormes especificações funcionais, documentação e longos ciclos de teste, atualmente em um mundo de releases semanais isso não funciona. Ainda segundo Gjko é necessário uma solução para:

  • Evitar super-especificações inúteis; Evitar gastar tempo em detalhes que mudarão antes do primeiro fragmento de trabalho ser desenvolvido.
  • Ter documentos legíveis que explicam oque o sistema faz para que se posso modificá-lo facilmente.
  • Checar de maneira eficiente que o sistema faz o que as especificações dizem.
  • Manter a documentação relevante e confiável com o menor custo de manutenção.
  • Colocar tudo isso em processos baseados em iterações, de forma que a informação do trabalho a ser feito é produzida sob demanda.

Specification by Example unificou padrões e processos que times do mundo real utilizaram para atingir esses objetivos.


Padrões de processo

Os padrões estabelecidos por Specification by Example são assim denominados no sentido em que eles são elementos recorrentes usados por diferentes times; São resultados de uma série de experimentos empíricos com projetos e times reais e não de um modelo teórico de elaboração de processos.




Figura 1. Principais padrões de processo de Specification by Example.

1. Deriving scope from goals (Derivando o escopo dos objetivos): Nessa etapa a equipe que criará o software deve derivar os escopos de desenvolvimento a partir dos objetivos estabelecidos pelos stakeholders. Segundo Gojko é um erro esperar que os usuários envolvidos digam qual o escopo de desenvolvimento pois os mesmos não são designers de software. O mais apropriado nessa etapa é elencar os objetivos que os stakeholders querem atingir com o software em questão. Em outras palavras, qual ou quais os problemas que a “solução” deve ser capaz de resolver. Começa-se com um objetivo de negócios o time de desenvolvimento colabora definindo o escopo que vai atingir este objetivo.

2. Specifying collaboratively (Especificando colaborativamente): O time nesse etapa deverá juntamente com os stakeholders especificar colaborativamente o comportamento esperado para cada funcionalidade do escopo. Desenvolvedores, testadores e analista de negócios devem participar nessa etapa pois cada um tem um contexto único e habilidades que podem ajudar a resolver questões que de outra forma poderiam passar desapercebidas gerando re-trabalho no futuro.

3. Illustrating using examples (Ilustrando utilizando exemplos): Ao invés de esperar que as especificações sejam expressadas precisamente em uma linguagem de programação durante a implementação, deve-se ilustrar o comportamento  esperado do sistema utilizando exemplos antes do desenvolvimento ser iniciado. O time de desenvolvimento trabalha com os stakeholders para identificar exemplos-chave que descrevem a funcionalidade esperada. Desenvolvedores e testadores dão exemplos adicionais que revelam áreas antes ignoradas da funcionalidade evitando assim gaps funcionais e faz com que todos tenham um conhecimento distribuído sobre aquilo que precisam entregar.

4. Refining the specification (Refinando a especificação): Nessa etapa o time de desenvolvimento deve remover informações irrelevantes dos exemplos tais como detalhes que tornam os exemplos extensos e verbosos sem adicionar informações úteis. Segundo Gjko deve-se identificar o que o software deve fazer e não detalhar o como fazer. Os resultados dessa etapa podem ser considerados critérios de aceitação, que ao mesmo tempo são especificações para o desenvolvimento e futuramente quando automatizados farão parte dos testes de regressão.

5. Automating validation without changing specifications (Automatizando as validações sem modificar as especificações): Com os exemplos especificados e refinados o time pode usá-los como meio de validar o produto. O sistema será validado diversas vezes durante o desenvolvimento para assegurar que o mesmo atinge os objetivos. Rodar essas validações manualmente introduziria um delay desnecessário e o feedback seria lento. A solução para isto é automatizar as validações, porém essa automação deve também ser acessível aos stakeholders e não deve modificar as especificações originais. O time de desenvolvimento literalmente deve escrever a automação com as mesmas palavras utilizadas para criarem os exemplos, pois scripts e código fonte não têm a capacidadade de contar expressar adequadamente o contexto de negócio em que estão inseridos e documentação puramente textual fica desatualizada rapidamente. Portanto nessa etapa a validação automática do sistema, suas especificações por exemplos e seus critérios de aceitação tornam-se um só. O resultado dessa etapa gera especificações executáveis.  

6. Validating Frequently (Validando frequentemente): Gjko afirma que a documentação tradicional de software fica desatualizada antes mesmo de o sitema ser lançado. A validação frequente é um produto das especificações executáveis ela sincroniza o que foi especificado com o que o sistema realmente está fazendo.

7. Evolving a documentation system (Evolução de um sistema de documentação): Nessa etapa o time de desenvolvimento mantém a documentação viva (especificações executáveis - testes) atualizada com as modificações requisitadas pelos stakeholders para incrementar o software. As especificações e testes estando em um mesmo lugar facilitam essa mudança pois concentram os esforços em apenas uma fonte de informações. Desenvolvedores utilizam essa documentação como especificações, testadores utilizam como testes e os analistas de negócio utilizam para avaliar o impácto que uma mudança ou especificação futura pode ter no sistema.
Os exemplos são tratados como fonte única de verdade, sendo este um aspecto chave desta metodologia. Desta forma, evita que diferentes colaboradores de uma equipe de desenvolvimento gerem e trabalhem somente em seus próprios documentos. Neste contexto, pode-se afirmar que a eficácia da entrega do software é significativamente afetada pela constante necessidade de coordenação e sincronização destas diferentes “versões da verdade”. Fazendo uso de SbE todos os membro da equipe participam da criação da única fonte de verdade, sendo assim nela encontra-se a compreensão de todos. Estes exemplos são utilizados para proporcionar precisão e clareza, para fazer uso desta informação tanto como uma especificação como um teste funcional. Qualquer informação considerada relevante durante o ciclo de desenvolvimento é adicionada a esta fonte de exemplos única, sem requerer qualquer necessidade de tradução ou interpretação.

Documentação Viva

Segundo Gojko a questão da documentação gerada pelo Specification by Example advém parte do ATTD e parte do BDD, ambas com focos diferentes que quando unidas proporcionam uma totalidade na cobertura e profundidades acerca das especificações do sistema. O ATTD detém seu foco na automação dos testes funcionais, de regressão e são alvos mais claros para o desenvolvimento. O ATDD é mais útil para a adoção inicial quando se tem muitos problemas relacionados a qualidade funcional do sistema. Já o BDD centra-se no processo de especificação de cenários por meio do comportamento do sistema, podendo servir como base para fundamentar as atividades de entrega de software, a médio e curto prazo. O BDD centra-se na construção do entendimento comum entre as partes interessadas através da colaboração e esclarecimento de especificações. É necessário saber o que um sistema faz para ser capaz de analisar os impactos das mudanças sugeridas, apoiá-lo, e solucionar problemas. Muitas vezes, a única maneira de descobrir o que o sistema faz é olhar para o código-fonte da linguagem de programação e aplicar engenharia reversa na funcionalidade do negócio. Logo uma boa documentação é útil para além do desenvolvimento de software. 
A solução ideal seria um sistema de documentação que é fácil e barato de manter, de forma que ele possa ser mantido de acordo com a funcionalidade do sistema, mesmo se o código da linguagem de programação subjacente é alterado com frequência. O problema com qualquer tipo de documentação completa é, de fato, o custo de manutenção. Quando um sistema de software é continuamente validado contra um conjunto de especificações executáveis, uma equipe pode estar certa de que o sistema irá fazer o que as especificações dizem, ou, em outras palavras, que as especificações vão continuar a descrever o que o sistema faz. Essas especificações vivem com o sistema, e elas são sempre consistentes, e pelo fato da noção das diferenças entre as especificações e a funcionalidade de fato implementada de forma imediata, esta documentação pode ser mantida consistente a um baixo custo. Estas especificações executáveis ​​criam um corpo robusto de documentação, uma fonte autorizada e não ambígua de informações sobre a funcionalidade de um sistema,fazendo uma analogia, cada uma das especificações seriam como páginas do livro que é o próprio sistema de documentação viva. 
Gojko ainda afirma que a documentação viva substitui todos os artefatos que as equipes precisam para entregar o produto certo, ela pode até mesmo apoiar a produção de manuais de usuários (embora provavelmente não substituí-los). As especificações são definidas conforme e concomitante a evolução do sistema, a documentação resultante é incremental e assim torna-se barata de escrever. Ao mesmo tempo em que os processos de negócio são derivados é possível executá-los exercitando e auxiliando o processo de desenvolvimento do software, já que se trata de algo mais leve e intrinsecamente mais ligado ao código real, é uma documentação real. Aplicar Specification by Example somente pelo fato do ganho por meio dos testes de regressão acaba por não justificar o investimento feito em longo prazo para implementá-lo já que conforme as estimativas dos custos de software, aponta que a eficiência na remoção dos defeitos por meio de testes de regressão é de 23% em média. Esta prática permite a criação de documentação viva sem necessidade de anos de prática pela sua forma mais natural de escrita, criando documentação por meio de especificações executáveis.
Figura 2 Tipo de documentação que deve ser escrita
A documentação viva é tão importante quanto o sistema que se está entregando, a ideia de que a documentação é um produto chave é o cerne deste método. Algumas vantagens em ter uma documentação viva são apontadas por Gojko: 
  • Ajuda as equipes a longo prazo  evitando os problemas mais comuns com manutenção;
  •  Ajuda as equipes a criarem documentação útil que irá facilitar a evolução do software ao longo do tempo;
  •  Ajuda a evitar problemas de manutenção causados ​​pela falta de conhecimento compartilhado.

sábado, 17 de novembro de 2012

Como o Cucumber Funciona



O cucumber é uma ferramenta de linha de comando. Seu módo de funcionamento e suas camadas operam basicamente da seguinte forma:

Camada de negócios

  1. O Cucumber lê as especificações escritas em arquivos de texto plano chamados features;
  2. Examina esse tipo de arquivos a procura de scenarios;
  3. Cada scenario é uma lista de steps que o Cucumber irá tentar executar;
  4. Cada step é escrito em linguagem natural de domínio da aplicação. Para que sejam facilmente lidos e interpretados por pessoas sem a necessidade de qualquer conhecimento técnico;

Camada de tecnologia

  1. Para realizar quaisquer ações os steps# precisam estar implementados em um arquivo separado chamado de  step definition;
  2. A implementação dos steps dentro dos steps definitions é realizada através do support code ou código de suporte, que pode ser escrito em uma variada gama de linguagens¹;
  3. O support code é o responsável por se encarregar das tarefas de automação, normalmente isso envolve uma automation library ou biblioteca de automação que então entrará em contato direto com o sistema alvo do teste.

Essa hierarquia de camadas pode ser melhor observada na figura 1.0.

Figura 1.0. Pilha de funcionamento do cucumber.


Gherkin

O padrão de escrita chamado Gherkin nasceu da necessidade  de expressar de forma clara o comportamento esperado das funcionalidades que os stakeholders esperam do sistema utilizando exemplos.

“O Gherkin fornece uma estrutura leve para documentar os exemplos de comportamento que os stakeholders querem.”  

Mesmo o Gherkin podendo ser similar a uma linguagem de programação o seu principal objetivo é ser legível para humanos, isto significa que, é possível escrever testes automatizados que podem ser lidos como documentação tais como no exemplo a seguir:



Funcionalidade: Retirar dinheiro do caixa eletrônico

Cenário: Retirando dinheiro de uma conta com crédito
Dado uma conta contendo R$ 100,00
Quando eu requisito $ 49,00
Então o caixa deve liberar o valor de $ 49,00
E o saldo restante deve ser R$ 51,00

Exemplo de cenário escrito com Gherkin.

O Gherkin também foi traduzido para mais de quarenta idiomas bastando para isso utilizar as palavras-chave (em negrito no exemplo anterior) equivalentes no idioma desejado.


Formato e Sintaxe

Os arquivos Gherkin usam a extensão .feature e são salvos em texto plano, isto significa que eles podem ser lidos e editados por ferramentas simples. A estrutura de um arquivo Gherkin é estabelecida pelas seguintes palavras-chave (com seus equivalentes em português):

  • Feature, Funcionalidade.
  • Background, Contexto.
  • Scenario, Cenário.
  • Given, Dado.
  • When, Quando.
  • Then, Então.
  • And, E.
  • But, Mas.
  • *.
  • Scenario Outline, Esquema do Cenário.
  • Examples, Exemplos.

Para outro idioma basta utilizar as palavras equivalentes na linguagem desejada.



Feature (Funcionalidade)

Cada arquivo Gherkin começa com a palavra-chave Feature. Essa palavra-chave não afeta o comportamento do cucumber, ela apenas dá um lugar conveniente para escrever alguma documentação resumida a respeito do comportamento da funcionalidade que será descrita através dos testes.

Segue um exemplo da utilização dessa palavra-chave:

Funcionalidade: Esse é o título da funcionalidade
Essa é a descrição da funcionalidade que pode ocupar
diversas linhas.
É possível até mesmo colocar linhas em branco

De fato, tudo que esteja escrito até a próxima palavra-chave do Gherkin é incluído
na descrição.

Dentro de uma estrutura Gherkin válida a palavra-chave Feature deve obrigatoriamente ser seguida de uma das seguintes palavras-chave:

  • Scenario
  • Background
  • Scenario Outline

Scenario (Cenário)

Para representar o comportamento necessário, cada feature contém vários Scenarios. Cada Scenario é um único e concreto exemplo de como a funcionalidade em questão deve se comportar em um caso específico. Todos os Scenarios de uma Feature juntos definem o comportamento dessa Feature.
Todos os Scenarios seguem o seguinte padrão:

  1. Colocam o sistema em um estado específico.
  2. Realizam algum tipo de ação.
  3. Examinam o estado final.





Given, When, Then (Dado, Quando, Então)

No padrão Gherkin os estados, ações e asserções que ocorrem em um Scenario são representados pelas palavras-chave Given, When, Them, da seguinte forma:

Scenario:
Given <prepara o contexto>
When <executa uma ação ou evento>
Then <verifica o estado final>

Dessa  forma usa-se o  Given para preparar o contexto de onde o Scenario vai acontecer. Usa-se o When para interagir com o sistema de alguma forma e o Then para checar se o resultado dessa ação foi o esperado.

And, But (E, Mas)

Cada linha de um Scenario é conhecido como step (passo). É possível adicionar mais steps para cada Given, When ou Them utilizando-se And e But. Como no exemplo a seguir:

Cenário: Retirando dinheiro de uma conta com crédito
Dado uma conta contendo R$ 100,00
Quando eu requisito $ 49,00
Então o caixa deve liberar o valor de $ 49,00
E o saldo restante deve ser R$ 51,00

Essas palavras-chave não modificam o comportamento do Cucumber e existem simplesmente para promover a legibilidade dos Scenarios.