Como começar a testar sua aplicação Ruby on Rails com Rspec

Tutoriais - 17/Jun/2020 - por André Kanamura

Testes automatizados são parte integral de aplicações Web. Apresentamos as principais razões porque acreditamos que testes são indispensáveis em desenvolvimento neste artigo. Neste tutorial básico vamos mostrar como você pode começar a aplicar testes na sua aplicação Ruby on Rails usando Rspec. Em nosso exemplo, utilizamos Rails 6 e Rspec Rails 4.

Vamos começar instalando e configurando Rspec Rails seguindo as instruções da ferramenta. Primeiro adicionamos a gem aos grupos :test e :development no Gemfile da sua aplicação:

group :development, :test do
  gem 'rspec-rails', '~> 4.0.0'
end

Depois disso, você vai precisar rodar no diretório da sua aplicação:

$ bundle install

E em seguida:

$ rails generate rspec:install
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb

Feito isso, estamos preparados para começar a escrever nossos testes. O comando acima criou a pasta spec dentro do diretório da aplicação. É lá que vamos colocar os arquivos com testes. Note também que foram criados spec_helper.rb e rails_helper.rb, que são arquivos de configuração do rspec. Não vamos alterá-los no momento, mas é possível modificá-los para adicionarmos funcionalidades à ferramenta.

Existem diferentes tipos de testes quando falamos de desenvolvimento Web. Testes unitários, funcionais, requisição, entre outros. Aqui vamos apresentar um teste simples de usabilidade, que simula as ações de um usuário navegando pela nossa aplicação. No caso do Rails uma gem chamada Capybara fornece ferramentas para ajudar nessa tarefa. Ela já deve ter vindo configurada no Gemfile por padrão, então não é necessário fazer nada a mais para utilizá-la. Caso contrário, você pode seguir as instruções apresentadas na documentação da gem.

Em nosso primeiro teste, vamos implementar um cenário simples em que uma pessoa acessa a Home da nossa aplicação Web. Para isso, dentro do diretório spec vamos criar outro diretório features e dentro dele o arquivo visit_home_spec.rb. Com o intuito de contribuir com a organização e clareza, recomendamos separar os testes em pastas de acordo com sua função. Além disso, se você estiver trabalhando em times, a clareza dos nomes de arquivos e diretórios se torna especialmente importante, para que qualquer pessoa possa entender os testes com facilidade.

Agora dentro do arquivo visit_home_spec.rb vamos começar a implementar o código do teste, primeiro montando a estrutura geral:

require 'rails_helper'

feature 'Visitante acessa home' do
  scenario 'com sucesso' do

  end
end

A primeira linha define a dependência do arquivo de configuração 'rails_helper.rb'. O bloco que começa em 'feature' é onde vamos escrever o código de testes em si. Os termos feature e scenario são na realidade aliases de describe e a função deles é descrever o contexto em que os testes serão realizados. A funcionalidade que vamos procurar testar é descrita em feature, neste caso, o visitante acessa a home da aplicação. Mais especificamente, testaremos o cenário em que o visitante consegue acessar a home com sucesso. Perceba como os termos feature e scenario são semanticamente mais claros que describe, o que é particularmente interessante em testes de usabilidade.

O Rspec em associação ao Capybara oferece uma série de métodos que permitem simular as ações executadas por um pessoa acessando sua aplicação. Com o método visit, por exemplo, simulamos o acesso a uma página específica, já o método fill_in simula o preenchimento de um campo em formulário. Considerando nosso primeiro exemplo em que um visitante acessa a home da aplicação, nosso teste poderia ficar assim:

require 'rails_helper'

feature 'Visitante acessa home' do
  scenario 'com sucesso' do
    visit root_path

    expect(page).to have_content('Boas vindas!')
  end
end

A linha visit root_path define a rota que será visitada, neste caso root_path, que representa a Home da aplicação. Em seguida, definimos as expectativas dessa ação: na página inicial esperamos que exista a frase 'Boas vindas!'. Para isso, implementamos expect(page), que indica o que esperamos da página. No lugar de page, poderíamos incluir qualquer outra variável disponível dentro do escopo do teste. Em testes de requisição, por exemplo, é comum criarmos uma variável response que contém o resultado de uma requisição específica. Neste caso, como esperamos que a página contenha o conteúdo 'Boas vindas!', implementamos o código .to have_content('Boas vindas!'). Também é possível verificar se a página não contém um determinado conteúdo com not_to ou to_not. Existem outros métodos além destes, como é o caso do have_css, que verifica a presença de um marcador HTML específico, por exemplo.

