Skip to content

Instantly share code, notes, and snippets.

@mig
Created October 31, 2010 21:28
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mig/657175 to your computer and use it in GitHub Desktop.
Save mig/657175 to your computer and use it in GitHub Desktop.
I want to use minitest in a Rails project with spec like syntax (work in progress)
class Object
cattr_accessor :current_test
end
module Minispec
class TestClass
def self.prepare(desc)
name = name_for_class(desc)
Class.new(base_test_class(name)) do
define_singleton_method(:name) { name }
extend TestMethods
end
end
def self.name_for_class(desc)
(desc.kind_of?(Class) ? desc.to_s : desc_to_class(desc)) + "Test"
end
def self.desc_to_class(desc)
desc.to_s.split(/\W+/).map {|s| s.capitalize}.join
end
def self.base_test_class(name)
case name
when /Controller/
ActionController::TestCase
when /Helper/
ActionView::TestCase
else
ActiveSupport::TestCase
end
end
end
module TestMethods
def describe(desc, &block)
instance_eval(&block)
instance_exec(setups) {|setups| after { setups.pop }}
end
def before(&block)
define_method(:setup) { self.class.setups.each {|s| instance_eval(&s) }}
setups << block
end
def setups
@setups ||= []
end
def after(&block)
define_method(:teardown, &block)
end
def it(name, &block)
define_method("test_#{name.gsub(/\W/, '_')}", &block)
end
end
end
module Kernel
def describe(desc, &block)
klass = Minispec::TestClass.prepare(desc)
klass.class_eval do
def initialize(name)
super
@@current_test = self
end
end
klass.class_eval &block
end
end
class Module
def assertion_map
{
/_operator/ => '_be',
/_includes/ => '_include',
/(#{@assert}_throw)s/ => '\1',
/(?!not)_same/ => '_be_same_as',
/_in_/ => '_be_within_',
/(#{@assert}|#{@refute})_(.*_of|nil|silent|empty)/ => '\1_be_\2',
/#{@assert}_raises/ => '#{@assert}_raise'
}
end
def assertion_skip
/^(#{@assert}|#{@refute})$|##{@assert}_(throw)|#{@assert}_(block|not?_|nothing|raise$)/x
end
def assertion_dont_flip
/(#{@assert}|#{@refute})_(include|respond_to)/
end
def assertion_set
MiniTest::Assertions.public_instance_methods(false).select {|m| m.to_s =~ /^(assert|refute)/}.sort
end
def make_new_assertion(method_name, new_method_name, dont_flip = false)
self.class_eval do
define_method(new_method_name) do |*args|
return current_test.send(method_name.to_sym, *args, &self) if Proc === self
return current_test.send(method_name.to_sym, args.first, self) if args.size == 1 unless !!dont_flip
return current_test.send(method_name.to_sym, self, *args)
end
end
end
def make_new_assertions(assert, refute)
@assert, @refute = assert, refute
assertion_set.each do |method_id|
method_name = method_id.to_s
new_method_name = case method_name
when /^assert/ then method_name.sub(/^assert/, @assert)
when /^refute/ then method_name.sub(/^refute/, @refute)
end
regex, replacement = assertion_map.find {|re, _| new_method_name =~ re}
new_method_name.sub!(regex, replacement) if replacement
make_new_assertion(method_name, new_method_name, new_method_name =~ assertion_dont_flip)
end
end
end
Object.make_new_assertions("should", "should_not")
# Simple example of a functional test
require 'test_helper'
describe PostsController do
before do
@post = posts(:one)
@posts = [@post]
end
describe "on GET to index" do
before { get :index }
it "should assign to @posts" do
assigns(:posts).should_equal @posts
end
end
describe "on GET to show" do
before { get :show, :id => @post.id }
it "should assign to @post" do
assigns(:post).should_equal @post
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment