Skip to content
By Yuji Yokoo

Choosing appropriate tools for the job

In software development, it is easy for developers to sometimes choose tools that are not perfect for the job. This could be because maybe it made sense at that particular time, we were facing a tight deadline, we were not familiar enough with our tools, or a plethora of particular circumstances. It is always beneficial to consider alternatives.

Recently, we have encountered a few situations where using alternatives to our "default" tools improved our project code. The tools that were already in place did the job sufficiently well, but replacing them with simpler ones made more sense in these situations.

Feature specs and view specs

We had a situation where feature specs were overused, and we replaced them with view specs successfully.

In this particular project, we used rspec for each module, and feature specs for integrating the whole lot. In one case, all we were checking was that the message intended for admin users was displayed for admin users, and not regular users.

We were checking the page contents in both cases here, but feature specs actually used real web browsers in a "headless" manner, while view specs simply rendered templates.

The code was like this:

<% if current_user.admin? %>
  <%= @admin_message %>
<% end %>

We had feature specs like these:

feature 'user notifications' do
  scenario 'admin message is not shown' do
    login_as user
    ...
    expect(page).not_to have_content(latest_admin_message)
  end
end

feature 'admin notifications' do
  scenario 'admin message is shown' do
    login_as admin
    ...
    expect(page).to have_content(latest_admin_message)
  end
end

We replaced these with view specs:

context 'user notifications' do
  before do
    allow(user).to receive(:admin?) { false }
  end

  it 'does not show admin message'
    render
    expect(rendered).not_to have_content(latest_admin_message)
  end
end

context 'admin notifications' do
  before do
    allow(user).to receive(:admin?) { true }
  end

  it 'shows admin message' do
    render
    expect(rendered).to have_content(latest_admin_message)
  end
end

Unit tests cannot always replace integration tests, but in this case, this was sufficient for us. In fact, this eliminated many other potential causes of failure that we were not interested in, and the view specs ran much faster.

Another important benefit of this was that it has made the specs more focused and clearer about our intentions.

VCR and Webmock

In a separate situation, the VCR gem was used to capture the remote API response where direct use of Webmock would simplify the code.

If you don't know what VCR does, it lets us "record" web responses to requests, and play it back later so we don't have to access the real remote server every time. It is extremely valuable in testing since it removes the dependency on external services. While it is no replacement for manual, real-world tests, it lets us simulate very closely.

It saves a lot of information in yaml files. This is not all, but it looks like this:

---
http_interactions:
- request:
    method: get
    uri: http://example.com/api/
    body:
      encoding: US-ASCII
      string: ''
    headers:
      Accept-Encoding:
      - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
      Accept:
      - "*/*"
      User-Agent:
      - Ruby
  response:
    status:
      code: 200
      message: OK

and so on.

The problem we had, was that we had tests that used recorded and then modified response files. Let's say we want to test our code against errors, like 500, or 200 with broken JSON contents. These error scenarios should be tested but they are not easy to actually record, since we usually don't (or at least we hope not to) receive a lot of malformed responses or internal server errors from remote services. In our test cases, we had modified response files (or "vcr cassettes") to suit our needs.

Instead of modifying saved response files, we simplified this by using Webmock's stub_request:

stub_request(:any, remote_api_address).to_return { { status: 500, body: '' } }

or:

stub_request(:any, remote_api_address).to_return { { status: 200, body: 'Malformed JSON!' } }

This made our specs a lot easier to read since we did not need all the extra details VCR would save for us in these cases.

One of the major advantages of VCR is the ability to update the input files by recording the updated responses but, we were not interested in that here. This rewrite made it more focused and easier to understand the intentions.

Other gems

Similarly, we have come across situations where it made sense to replace a decorator gem with our own, simpler decorators that did less. There were also some other gems we have removed in the past, like the one that helped us with memoization.

These gems worked well, and they were very good for what they were intended for. However, it does not mean we should use third-party tools just because their functionalities cover what we need.

Summary

Every tool has its advantages and disadvantages. Every time we add a third-party tool, we are accepting all the disadvantages that come with it. Keeping the code simple and free of unnecessary complexity makes it easier to read and maintain.

We should always try to choose the simplest tools that do the job. It'll help us keep things simpler, because simpler code is always easier to work with.

Latest Articles by Our Team

Our expert team of designers and developers love what the do and enjoy sharing their knowledge with the world.

We Hire Only the Best

reinteractive is Australia’s largest dedicated Ruby on Rails development company. We don’t cut corners and we know what we are doing.

We are an organisation made up of amazing individuals and we take pride in our team. We are 100% remote work enabling us to choose the best talent no matter which part of the country they live in. reinteractive is dedicated to making it a great place for any developer to work.

Free Community Workshops

We created the Ruby on Rails InstallFest and Ruby on Rails Development Hub to help introduce new people to software development and to help existing developers hone their skills. These workshops provide invaluable mentorship to train developers, addressing key skills shortages in the industry. Software development is a great career choice for all ages and these events help you get started and skilled up.

  • Webinars

    Webinars

    Webinars are our online portal for tips, tricks and lessons learned in everything we do. Make the most of this free resource to help you become a better developer.

    Learn more about webinars

  • Installfest

    Installfest

    The Ruby on Rails Installfest includes a full setup of your development environment and step-by-step instructions on how to build your first app hosted on Heroku. Over 1,800 attendees to date and counting.

    Learn more about Installfest

  • Development Hub

    Development Hub

    The Ruby on Rails Development Hub is a monthly event where you will get the chance to spend time with our team and others in the community to improve and hone your Ruby on Rails skills.

    Learn more about Development Hub

Get the “reinteractive Review” Monthly Email