Em artigo anterior, mostramos um processo de desenvolvimento utilizando como base uma aplicação Ruby on Rails simples que acessa a Covid19 Brazil API para obter dados de casos da Covid-19 nos estados brasileiros. Utilizamos Ruby 2.7 e Rails 6.0, além do Faraday para lidar com as requisições HTTP. Para fazer nossos testes, utilizamos Rspec puro e agora vamos aproveitar este contexto para mostrar como usar o VCR com o objetivo de melhorar nossos testes.
Nossos testes unitários tentam garantir que o método all
esteja recebendo os dados enviados pela API e retornando um array no formato esperado. No entanto, usamos um stub que simula o recebimento de um json, que neste caso está no arquivo brazil_states_data.json
.
describe StateInfo do
it 'should get all states information' do
json = File.read(Rails.root.join('spec/support/brazil_states_data.json'))
url = 'https://covid19-brazil-api.now.sh/api/report/v1'
echo = double('faraday_response', body: json, status: 200)
allow(Faraday).to receive(:get).with(url).and_return(echo)
result = StateInfo.all
expect(result.length).to eq 3
expect(result[0].uf).to eq 'Rondônia'
expect(result[0].abbreviation).to eq 'RO'
expect(result[0].cases).to eq 0
expect(result[0].deaths).to eq 0
expect(result[0].suspicions).to eq 61
expect(result[1].uf).to eq 'Acre'
expect(result[2].uf).to eq 'Amazonas'
end
Esse stub simula a chamada real para a API e nos devolve sempre o mesmo resultado, extraído de um arquivo JSON apenas por motivos de organização do código. Caso a API mude seu retorno, adicionando ou removendo atributos no JSON por exemplo, nosso teste não é capaz de detectar essa mudança e passamos a ter um falso positivo. Ao publicar nossa aplicação e consumir a API de verdade vamos ter problemas.
A gem VCR é popular na comunidade por automatizar o processo de criação de arquivos com os resultados de uma chamada para API externa e por reaproveitar esses resultados no futuro durante novas execuções dos testes. Vamos instalar e configurar a gem no nosso projeto para entender como ela funciona. Você vai precisar colocar o VCR no Gemfile e instalar com bundle install
.
group :test do
gem 'vcr'
end
Então precisamos adicionar require 'vcr'
ao arquivo de testes e configurar o VCR para o Faraday.
require 'vcr'
VCR.configure do |c|
c.cassette_library_dir = 'spec/vcr'
c.hook_into :faraday
end
Dessa maneira, estamos configurando que o VCR usa o diretório spec/vcr
para salvar arquivos. Você pode incluir esse código no spec_helper.rb
ou no 'rails_helper.rb' para que ele fique disponível em todos os testes. Se você estiver usando Webmock ou Excon, substitua :faraday
por :webmock
ou :excon
. Em seguida podemos substituir toda a configuração da requisição HTTP do stub para usar o VCR:
describe StateInfo do
it 'should get all states information' do
result = VCR.use_cassette('covid') { StateInfo.all }
expect(result.length).to eq 27
expect(result[0].uf).to eq 'São Paulo'
expect(result[0].abbreviation).to eq 'SP'
expect(result[0].cases).to eq 9371
expect(result[0].deaths).to eq 695
expect(result[0].suspicions).to eq 5334
expect(result[1].uf).to eq 'Rio de Janeiro'
expect(result[2].uf).to eq 'Ceará'
end
end
Anteriormente nossos dados eram simulados, mas agora estamos de fato acessando a API e obtendo dados reais. Assim, as expectativas do nosso teste devem mudar. Neste ponto entra a verdadeira vantagem do VCR. Nós poderíamos ter feito nossos testes desde o início de forma que eles acessassem a API diretamente e obtivessem as informações necessárias. No entanto, essas requisições são muito demoradas e a conexão pode falhar, o que poderia acarretar em tempo de processamento muito longo para todo o conjunto de testes da aplicação. Com o intuito de otimizar o trabalho, o VCR grava a primeira resposta e a utiliza quando requerida novamente, tornando os testes muito mais rápidos.
Configurações adicionais do VCR permitem definir a duração do cache das respostas, o que fazer em caso de mudanças na API etc. Dessa forma temos testes que são menos suscetíveis a falsos positivos no futuro.
Em conclusão, o VCR nos ajuda a limpar o código dos nossos testes, além de reduzir muito o tempo de processamento do conjunto de testes da aplicação.