Behavior Driven Design (BDD) – Validando o comportamento de uma aplicação com VS 2015 + SpecFlow + Selenium

15 mar

Fala Galera,

Quando nós construímos uma aplicação temos diversas variáveis para nos preocupar. Essas variáveis geralmente são performance, ser escalável, uma boa usabilidade e atender aos requisitos de negócio. Existe uma outra variável que temos que nos preocupar também a nossa aplicação deve ter qualidade. E por que não coloquei a qualidade nas variáveis acima citadas, por que é implícito que devemos construir algo com qualidade ou alguém já pensou em construir uma aplicação sem qualidade ? Acredito que não.

Porém obter qualidade não é tão simples quanto parece. Quais métricas iremos usar  ? Quantidade de Bug ? Números de Teste? Cobertura de Código ? Não existe uma resposta correta nem uma bala de prata.

Qualidade é importante ? Claro que é. A empresa no qual trabalha espera por isso, seu cliente espera por isso, sua equipe espera por isso. Isso ninguém questiona.

E como podemos aumentar a qualidade do nosso software ? A resposta é testando seu software ao máximo. Testes são importantes, porém poucas pessoas fazem ou fazem os testes de forma correta.

Conceito do TDD (Test Driven Design)

Todo o ciclo do TDD se baseia em você fazer os testes antes de implementar seu código, essa quebra de paradigma é um pouco complicada no inicio pois estamos acostumados a primeiro desenvolver e depois testar. Isso força os desenvolvedores a pensar mais como será a funcionalidade, como será seu comportamento e o quais regras de negócio aplicar.  Daí temos o famoso conceito do TDD que é o RED, GREEN, REFACTOR.

Esse conceito é o core do TDD, se baseia no ciclo no qual seu teste no começo será vermelho, depois ele ficará verde e após temos que fazer o refactor do nosso código até ficar verde de novo

Esse ciclo se repete para todas as funcionalidades que iremos implementar. No final teremos todos os testes da nossa aplicação mapeada e nosso código sempre estará sendo testado pelos os testes unitários.

O Behavior Driven Design

O BDD é uma técnica de desenvolvimento ágil que encoraja a colaboração entre os Desenvolvedores, a equipe de QA (Quality Assurance) e a equipe de negócio ou uma equipe não técnica.

O BDD é mais voltado para especificações de negócio do que propriamente soluções técnicas. O analista de negócio escreve uma estória de negócio em um português estruturado e nós temos que desenvolver nosso código baseado nessa regra de negócio.

Logo nossa funcionalidade deve atender a estória de negócio e os testes garantirão que essa regra foi atendida como o esperado.

Os principais conceitos do BDD são

  • Uma estória testável (deve ser pequena para se encaixar em um ciclo)
  • O título deve descrever uma atividade
  • A narrativa deve incluir um ator, uma característica e um benefício.
  • A narrativa deve descreve somente um evento baseado no contexto da estória
  • O evento deve descrever uma funcionalidade

Ferramentas essenciais para BDD

  • SpecFlow – Framework que suporta a especificações BDD para .NET
  • MSTest ou outro Framework de testes de sua preferência
  • Selenium – Framework para testes de interfaces utilizando Browsers como Chrome, Firefox e etc

 

Configuração Inicial

Para usar essas ferramentas iremos criar um projeto ASP.NET MVC, o SpecFlow suporta as versões do Visual Studio 2012, 2013, 2015.

Para instalar o SpecFlow iremos adicionar o plugin do SpecFlow no Visual Studio conforme imagem abaixo:

BDD1

Com o plugin instalado, poderemos usar as especificações do BDD.

Entendo os cenários com o SpecFlow.

Devemos criar os cenários de testes no qual usaremos para realizar os testes. O SpecFlow permite que você crie testes em uma linguagem de fácil compreensão utilizando o Cucumber . O Cucumber é uma linguagem estruturada e que permite você escrever especificações no formato Gherkin Syntax. Um cenário é formato por três passos: GIVEN, WHEN, and THEN

Sabendo desses conceitos vamos criar nossos cenários. Crie um projeto de Unit Tests no Visual Studio e adicione um novo item. Com o plugin do SpecFlow instalado irá aparecer um novo formato o SpecFlow Feature File, iremos adicionar este arquivo.

BBD2

Para saber mais sobre o Cucumber, clique aqui
Para saber mais sobre o Gherkin Project, clique aqui

Escrevendo os cenários com o SpecFlow.

Para escrever os cenários utilizaremos o Cucumber, nele será possível criar cenários testáveis no qual qualquer pessoa pode ler e o melhor podemos usar nossa língua mãe o português. Veja na imagem abaixo:

BBD4

 

Criando os Testes Unitários:

Com os cenários já criados, devemos criar nossos testes unitários baseados nos cenários escritos anteriormente. Primeiro temos que instalar o pacote do SpecFlow ao projeto de testes. Ele está disponível via NuGet basta rodar o comando no Package Manager Console Install-Package SpecFlow.MsTest.

Agora basta clicar com o botão direito e escolher a opção Generate Step Definition, o SpecFlow irá gerar nossa classe de teste conforme especificado.

 

using System;
using TechTalk.SpecFlow;

namespace BDD.Tests
{
    [Binding]
    public class RegistroOnlineSteps
    {
        [Given(@"que sou um novo usuário")]
        public void DadoQueSouUmNovoUsuario()
        {
            ScenarioContext.Current.Pending();
        }
        
        [When(@"o eu navegar para a página de cadastro")]
        public void QuandoOEuNavegarParaAPaginaDeCadastro()
        {
            ScenarioContext.Current.Pending();
        }
        
        [When(@"inseri todas as informações do formulário corretas")]
        public void QuandoInseriTodasAsInformacoesDoFormularioCorretas()
        {
            ScenarioContext.Current.Pending();
        }
        
        [When(@"clicar no botão de criar conta")]
        public void QuandoClicarNoBotaoDeCriarConta()
        {
            ScenarioContext.Current.Pending();
        }
        
        [When(@"não inseri as informações de email")]
        public void QuandoNaoInseriAsInformacoesDeEmail()
        {
            ScenarioContext.Current.Pending();
        }
        
        [Then(@"o usuário deve ser redirecionado para a Home Page")]
        public void EntaoOUsuarioDeveSerRedirecionadoParaAHomePage()
        {
            ScenarioContext.Current.Pending();
        }
        
        [Then(@"a pagina de cadastro deve exibir uma mensagem de erro")]
        public void EntaoAPaginaDeCadastroDeveExibirUmaMensagemDeErro()
        {
            ScenarioContext.Current.Pending();
        }
    }
}

 

Utilizando o Selenium WebDriver

Para escrever as validações dos nossos testes unitários usaremos uma biblioteca chamada Selenium (clique aqui para saber mais), essa biblioteca é feita para facilitar os testes de interfaces utilizando os browsers como ferramenta de validação. Com essa biblioteca podemos criar uma instancia de um browser, navegar por páginas e selecionar elementos dentro de uma página. Precisaremos de todos essas funcionalidades para validar os requisitos escritos nos nossos testes.

Vamos adicionar o Selenium utilizando o Package Manager Console. O Selenium está disponível via NuGet então vamos executar o seguinte comando Install-Package Selenium.WebDriver também iremos instalar o suporte ao UI para facilitar a seleção dos elementos da tela utilizando o seguinte comando Install-Package Selenium.Support

Com o Selenium instalado vamos ajustar nossos testes e validar os requisitos, conforme código abaixo.

using System;
using TechTalk.SpecFlow;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Diagnostics;

namespace BDD.Tests
{
    [Binding]
    public class RegistroOnlineSteps
    {
        IWebDriver Browser;

        [BeforeScenario]
        public void CreateWebDriver()
        {
            //Cria a instancia do browser antes de executar os cenarios
            this.Browser = new ChromeDriver();
        }

        [AfterScenario]
        public void CloseWebDriver()
        {
            //Fecha o browser depois que termina os cenarios
            this.Browser.Close();
            this.Browser.Dispose();
        }


        [Given(@"que sou um novo usuário")]
        public void DadoQueSouUmNovoUsuario()
        {
            //Faz Nada
        }
        
        [When(@"o eu navegar para a página de cadastro")]
        public void QuandoOEuNavegarParaAPaginaDeCadastro()
        {
            //Navega para a URL da pagina de Cadastro
            this.Browser.Navigate().GoToUrl("http://localhost:23324/Account/Create");
        }
        
        [When(@"inseri todas as informações do formulário corretas")]
        public void QuandoInseriTodasAsInformacoesDoFormularioCorretas()
        {
            //Pegando os elementos e gerando valores de testes
            var txtNome = this.Browser.FindElement(By.Id("Nome"));
            var txtEmail = this.Browser.FindElement(By.Id("Email"));
            var txtPassword = this.Browser.FindElement(By.Id("Password"));

            //Envia os dados para o formulário
            txtNome.SendKeys("Rafael Cruz");
            txtEmail.SendKeys("teste@teste.com.br");
            txtPassword.SendKeys("123Mudar");
        }
        
        [When(@"clicar no botão de criar conta")]
        public void QuandoClicarNoBotaoDeCriarConta()
        {
            var btnCriarConta = this.Browser.FindElement(By.Id("btnSubmit"));

            //Faz o submit no formulario
            btnCriarConta.Submit();

        }
        
        [When(@"não inseri as informações de email")]
        public void QuandoNaoInseriAsInformacoesDeEmail()
        {
            //Pegando os elementos e gerando valores de testes
            var txtNome = this.Browser.FindElement(By.Id("Nome"));
            var txtPassword = this.Browser.FindElement(By.Id("Password"));

            //Envia os dados para o formulário
            txtNome.SendKeys("Rafael Cruz");
            txtPassword.SendKeys("123Mudar");
        }
        
        [Then(@"o usuário deve ser redirecionado para a Home Page")]
        public void EntaoOUsuarioDeveSerRedirecionadoParaAHomePage()
        {
            Assert.IsTrue(this.Browser.Title == "Home Page - My ASP.NET MVC Application");
        }
        
        [Then(@"a pagina de cadastro deve exibir uma mensagem de erro")]
        public void EntaoAPaginaDeCadastroDeveExibirUmaMensagemDeErro()
        {
            Assert.IsTrue(this.Browser.FindElement(By.XPath("//span[@data-valmsg-for='Email']")).Text == "Email é obrigatório");
        }
    }
}

Com isso nosso teste unitário irá levantar uma instância de um browser, irá navegar até a tela de cadastro e executará os requisitos de negócio conforme especificado no arquivo Feature do SpecFlow

Como podemos ver na imagem abaixo, todos os nossos testes passaram e agora estão verdinhos. =]

BDD6

Dica: Para usar o Chrome, devemos fazer o download do Chrome Driver neste Link 

Com a junção dessas ferramentas conseguimos garantir uma qualidade maior ao nosso software sem contar que podemos colocar em um servidor de integração como Team City ou Team Foundation. Outro ponto importante é que o Cucumber é uma linguagem estruturada não precisando de domínio em informatica ou seja nossos usuários estariam aptos a escrever estórias e nos implementaríamos no nossos testes unitários

Gostaram ? Não deixem de comentar.

Faça download do código clicando aqui

Abs e até a próxima

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *