mcmire-matchy 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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'