Last Updated: October 15, 2019
·
1.825K
· hauleth

Make your MiniTest spec sexy as fu**

Today I've started my first Rails project where I'm gonna use MiniTest as testing framework. I sue spec syntax so I ask myself how to make my test super sexy? And this is solution:

module SubjectMatchers
  extend ActiveSupport::Concern

  included do
    alias_method :context, :describe
  end

  MiniTest::Expectations.methods.grep(/^(must|wont)_/).each do |m|
    define_method m do |*args, &block|
      subject.send(m, *args, &block)
    end
  end

  def pending
    skip('Not yet implemented...')
  end

  module ClassMethods
    def subject(name = nil, &block)
      if name
        let(name, &block)
        let(:subject) { send(name) }
      else
        let(:subject, &block)
      end
    end

    def its(name, &block)
      it { subject.send(name).instance_eval(&block) }
    end

    def pending
      it { skip('Not yet implemented...') }
    end
  end
end

ActiveSupport::TestCase.send :include, SubjectMatchers

Some of features:

  • No more subject.must_blabla! From now I can write simply must_blabla and it will be applied to subject by default.
  • You want to fast check that, i.e. model is valid? Instead it { subject.valid?.must_equal true use its(:valid?) { must_equal true }. Nice, isn't it?
  • How many times have you been writing something like this? (which is good practice)

    let(:foo) { Foo.new }
    subject { foo }

    I've had enought this in RSpec. So here we have subject(:foo) { Foo.new }. Kill two birds with one stone and you'll be done.

  • Welcome back good ol' pending.

I hope that this snippet will be useful for you as well.