class MiniTest::Spec

def self.after type = :each, &block

def self.after type = :each, &block
  raise "unsupported after type: #{type}" unless type == :each
  add_teardown_hook {|tc| tc.instance_eval(&block) }
end

def self.before type = :each, &block

def self.before type = :each, &block
  raise "unsupported before type: #{type}" unless type == :each
  add_setup_hook {|tc| tc.instance_eval(&block) }
end

def self.bench name, &block

def self.bench name, &block
  define_method "bench_#{name.gsub(/\W+/, '_')}", &block
end

def self.bench_performance_constant name, threshold = 0.99, &work

def self.bench_performance_constant name, threshold = 0.99, &work
  bench name do
    assert_performance_constant threshold, &work
  end
end

def self.bench_performance_exponential name, threshold = 0.99, &work

def self.bench_performance_exponential name, threshold = 0.99, &work
  bench name do
    assert_performance_exponential threshold, &work
  end
end

def self.bench_performance_linear name, threshold = 0.99, &work

def self.bench_performance_linear name, threshold = 0.99, &work
  bench name do
    assert_performance_linear threshold, &work
  end
end

def self.bench_range &block

def self.bench_range &block
  return super unless block
  meta = (class << self; self; end)
  meta.send :define_method, "bench_range", &block
end

def self.children

def self.children
  @children ||= []
end

def self.create name, desc # :nodoc:

:nodoc:
def self.create name, desc # :nodoc:
  cls = Class.new(self) do
    @name = name
    @desc = desc
    nuke_test_methods!
  end
  children << cls
  cls
end

def self.describe_stack # :nodoc:

:nodoc:
def self.describe_stack # :nodoc:
  @@describe_stack
end

def self.it desc = "anonymous", &block

def self.it desc = "anonymous", &block
  block ||= proc { skip "(no tests defined)" }
  @specs ||= 0
  @specs += 1
  name = "test_%04d_%s" % [ @specs, desc.gsub(/\W+/, '_').downcase ]
  define_method name, &block
  self.children.each do |mod|
    mod.send :undef_method, name if mod.public_method_defined? name
  end
end

def self.let name, &block

def self.let name, &block
  define_method name do
    @_memoized ||= {}
    @_memoized.fetch(name) { |k| @_memoized[k] = instance_eval(&block) }
  end
end

def self.nuke_test_methods! # :nodoc:

:nodoc:
def self.nuke_test_methods! # :nodoc:
  self.public_instance_methods.grep(/^test_/).each do |name|
    self.send :undef_method, name
  end
end

def self.register_spec_type(*args, &block)

def self.register_spec_type(*args, &block)
  if block then
    matcher, klass = block, args.first
  else
    matcher, klass = *args
  end
  TYPES.unshift [matcher, klass]
end

def self.spec_type desc

def self.spec_type desc
  TYPES.find { |matcher, klass|
    if matcher.respond_to? :call then
      matcher.call desc
    else
      matcher === desc.to_s
    end
  }.last
end

def self.subject &block

def self.subject &block
  let :subject, &block
end

def self.to_s # :nodoc:

:nodoc:
def self.to_s # :nodoc:
  defined?(@name) ? @name : super
end

def after_setup

:stopdoc:
def after_setup
  run_setup_hooks
end

def before_teardown

def before_teardown
  run_teardown_hooks
end