DEV Community

loading...
Cover image for Como configurar ambiente de testes em Ruby on Rails com RSpec

Como configurar ambiente de testes em Ruby on Rails com RSpec

Paulo Melo
Ruby on Rails/Angular developer passionate. I love code and clean logic.
・8 min read

Photo by David Travis on Unsplash

Olá, nesse post eu vou mostrar como configurar o RSpec e demais gems para dar suporte a um ambiente de testes robusto no Ruby on Rails.

Se quiser ver o resultado final das instalações com todos os testes criados, acesse o meu repositório:

GitHub logo peimelo / blog_api

Ruby on Rails 6 course as API showing authentication via devise_token_auth.

Esse post serve para dar apoio ao meu curso de Ruby on Rails 6 - Autenticação via API, que está disponível no YouTube:

Criando o projeto

Vamos criar um novo projeto com banco de dados PostgreSQL e servindo como API (rode no Terminal):

$ rails new blog_api -d postgresql --api -T
Enter fullscreen mode Exit fullscreen mode

Flags:

  • -d postgresql configura o banco PostgreSQL, você pode omitir essa flag caso queira usar o SQLite, que é o banco padrão;
  • --api gera o projeto como API, se omitir essa flag será criado como MVC;
  • -T deixa de gerar os arquivos de testes padrão do Rails que é o Minitest. Caso você já tenha um projeto criado, pode apagar a pasta test.

Adicionando o RSpec

O RSpec é uma opção ao Minitest que vem como padrão no Ruby on Rails. Ele é muito usado e oferece uma sintaxe de fácil compreensão.

Vamos adicionar o RSpec via bundle (ao invés de editar diretamente o Gemfile), porque com esse comando ele adiciona a última versão da gem (rode no Terminal):

$ bundle add rspec-rails -g 'development, test'
Enter fullscreen mode Exit fullscreen mode

Agora rode o comando para criar os arquivos iniciais:

$ rails generate rspec:install
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb
Enter fullscreen mode Exit fullscreen mode

Vamos atualizar o arquivo .rspec para ficar dessa forma:

--require spec_helper
--format documentation
Enter fullscreen mode Exit fullscreen mode

Na primeira linha ele importa o arquivo spec/spec_helper.rb nos testes e o outro comando ele exibe no terminal as mensagens dos testes dessa forma:

Screen Shot 2021-04-18 at 10.01.15

ao invés de pontinhos por arquivo:

Screen Shot 2021-04-13 at 18.20.24

Crie uma pasta chamada support dentro da pasta spec. Agora vamos no arquivo spec/rails_helper.rb e descomente a linha abaixo para que o RSpec importe tudo que estiver dentro da pasta spec/support que vamos precisar mais abaixo nas gems Factory Bot e Database Cleaner:

# ... código existente

Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }

# ... código existente
Enter fullscreen mode Exit fullscreen mode

Adicionando o Shoulda Matchers

O Shoulda Matchers ajuda a fazer alguns testes em apenas uma linha para funcionalidades comuns, que se fossem escritas na mão seriam complexas e sujeitas a erro.

Rode o comando abaixo para adicionar a gem para o group test:

$ bundle add shoulda-matchers -g 'test'
Enter fullscreen mode Exit fullscreen mode

Adicione o código abaixo no final do arquivo spec/rails_helpers.rb e antes do último end:

# ... código existente

  Shoulda::Matchers.configure do |config|
    config.integrate do |with|
      with.test_framework :rspec
      with.library :rails
    end
  end

end # último end do arquivo spec/rails_helpers.rb
Enter fullscreen mode Exit fullscreen mode

Adicionando o SimpleCov

O SimpleCov mostra a cobertura de código dos nossos testes que é um indicador importante.

Rode o comando para adicionar a gem:

$ bundle add simplecov -g 'test'
Enter fullscreen mode Exit fullscreen mode

Vá até o arquivo Gemfile e atualize a linha abaixo para adicionar a instrução de require para false:

# ... código existente

gem "simplecov", "~> 0.21.2", :group => :test, require: false
Enter fullscreen mode Exit fullscreen mode

Vamos configurá-lo no projeto, adicionando desde a primeira linha do arquivo spec/rails_helper.rb o trecho de código abaixo:

