Usando VCR para melhorar seus testes

Tutoriais - 30/Abr/2020 - por André Kanamura

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.

Foto de perfil do autor
André Kanamura

Dev na Campus Code