Browsed by
Tag: rspec

How to run your feature specs using Capybara and Headless Chrome

How to run your feature specs using Capybara and Headless Chrome

Google has recently announced a way to run the Chrome browser in a headless environment. If you’re using Capybara gem, you can easily start using headless Chrome. Without further ado, let’s do it:

1) Make sure you have one of the following Chrome versions:

  • 57+ on Linux
  • 59+ on macOS
  • 60+ on Windows

(the last one hasn’t been released yet, so you have to use the beta, aka “Canary”)

2) Add (or update) the gem selenium-webdriver;

3) Make sure you’re using ChromeDriver version 2.30 or higher. You can install it by running brew install chromedriver on macOS or apt-get install chromium-chromedriver on Debian/Ubuntu Linux.

4) Add the following driver to your spec_helper.rb or rails_helper.rb:

Capybara.register_driver :chrome do |app|
  Capybara::Selenium::Driver.new app, browser: :chrome,
    options: Selenium::WebDriver::Chrome::Options.new(args: %w[headless disable-gpu])
end

Capybara.javascript_driver = :chrome

Done, enjoy headless Chrome! ᕕ( ᐛ )ᕗ


You might get a warning like the following:

WARN Selenium [DEPRECATION] :args or :switches is deprecated. Use Selenium::WebDriver::Chrome::Options#add_argument instead.

Make sure you don’t have another registered driver, I made this mistake myself and had an iphone driver, which was passing args in the old way and turned out to be the reason why I was getting the warning.

How to test ElasticSearch in a Rails application

How to test ElasticSearch in a Rails application

Since I started using ElasticSearch in my Rails applications, I had a problem to create separate indexes for the automated tests.

The problem is: there is no way to create more than one database in ElasticSearch. You can create different indexes, but no different databases. But creating indexes with different names doesn’t solve the problem: it’s necessary to configure our Rails models in order to work with a different index name when the tests is running.

I’m using the tire and RSpec gems and in this post, I’ll explain how to separate indexes for development and test environments.

First of all, I’ve included the code below in file config/initializers/tire.rb:

if Rails.env.test?
  prefix = "#{Rails.application.class.parent_name.downcase}_#{Rails.env.to_s.downcase}_"
  Tire::Model::Search.index_prefix(prefix)
end

And I set manually the index name in the model (assuming that there is a Movie model):

index_name "#{Tire::Model::Search.index_prefix}movies"

Done! After that, when your application is running in development environment, the name of indexes will be “movies”. But if it’s in the test environment, the name of indexes will be “appname_test_movies” and then the tire gem and your models can perform the search with different indexes!

Deleting test indexes

In order to delete the test indexes after the suite has finished running, just add the following code to file spec/integration_helper.rb (or similar):

RSpec.configure do |config|
  config.after(:all, type: :request) { delete_movie_index }
end

And create a custom macro, which will delete the indexes:

def delete_movie_index
  Movie.index.delete
end

Demo app

I created a small application to demonstrate the technique explained in this post:
https://github.com/lucascaton/elasticsearch_app_example

I hope this has been helpful!

Como debugar testes no RSpec 2

Como debugar testes no RSpec 2

Desde que comecei a usar a versão 2 do RSpec, notei que ao tentar fazer debug em algum teste, ele não configurava automaticamente o “autoeval”. O que problema é que ao adicionar um comando `debugger` no meio do teste, e tentar digitar algo, aparece:

*** Unknown command: ".....".  Try "help".

Bom, a solução para isso, foi criar no meu diretório ~/ (pasta do meu usuário), o arquivo .rdebugrc, com o seguinte conteúdo:

set autoeval
set listsize 12

Pronto! Agora basta chamar os testes passando o parametro -d:

rspec spec/models/users_spec.rb -d
How to test Rails mailers using RSpec

How to test Rails mailers using RSpec

ActionMailer module has been reconstructed in Rails 3 and mailers have their own subdirectory (app/mailers) since then.

This blog post will demostrate how to test them in Rails using RSpec. Assuming that we have a mailer like the following:

class Notifier < ActionMailer::Base
  default from: 'noreply@company.com'

  def instructions(user)
    @name = user.name
    @confirmation_url = confirmation_url(user)
    mail to: user.email, subject: 'Instructions'
  end
end

To send an email through a method from User class:

class User
  def send_instructions
    Notifier.instructions(self).deliver_now
  end
end

Before test it, make sure the config/environments/test.rb file has the following configuration:

Rails.application.configure do
  config.action_mailer.delivery_method = :test
end

It ensures that emails won't be sent, but instead be stored on ActionMailer::Base.deliveries array.

So, in order to create the tests:

spec/models/user_spec.rb

require 'spec_helper'

RSpec.describe User, type: :model do
  subject { create :user }

  it 'sends an email' do
    expect { subject.send_instructions }
      .to change { ActionMailer::Base.deliveries.count }.by(1)
  end
end

spec/mailers/notifier_spec.rb

require 'spec_helper'

RSpec.describe Notifier, type: :mailer do
  describe 'instructions' do
    let(:user) { mock_model User, name: 'Lucas', email: 'lucas@email.com' }
    let(:mail) { described_class.instructions(user).deliver_now }

    it 'renders the subject' do
      expect(mail.subject).to eq('Instructions')
    end

    it 'renders the receiver email' do
      expect(mail.to).to eq([user.email])
    end

    it 'renders the sender email' do
      expect(mail.from).to eq(['noreply@company.com'])
    end

    it 'assigns @name' do
      expect(mail.body.encoded).to match(user.name)
    end

    it 'assigns @confirmation_url' do
      expect(mail.body.encoded)
        .to match("http://aplication_url/#{user.id}/confirmation")
    end
  end
end

Rails allows you to create very comprehensive tests for mailers. Happy coding!