mcmire-matchy 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -6,16 +6,19 @@ require File.dirname(__FILE__) + '/lib/matchy/version'
6
6
  begin
7
7
  require 'jeweler'
8
8
  Jeweler::Tasks.new do |gem|
9
- gem.version = Matchy::VERSION
9
+ gem.version = Matchy::VERSION::STRING
10
10
  gem.name = "mcmire-matchy"
11
11
  gem.summary = %Q{RSpec-esque matchers for use in Test::Unit}
12
12
  gem.description = %Q{RSpec-esque matchers for use in Test::Unit}
13
13
  gem.email = ["jeremy@entp.com"]
14
- gem.homepage = %q{http://github.com/mcmire/matchy}
14
+ gem.homepage = %q{http://matchy.rubyforge.org}
15
15
  gem.authors = ["Jeremy McAnally"]
16
+ gem.files.exclude ".gitignore", "test/*", "*.gemspec"
16
17
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
18
  end
18
19
  Jeweler::GemcutterTasks.new
20
+
21
+ task :test => :check_dependencies
19
22
  rescue LoadError
20
23
  puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
21
24
  end
@@ -40,16 +43,12 @@ rescue LoadError
40
43
  end
41
44
  end
42
45
 
43
- task :test => :check_dependencies
44
-
45
46
  task :default => :test
46
47
 
47
48
  require 'rake/rdoctask'
48
49
  Rake::RDocTask.new do |rdoc|
49
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
50
-
51
50
  rdoc.rdoc_dir = 'rdoc'
52
- rdoc.title = "mcmire-matchy #{version}"
51
+ rdoc.title = "matchy #{Matchy::VERSION::STRING}"
53
52
  rdoc.rdoc_files.include('README*')
54
53
  rdoc.rdoc_files.include('lib/**/*.rb')
55
54
  end
@@ -1,25 +1,111 @@
1
- $:.unshift(File.dirname(__FILE__)) unless
2
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
1
+ unless defined?(Test::Unit) || defined?(MiniTest)
2
+ raise LoadError, "Matchy couldn't find a testing library! You must require Test::Unit or MiniTest before requiring matchy."
3
+ end
3
4
 
4
- require 'test/unit/assertions'
5
+ # Matchy works with either Test::Unit or MiniTest, on both Ruby 1.8 and >= 1.9.1.
6
+ # Note that Ruby 1.9.0 is NOT supported... but you should really be using 1.9.1 ;)
7
+ module Matchy
8
+ class Adapter < Struct.new(:name, :full_name)
9
+ def on_use; end
10
+ end
11
+
12
+ @@adapters = {}
13
+ @@current_adapter = nil
14
+
15
+ class << self
16
+ def adapter(adapter_name, full_name, &block)
17
+ @@adapters[adapter_name.to_s] = Adapter.new(adapter_name, full_name).extend(Module.new(&block))
18
+ end
19
+ def use(adapter_name)
20
+ adapter_name = adapter_name.to_s
21
+ @@current_adapter = @@adapters[adapter_name] or raise "Couldn't find adapter by name '#{adapter_name}'"
22
+ if ENV["MATCHY_DEBUG"] || $MATCHY_DEBUG
23
+ msg = "\n"
24
+ msg << " -- This is Ruby version #{RUBY_VERSION}, using #{@@current_adapter.full_name}"
25
+ msg << " (MiniTest-Test::Unit shim)" if @@current_adapter.name == :minitest && Matchy.minitest_tu_shim?
26
+ msg << "\n\n"
27
+ print msg
28
+ end
29
+ @@current_adapter.on_use
30
+ Matchy.init
31
+ end
32
+ def adapter_not_found_msg
33
+ "Matchy detected you have a testing library loaded, but it doesn't have an adapter for it. Try these adapters: #{@@adapters.keys.sort.join(", ")}"
34
+ end
35
+ end
36
+
37
+ adapter :minitest, "MiniTest" do
38
+ def assertions_module; MiniTest::Assertions; end
39
+ def test_case_class; MiniTest::Unit::TestCase; end
40
+ def assertion_failed_error; MiniTest::Assertion; end
41
+ def on_use; MiniTest::Unit.autorun; end
42
+ end
43
+ adapter :testunit, "Test::Unit" do
44
+ def assertions_module; Test::Unit::Assertions; end
45
+ def test_case_class; Test::Unit::TestCase; end
46
+ def assertion_failed_error; Test::Unit::AssertionFailedError; end
47
+ end
48
+
49
+ #---
50
+
51
+ class << self
52
+ def minitest_tu_shim?
53
+ defined?(MiniTest) && defined?(MiniTest::Assertions) &&
54
+ defined?(Test::Unit::TestCase) && Test::Unit::TestCase < MiniTest::Assertions
55
+ end
56
+
57
+ def classic?
58
+ defined?(Test::Unit) && defined?(Test::Unit::TestCase) && !minitest_tu_shim?
59
+ end
60
+
61
+ def minitest?
62
+ # We have to decide if we really have a suite of MiniTest tests.
63
+ # Rails for example defines MiniTest, so to only check for
64
+ # defined?(MiniTest) would be malicious
65
+ defined?(MiniTest) && !classic?
66
+ end
67
+
68
+ %w(assertions_module test_case_class assertion_failed_error).each do |method|
69
+ class_eval <<-EOT, __FILE__, __LINE__
70
+ def #{method}
71
+ @@current_adapter ? @@current_adapter.#{method} : raise(LoadError, Matchy.adapter_not_found_msg)
72
+ end
73
+ EOT
74
+ end
75
+
76
+ def init
77
+ require 'matchy/expectation_builder'
78
+ require 'matchy/modals'
79
+ require 'matchy/matcher_builder'
80
+ require 'matchy/custom_matcher'
81
+ require 'matchy/version'
5
82
 
6
- require 'matchy/expectation_builder'
7
- require 'matchy/modals'
8
- require 'matchy/matcher_builder'
9
- require 'matchy/custom_matcher'
10
- require 'matchy/version'
83
+ require 'matchy/built_in/enumerable_expectations'
84
+ require 'matchy/built_in/error_expectations'
85
+ require 'matchy/built_in/truth_expectations'
86
+ require 'matchy/built_in/operator_expectations'
87
+ require 'matchy/built_in/change_expectations'
11
88
 
12
- require 'matchy/built_in/enumerable_expectations'
13
- require 'matchy/built_in/error_expectations'
14
- require 'matchy/built_in/truth_expectations'
15
- require 'matchy/built_in/operator_expectations'
16
- require 'matchy/built_in/change_expectations'
89
+ # Track the current testcase and
90
+ # provide it to the operator matchers.
91
+ Matchy.test_case_class.class_eval do
92
+ alias_method :old_run_method_aliased_by_matchy, :run
93
+ def run(whatever, *args, &block)
94
+ $current_test_case = self
95
+ old_run_method_aliased_by_matchy(whatever, *args, &block)
96
+ end
97
+ end
17
98
 
18
- if Object.const_defined?(:Protest)
19
- Protest::TestCase.send(:include, Matchy::Expectations::TestCaseExtensions)
20
- else
21
- require 'test/unit'
22
- Test::Unit::TestCase.send(:include, Matchy::Expectations::TestCaseExtensions)
99
+ Matchy.test_case_class.send(:include, Matchy::Expectations::TestCaseExtensions)
100
+ Object.send(:include, Matchy::CustomMatcher)
101
+ end
102
+ end
23
103
  end
24
104
 
25
- include Matchy::CustomMatcher
105
+ autodetected_adapter = case
106
+ when Matchy.minitest? then :minitest
107
+ when Matchy.classic? then :testunit
108
+ end
109
+ if autodetected_adapter
110
+ Matchy.use(autodetected_adapter)
111
+ end
@@ -11,21 +11,26 @@ module Matchy
11
11
  def change(&block)
12
12
  build_matcher(:change) do |receiver, matcher, args|
13
13
  before, done, after = block.call, receiver.call, block.call
14
- comparison = after != before
15
- if list = matcher.chained_messages
16
- comparison = case list[0].name
17
- # todo: provide meaningful messages
18
- when :by then (after == before + list[0].args[0] || after == before - list[0].args[0])
19
- when :by_at_least then (after >= before + list[0].args[0] || after <= before - list[0].args[0])
20
- when :by_at_most then (after <= before + list[0].args[0] && after >= before - list[0].args[0])
21
- when :from then (before == list[0].args[0]) && (after == list[1].args[0])
14
+ change_description = ''
15
+ comparison = if list = matcher.chained_messages
16
+ message = list.first
17
+ arg = message.args.first
18
+ name = message.name
19
+ change_description = " #{name.to_s.gsub('_', ' ')} #{arg.inspect}"
20
+ case name
21
+ when :by then (after == before + arg || after == before - arg)
22
+ when :by_at_least then (after >= before + arg || after <= before - arg)
23
+ when :by_at_most then (after <= before + arg && after >= before - arg)
24
+ when :from then (before == arg) && (after == list[1].args[0])
22
25
  end
26
+ else
27
+ after != before
23
28
  end
24
- matcher.positive_failure_message = "given block shouldn't alter the block attached to change"
25
- matcher.negative_failure_message = "given block should alter the block attached to change"
29
+ matcher.positive_failure_message = "given block should alter the given value#{change_description};\n was #{before.inspect},\n now #{after.inspect}"
30
+ matcher.negative_failure_message = "given block should not alter the given value#{change_description};\n was: #{before.inspect},\n now: #{after.inspect}"
26
31
  comparison
27
32
  end
28
33
  end
29
34
  end
30
35
  end
31
- end
36
+ end
@@ -8,7 +8,7 @@ module Matchy
8
8
  # "hello".length.should_not == 2
9
9
  #
10
10
  class OperatorExpectation #< Base
11
- include Test::Unit::Assertions
11
+ include Matchy.assertions_module
12
12
 
13
13
  def initialize(receiver, match)
14
14
  @receiver, @match = receiver, match
@@ -8,7 +8,7 @@ module Matchy
8
8
  end
9
9
 
10
10
  body = lambda do |klass|
11
- include Test::Unit::Assertions
11
+ include Matchy.assertions_module
12
12
  @matcher_name = matcher_name.to_s
13
13
 
14
14
  def self.matcher_name
@@ -1,3 +1,9 @@
1
1
  module Matchy
2
- VERSION = "0.4.2"
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 5
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
3
9
  end
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/test_helper.rb'
2
2
 
3
- class TestChangeExpectations < Test::Unit::TestCase
3
+ class TestChangeExpectations < Matchy.test_case_class
4
4
  def test_change
5
5
  var = 1
6
6
  lambda {var += 1}.should change {var}
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/test_helper.rb'
2
2
 
3
- class TestCustomMatcher < Test::Unit::TestCase
3
+ class TestCustomMatcher < Matchy.test_case_class
4
4
  class Foo < Struct.new(:valid)
5
5
  def valid?
6
6
  valid == true
@@ -110,12 +110,12 @@ class TestCustomMatcher < Test::Unit::TestCase
110
110
  foo.valid = false
111
111
  lambda {
112
112
  foo.should be_valid
113
- }.should raise_error("Expected to be valid but wasn't.")
113
+ }.should raise_error(/^Expected to be valid but wasn't/)
114
114
 
115
115
  foo.valid = true
116
116
  lambda {
117
117
  foo.should_not be_valid
118
- }.should raise_error("Expected to not be valid but was.")
118
+ }.should raise_error(/^Expected to not be valid but was/)
119
119
  end
120
120
 
121
121
  def test_matcher_with_chained_messages
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/test_helper.rb'
2
2
 
3
- class TestEnumerableExpectations < Test::Unit::TestCase
3
+ class TestEnumerableExpectations < Matchy.test_case_class
4
4
  def test_include
5
5
  [1,2,3,4].should include(4)
6
6
  end
@@ -8,7 +8,7 @@ class TestEnumerableExpectations < Test::Unit::TestCase
8
8
  def test_include_fail
9
9
  lambda {
10
10
  [1,2,3,4].should include(6)
11
- }.should raise_error(Test::Unit::AssertionFailedError)
11
+ }.should raise_error(Matchy.assertion_failed_error)
12
12
  end
13
13
 
14
14
  def test_exclude
@@ -18,7 +18,7 @@ class TestEnumerableExpectations < Test::Unit::TestCase
18
18
  def test_exclude_fail
19
19
  lambda {
20
20
  [1,2,3,4].should exclude(4)
21
- }.should raise_error(Test::Unit::AssertionFailedError)
21
+ }.should raise_error(Matchy.assertion_failed_error)
22
22
  end
23
23
 
24
24
  def test_multi_include
@@ -28,7 +28,7 @@ class TestEnumerableExpectations < Test::Unit::TestCase
28
28
  def test_multi_include_fail
29
29
  lambda {
30
30
  [1,2,3,4].should include(6,7,8)
31
- }.should raise_error(Test::Unit::AssertionFailedError)
31
+ }.should raise_error(Matchy.assertion_failed_error)
32
32
  end
33
33
 
34
34
  def test_multi_exclude
@@ -38,7 +38,7 @@ class TestEnumerableExpectations < Test::Unit::TestCase
38
38
  def test_multi_exclude_fail
39
39
  lambda {
40
40
  [1,2,3,4].should exclude(2,3,4)
41
- }.should raise_error(Test::Unit::AssertionFailedError)
41
+ }.should raise_error(Matchy.assertion_failed_error)
42
42
  end
43
43
 
44
44
  def test_negative_include
@@ -48,7 +48,7 @@ class TestEnumerableExpectations < Test::Unit::TestCase
48
48
  def test_negative_include_fail
49
49
  lambda {
50
50
  [1,2,3,4].should_not include(4)
51
- }.should raise_error(Test::Unit::AssertionFailedError)
51
+ }.should raise_error(Matchy.assertion_failed_error)
52
52
  end
53
53
 
54
54
  def test_negative_exclude
@@ -58,7 +58,7 @@ class TestEnumerableExpectations < Test::Unit::TestCase
58
58
  def test_negative_exclude_fail
59
59
  lambda {
60
60
  [1,2,3,4].should_not exclude(6,7)
61
- }.should raise_error(Test::Unit::AssertionFailedError)
61
+ }.should raise_error(Matchy.assertion_failed_error)
62
62
  end
63
63
 
64
64
  def test_include_fail_message
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/test_helper.rb'
2
2
 
3
- class TestErrorExpectations < Test::Unit::TestCase
3
+ class TestErrorExpectations < Matchy.test_case_class
4
4
  def test_raises_error
5
5
  lambda { raise "FAIL" }.should raise_error
6
6
  end
@@ -8,7 +8,7 @@ class TestErrorExpectations < Test::Unit::TestCase
8
8
  def test_raises_error_fail
9
9
  lambda {
10
10
  lambda { "WIN" }.should raise_error
11
- }.should raise_error(Test::Unit::AssertionFailedError)
11
+ }.should raise_error(Matchy.assertion_failed_error)
12
12
  end
13
13
 
14
14
  def test_negative_raises_error
@@ -18,7 +18,7 @@ class TestErrorExpectations < Test::Unit::TestCase
18
18
  def test_negative_raises_error_fail
19
19
  lambda {
20
20
  lambda { raise "FAIL" }.should_not raise_error
21
- }.should raise_error(Test::Unit::AssertionFailedError)
21
+ }.should raise_error(Matchy.assertion_failed_error)
22
22
  end
23
23
 
24
24
  def test_raises_specific_error
@@ -28,13 +28,13 @@ class TestErrorExpectations < Test::Unit::TestCase
28
28
  def test_raises_specific_error_fail_with_no_error
29
29
  lambda {
30
30
  lambda { "WIN" }.should raise_error(TypeError)
31
- }.should raise_error(Test::Unit::AssertionFailedError)
31
+ }.should raise_error(Matchy.assertion_failed_error)
32
32
  end
33
33
 
34
34
  def test_raises_specific_error_fail_with_different_error
35
35
  lambda {
36
36
  lambda { raise StandardError }.should raise_error(TypeError)
37
- }.should raise_error(Test::Unit::AssertionFailedError)
37
+ }.should raise_error(Matchy.assertion_failed_error)
38
38
  end
39
39
 
40
40
  def test_throws_symbol
@@ -48,7 +48,7 @@ class TestErrorExpectations < Test::Unit::TestCase
48
48
  lambda {
49
49
  throw :fail
50
50
  }.should throw_symbol(:win)
51
- }.should raise_error(Test::Unit::AssertionFailedError)
51
+ }.should raise_error(Matchy.assertion_failed_error)
52
52
  end
53
53
 
54
54
  def test_negative_throws_symbol
@@ -63,7 +63,7 @@ class TestErrorExpectations < Test::Unit::TestCase
63
63
  lambda {
64
64
  throw :fail
65
65
  }.should_not throw_symbol(:fail)
66
- }.should raise_error(Test::Unit::AssertionFailedError)
66
+ }.should raise_error(Matchy.assertion_failed_error)
67
67
 
68
68
  end
69
69
 
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/test_helper.rb'
2
2
 
3
- class TestExpectationBuilder < Test::Unit::TestCase
3
+ class TestExpectationBuilder < Matchy.test_case_class
4
4
 
5
5
  def setup
6
6
  @obj = Object.new
@@ -1 +1,87 @@
1
- require File.dirname(__FILE__) + '/../lib/matchy.rb'
1
+ # Here we are ensuring the following cases are easily testable:
2
+ #
3
+ # * Ruby 1.8 with Test::Unit (in standard library)
4
+ # * Ruby 1.8 with MiniTest (gem)
5
+ # * Ruby 1.8 with MiniTest-Test::Unit shim (minitest_tu_shim gem)
6
+ # * Ruby 1.8 with a different test library that uses parts from
7
+ # Test::Unit (e.g. Protest)
8
+ # * Ruby 1.9.1 with MiniTest (in standard library)
9
+ # * Ruby 1.9.1 with Test::Unit (in standard library; acts like a
10
+ # MiniTest-Test::Unit shim)
11
+ # * Ruby 1.9.1 with Test::Unit 1.2.3 (gem)
12
+ # * Ruby 1.9.1 with a different test library that uses parts from
13
+ # Test::Unit (e.g. Protest)
14
+ #
15
+ # Note that Ruby 1.9.0 is NOT supported... but really, who's using
16
+ # that still :)
17
+ #
18
+ # To run through the tests, first go get RVM and install 1.9.1 using
19
+ # that. Then you can just say:
20
+ #
21
+ # rvm use system
22
+ # rake test USING=minitest_tu_shim
23
+ # rake test USING=minitest
24
+ # rake test USING=incompatible
25
+ # rake test (uses test/unit by default)
26
+ #
27
+ # and then:
28
+ #
29
+ # rvm use 1.9.1
30
+ # rake test USING=minitest_tu_shim
31
+ # rake test USING=testunit
32
+ # rake test USING=incompatible
33
+ # rake test (uses minitest/unit by default)
34
+ #
35
+ # References:
36
+ #
37
+ # * http://blog.floehopper.org/articles/2009/02/02/test-unit-and-minitest-with-different-ruby-versions
38
+ #
39
+
40
+ if RUBY_VERSION.to_f < 1.9
41
+ # Ruby 1.8.x
42
+ case ENV["USING"]
43
+ when "minitest_tu_shim"
44
+ require 'rubygems'
45
+ gem 'minitest'
46
+ dir = Config::CONFIG["sitelibdir"]
47
+ unless File.symlink?("#{dir}/minitest") && File.symlink?("#{dir}/test")
48
+ #puts
49
+ #puts " ** To get a true test, you need to run `sudo use_minitest yes` to flip on minitest_tu_shim mode."
50
+ #puts
51
+ #exit 1
52
+ puts "Enabling the shim..."; `sudo use_minitest yes`
53
+ at_exit { puts "Disabling the shim..."; `sudo use_minitest no` }
54
+ end
55
+ require 'test/unit'
56
+ when "minitest"
57
+ require 'rubygems'
58
+ gem 'minitest'
59
+ require 'minitest/unit'
60
+ when "incompatible"
61
+ require 'rubygems'
62
+ gem 'protest'
63
+ require 'protest'
64
+ else
65
+ require 'test/unit'
66
+ end
67
+ else
68
+ # Ruby 1.9.1 and above
69
+ case ENV["USING"]
70
+ when "minitest_tu_shim"
71
+ require 'rbconfig'
72
+ $:.unshift RbConfig::CONFIG['rubylibdir'] # in case you also have test-unit 1.2.3 installed
73
+ require 'test/unit'
74
+ when "testunit"
75
+ gem 'test-unit', "= 1.2.3"
76
+ require 'test/unit'
77
+ when "incompatible"
78
+ gem 'protest'
79
+ require 'protest'
80
+ else
81
+ require 'minitest/unit'
82
+ end
83
+ end
84
+
85
+ $MATCHY_DEBUG = true
86
+
87
+ require 'matchy'