require 'simplecov'
SimpleCov.start do
  add_group 'Config', 'config'
  add_group 'Controllers', 'app/controllers'
  add_group 'Libs', 'lib'
  add_group 'Models', 'app/models'
  add_group 'Serializers', 'app/serializers'
  add_group 'Specs', 'spec'
end

# ... resto do código existente
Enter fullscreen mode Exit fullscreen mode

Aqui estamos fazendo o import e iniciando o SimpleCov, porém eu defini grupos para melhorar a visualização do resultado por abas. Se você desejar poderá adicionar/remover grupos. O resultado final ficará parecido com isso:

Screen Shot 2021-04-19 at 19.38.24

Após rodarmos os testes o SimpleCov irá gerar um relatório que ficará na pasta coverage do nosso projeto, porém é desnecessário que ela esteja no controle de versão do GIT, por isso vamos adicionar uma linha no arquivo .gitignore para ignorá-la:

# ... código existente

/coverage
Enter fullscreen mode Exit fullscreen mode

Adicionando o Factory Bot

O Factory Bot facilita a fabricação de dados para testes, podendo ser usada para pegar os atributos com valores, criar uma nova instância ou mesmo salvar no banco de dados. Rode o comando para adicionar a gem:

$ bundle add factory_bot_rails -g 'development, test'
Enter fullscreen mode Exit fullscreen mode

Agora vamos configurar a nossa suite de testes para adicionar os métodos do factory_bot, para isso o arquivo spec/support/factory_bot.rb e cole o trecho abaixo:

RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end
Enter fullscreen mode Exit fullscreen mode

Dessa forma, ao invés de usarmos nos arquivos de teste o comando FactoryBot.build :article, vamos usar apenas build :article.

Adicionando o Faker

O Faker serve para gerar dados fictícios de diversos tipos. Rode o comando para instalar:

$ bundle add faker -g 'development, test'
Enter fullscreen mode Exit fullscreen mode

Adicionando o Database Cleaner

O Database Cleaner apaga os registros do banco de dados de testes antes de rodar os testes. Para instalar:

$ bundle add database_cleaner-active_record -g 'test'
Enter fullscreen mode Exit fullscreen mode

Agora vamos configurar a nossa suite de testes para adicionar os métodos do Database Cleaner, para isso crie o arquivo spec/support/database_cleaner.rb e cole o trecho abaixo:

RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
  end

  config.around(:each) do |example|
    DatabaseCleaner.cleaning do
      example.run
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

Organizando o Gemfile

Como já adicionamos todas as gems necessárias, eu dou uma organizada no Gemfile para cada uma ficar no seu próprio grupo. Conforme dito antes, eu uso o comando bundle add para que ele adicione a versão da gem ao invés de ficar sem nada.

Veja como fica a organização das gems no Gemfile:

# ... código existente

group :development, :test do
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem "factory_bot_rails", "~> 6.1"
  gem "faker", "~> 2.17"
  gem "rspec-rails", "~> 5.0"
end

group :test do
  gem "database_cleaner-active_record", "~> 2.0"
  gem "shoulda-matchers", "~> 4.5"
  gem "simplecov", "~> 0.21.2", require: false
end

# ... código existente
Enter fullscreen mode Exit fullscreen mode

Veja que retirei os trechos :group => :test e :groups => [:development, :test] após cada gem ficar no seu grupo.

Adicionando Helpers

Podemos adicionar métodos para simplificar operações e evitar repetições. Tem um helper que eu uso que serve para acessar a resposta json nos meus testes de requests.

Crie um arquivo chamado spec/support/request_helpers.rb e adicione o conteúdo:

module Request
  module JsonHelpers
    def json_response
      @json_response ||= JSON.parse(response.body, symbolize_names: true)
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

Vamos alterar novamente o arquivo spec/rails_helper.rb para adicionar antes do último end e depois da configuração do Shoulda::Matchers a informação para incluir o Request::JsonHelpers:

# ... código existente

  Shoulda::Matchers.configure do |config|
    config.integrate do |with|
      with.test_framework :rspec
      with.library :rails
    end
  end

  config.include Request::JsonHelpers, type: :request
end # último end do arquivo spec/rails_helpers.rb
Enter fullscreen mode Exit fullscreen mode

Dessa forma, podemos usar o helper nos testes de request como no exemplo abaixo:

# ... código existente

  describe 'GET /index' do
    context 'without logged user' do
      it 'renders two articles from distinct users' do
        article
        article_two

        get api_articles_url, headers: {}, as: :json
        expect(json_response.size).to eq 2
      end
    end
  end

