Sinatra Tests 101 - MiniTest

Here's the most important thing you need to know about MiniTest: It comes with Ruby. Well, from 1.9.1 upwards at least.

Nevertheless, it's the (mostly drop-in) replacement for the Test::Unit module with support for everything it could accomplish plus benchmarking, mocking, stubbing (you should learn about these terms right now!), and a RSpec-like syntax for expectations.

Let me say that again: everything I just mentioned comes bundled with Ruby so there is no need for you to be adding extra libs, plugins, packages, gems, etc to your project.

Core: minitest/spec

I'm gonna follow the scheme I used in my last post. I know this is probably a lazy choice on my end, but can you really blame me? One more thing: MiniTest has a lot of features but I'm intentionally focusing on MiniTest::Spec so I can provide a simple entrance door to this universe.

And so you can easily change your mindset from RSpec to MiniTest of course!

First of all, go ahead and create a Gemfile for your project...

source 'https://rubygems.org'

gem 'minitest'  
gem 'sinatra'  
gem 'rack'  
gem 'rack-test'  
gem 'guard'  
gem 'guard-minitest'  
gem 'foreman'  

...and get Bundler if you haven't yet so you can

$ bundle install

Like last time, part of the work will be done by the guard-minitest gem. Be sure to check their repo @Github for other available options and usage examples. For now, just run

$ guard init minitest

This time around though, there will be some editing required to your Guardfile. Open it in your favourite text editor, and uncomment the Minitest::Spec lines so it looks like this:

guard :minitest do  
  # with Minitest::Unit
  watch(%r{^test/(.*)\/?test_(.*)\.rb$})
  watch(%r{^lib/(.*/)?([^/]+)\.rb$})     { |m| "test/#{m[1]}test_#{m[2]}.rb" }
  watch(%r{^test/test_helper\.rb$})      { 'test' }

  # with Minitest::Spec
  watch(%r{^spec/(.*)_spec\.rb$})
  watch(%r{^lib/(.+)\.rb$})         { |m| "spec/#{m[1]}_spec.rb" }
  watch(%r{^spec/spec_helper\.rb$}) { 'spec' }

  (...)

end  

And comment change this line

watch(%r{^lib/(.+)\.rb$})         { |m| "spec/#{m[1]}_spec.rb" }  

To look like this

watch(%r{^(.+)\.rb$})         { |m| "spec/#{m[1]}_spec.rb" }  

That little change basically means that we'll be looking at the files in the root of our folder instead of inside a lib folder when we want to check for live changes in files, and says that for every file named X.rb, run spec/X_spec.rb.

Next, we have to get our app up and running, so I got a basic Sinatra file...up and runnning. For this simple exercise I've called it test.rb and placed it in the root folder of the project.

require 'sinatra'

get '/' do  
  'Hello, World!'
end  

Run along and create a spec folder. We're gonna create ourselves a simple spec_helper.rb inside it.

ENV['RACK_ENV'] = 'test'

require 'rack/test'  
require_relative '../test.rb'

include Rack::Test::Methods

def app  
  Sinatra::Application
end

And we're also adding a basic test on a new file. Once again, for the newcomers, pay attention to the filename with _spec.rb since that's important for your Guardfile (and will be handy if you create your own Guard rules in the future!). You don't have to place your tests inside this folder, but keeping them separate from the rest of the code is the way to go about it.

So, lastly, your test_spec.rb should look like

require_relative 'spec_helper.rb'

describe "my example spec" do  
  it "should successfully return a greeting" do
    get '/'
    last_response.body.must_include 'Hello, World!'
  end
end  

That will work for now. To travel the simple path of things, please use The Foreman Foreman and create a Procfile

web: bundle exec ruby test.rb  
guard: bundle exec guard -i  

Go to your Terminal, change to your project directory and run

$ foreman start

Blank Success

Did you see it? Blazing fast testing with a brand new tool? Pat yourself on the back
(as always, for the rest of you...to the corner with debugger)

Optional: minitest/pride

I know we're all good friends and all, but don't you think that was just plain dull? I mean, we got the tests, we got the results, but there's no sense of joy or happiness...what else is missing?

Let me tell you what (from seattlerb)

minitest/pride shows pride in testing and adds coloring to your test output. I guess it is an example of how to write IO pipes too. :P

And with that, add the following to spec_helper.rb

ENV['RACK_ENV'] = 'test'

require 'minitest/pride' # show your pride!  
require 'rack/test'  
require_relative '../test.rb'

include Rack::Test::Methods

def app  
  Sinatra::Application
end  

And witness the power of...colors!

Extra: minitest/benchmark

One more tool I would like to talk about is benchmarking. Ruby itself has a Benchmark module, but who knows, maybe it too will be replaced! In any case, the fact is that you can also use MiniTest to do some benchmarking on your code. Why wouldn't you want to use the same tool?

On your spec_helper.rb, add minitest/benchmark

ENV['RACK_ENV'] = 'test'

require 'minitest/pride'  
require 'minitest/benchmark' # let's do this!  
require 'rack/test'  
require_relative '../test.rb'

include Rack::Test::Methods

def app  
  Sinatra::Application
end  

On your Guardfile edit this line

# OLD: watch(%r{^lib/(.+)\.rb$})         { |m| "spec/#{m[1]}_benchmark.rb" }
watch(%r{^(.+)\.rb$})         { |m| "spec/#{m[1]}_benchmark.rb" }  

And finally, add a test_benchmark.rb file inside your spec folder

require_relative 'spec_helper.rb'

describe "my example Benchmark" do  
  bench_range { bench_exp 1, 10_000 }
  bench_performance_linear "welcome benchmark test", 0.9999 do |n|
    n.times do
      get '/'
      last_response.body.must_include 'Hello, World!'
    end
  end
end  

Of course this is a pointless test and should not be taken into consideration as some kind of superb piece of code in the highest chocolate pedestal of the Coders hall of...sorry, got lost there.

Back to the pedestal terminal, redo your foreman start command and voilá!

And if you took the time to add minitest/pride, in breathtaking & outrageous colors

Benchmark success

When you feel you're ready to follow up on this article, or you just want more goodies on the same topic, Matt Sears | MiniTest Quick Reference seems like a good way to go.

With this setup you can easily start your BDD development without wasting too much time setting up, but you should really get a CI server as soon as your test suite starts growing through the roof and you find yourself with more tests than you can handle.

If, on the other hand, you just want a way to run your tests automatically on your customized Sublime Text/Atom, I find this to be an interesting alternative.

Github Repository

Tiago Casanova

Developer @ Jumpseller. Currently working with Ruby & JavaScript. Curious and creative on a daily basis and works like a chameleon. Loves hoops and cooks.

Subscribe to Binary Lies

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!