Depois que escrevemos o teste, quando rodamos o comando rspec no terminal, recebemos o seguinte retorno:

$ rspec

Visitante acessa home
  com sucesso (FAILED - 1)

  1) Visitante acessa home com sucesso
    Failure/Error: visit root_path

    NameError:
    undefined local variable or method 'root_path' for #<RSpec::ExampleGroups::VisitorViewsHomePage:0x000055fba258d150>
    # ./spec/features/visit_home_spec.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.001 seconds (files took 0.28912 seconds to load)
1 example, 1 failure

O rspec nos devolve o resultado do código. Veja como as primeiras linhas impressas na tela descrevem o cenário exatamente como o implementamos. Logo em seguida, o rspec mostra a resposta que resulta da execução do teste, neste caso:

Failure/Error: visit root_path

    NameError:
    undefined local variable or method 'root_path' for #<RSpec::ExampleGroups::VisitorViewsHomePage:0x000055fba258d150>

Dessa forma podemos compreender claramente o que precisa ser feito. Neste caso, sabemos que o erro ocorreu ao tentarmos acessar a rota root_path. Por meio da mensagem do erro sabemos que root_path não foi definida, afinal ainda não criamos essa rota na nossa aplicação. Para resolver isso, basta abrir o arquivo de rotas e incluir a linha root to: 'home#index', para criar a root_path. Agora, ao rodarmos o rspec novamente, a mensagem do erro deve mudar, indicando o próximo passo que precisamos tomar. Ao final, resolvendo todos os erros, o teste deve passar:

$ rspec

Finished in 0.001 seconds (files took 0.28912 seconds to load)
1 example, 0 failures

Agora que você entendeu o processo geral, vamos mostrar um exemplo um pouco mais complexo de teste de usabilidade, que simula o preenchimento de um formulário. Vamos considerar que o visitante acessa a home da página, preenche um campo de pesquisa e aperta o botão 'Buscar'. Vamos criar então outro cenário no mesmo arquivo de testes:

require 'rails_helper'

feature 'Visitante acessa home' do
  scenario 'com sucesso' do
    visit root_path

    expect(page).to have_content('Boas vindas!')
  end

  scenario 'e realiza uma pesquisa' do
    visit root_path
    fill_in 'Pesquisa', with: 'Termo para ser pesquisado'
    click_in 'Buscar'

    expect(current_path).to eq(search_path)
    expect(page).to have_content('Um resultado encontrado')
  end
end

Note que o segundo cenário proposto utiliza a mesma descrição de feature que o teste acima dele, porém neste cenário outra característica será testada. Os passos definidos nos testes montam a estrutura esperada na nossa aplicação, neste caso, a Home deve ter um formulário de busca com um botão com nome 'Buscar', que depois de clicado redireciona a navegação para outra página (search_path) onde os resultados serão apresentados. Cada uma das etapas dos testes reflete a forma como a sua aplicação deve funcionar, assim, se seu teste não estiver correto, sua aplicação também não estará. Depois que seus testes automatizados estiverem passando, você pode rodar a aplicação e fazer um teste manual, observando se está tudo funcionando como esperado.

Descrevemos apenas exemplos simples de testes de usabilidade e na documentação do Rspec você vai encontrar detalhes de como implementar todo tipo de teste para as necessidades da sua aplicação. Neste artigo tocamos apenas na superfície do que é o processo real completo de desenvolvimento com testes. O desenvolvimento guiado por testes, ou TDD ("Test Driven Development"), é uma técnica muito mais sofisticada e poderosa do que somos capazes de apresentar em um artigo.

Se você quiser aprender mais sobre testes automatizados com Ruby on Rails, recomendamos a leitura de outros artigos da Campus Code:

Referências

Foto de perfil do autor
André Kanamura

Dev na Campus Code