# ... código existente
Enter fullscreen mode Exit fullscreen mode

Integrando tudo

Agora que tudo foi configurado, qualquer comando rails generate irá criar o arquivo de testes correspondente.

Vamos criar um CRUD de Articles para testar apenas o model como exemplo. Rode o comando:

$ rails g scaffold Article title:string body:text
Enter fullscreen mode Exit fullscreen mode

Caso você já tenha um projeto existente e está adicionando os testes nesse momento, segundo a documentação do RSpec, você pode rodar o comando abaixo para criar os arquivos de testes do model:

$ rails g rspec:model Article
      create  spec/models/article_spec.rb
      invoke  factory_bot
      create    spec/factories/articles.rb
Enter fullscreen mode Exit fullscreen mode

Temos que rodar o migrate, tanto para development quanto para test, com os dois comandos:

$ rails db:migrate

$ rails db:migrate RAILS_ENV=test
Enter fullscreen mode Exit fullscreen mode

Geração de dados fictícios

Vamos atualizar o arquivo que gera os dados de Article, edite o arquivo spec/factories/articles.rb:

FactoryBot.define do
  factory :article do
    title { Faker::Lorem.sentence }
    body { Faker::Lorem.paragraph(sentence_count: 10) }
  end
end
Enter fullscreen mode Exit fullscreen mode

Dessa forma o Factory Bot e Faker irão gerar dados fictícios e aleatórios para serem testados quando forem solicitados.

Testando o model Article

Vamos atualizar o arquivo app/models/article.rb para adicionar algumas validações:

class Article < ApplicationRecord
  validates :title, presence: true,
                    length: { minimum: 3 },
                    uniqueness: { case_sensitive: false }
  validates :body, presence: true
end
Enter fullscreen mode Exit fullscreen mode

Agora vamos criar nossos testes modificando o arquivo spec/models/article_spec.rb:

require 'rails_helper'

RSpec.describe Article, type: :model do
  subject(:article) { build :article }

  describe 'validations' do
    it { should validate_presence_of(:title) }
    it { should validate_presence_of(:body) }

    it { should validate_length_of(:title).is_at_least(3) }

    it { should validate_uniqueness_of(:title).case_insensitive }
  end
end
Enter fullscreen mode Exit fullscreen mode

Agora rode no terminal o comando rspec e veja o resultado:

Screen Shot 2021-04-18 at 10.01.15

Percebe que o Shoulda Matchers adiciona o texto referente aos testes e cada teste fica com apenas 1 linha.

Outro resultado do comando rspec é que o SimpleCov vai gerar o relatório de cobertura de testes em coverage\index.html. Dê um duplo clique nesse arquivo no seu gerenciador de arquivos (Windows Explorer/Finder) e veja o resultado:

Screen Shot 2021-04-19 at 19.41.01

Bônus: Teste de integração via GitHub Actions

Eu comecei a usar o GitHub Actions ao invés do CircleCI para rodar meus testes antes de fazer o deploy no Heroku.

Crie o arquivo config/database.ci.yml e cole nele o conteúdo abaixo:

Agora crie as pastas e arquivo .github/workflows/ruby.yml e cole nele o conteúdo abaixo:

Verifique e altere, caso necessário, o nome do seu branch no GitHub e a versão do seu Ruby no arquivo .github/workflows/ruby.yml:

# ... código existente

on:
  push:
    branches: [main] # <= AQUI
  pull_request:
    branches: [main] # <= AQUI

# ... código existente

      - name: Setup Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: 3.0.0 # <= AQUI
          bundler-cache: true

# ... código existente
Enter fullscreen mode Exit fullscreen mode

De agora em diante, ao fazer um push para o GitHub, seu testes irão rodar também no Actions:

Screen Shot 2021-04-20 at 06.39.45

E se tudo ocorrer com sucesso, o deploy será realizado no Heroku, porque eu deixei marcada a opção de Wait for CI to pass before deploy:

Screen Shot 2021-04-20 at 06.51.00

Eu gravei um vídeo sobre isso explicando em detalhes:

Conclusão

Se você chegou até aqui eu te agradeço e parabenizo, porque dessa forma você configurou seu projeto Ruby on Rails para ser seguro e confiante, porque testes são indispensáveis.

Espero que tenham gostado. Um forte abraço.

Discussion (0)