MacSpec 0.3.1
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/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +20 -0
- data/Rakefile +53 -0
- data/lib/mac_spec.rb +59 -0
- data/lib/mac_spec/matcher_system.rb +19 -0
- data/lib/mac_spec/matcher_system/built_in/change_expectations.rb +36 -0
- data/lib/mac_spec/matcher_system/built_in/enumerable_expectations.rb +43 -0
- data/lib/mac_spec/matcher_system/built_in/error_expectations.rb +68 -0
- data/lib/mac_spec/matcher_system/built_in/operator_expectations.rb +45 -0
- data/lib/mac_spec/matcher_system/built_in/truth_expectations.rb +148 -0
- data/lib/mac_spec/matcher_system/core/def_matcher.rb +14 -0
- data/lib/mac_spec/matcher_system/core/exceptions.rb +7 -0
- data/lib/mac_spec/matcher_system/core/expectation_builder.rb +11 -0
- data/lib/mac_spec/matcher_system/core/matcher_builder.rb +53 -0
- data/lib/mac_spec/matcher_system/core/modals.rb +36 -0
- data/lib/mac_spec/mocking_framework.rb +13 -0
- data/lib/mac_spec/mocking_framework/extensions/kernel_extension.rb +14 -0
- data/lib/mac_spec/mocking_framework/extensions/object_extension.rb +74 -0
- data/lib/mac_spec/mocking_framework/message_expectation.rb +127 -0
- data/lib/mac_spec/mocking_framework/mock.rb +20 -0
- data/lib/mac_spec/testing_framework.rb +13 -0
- data/lib/mac_spec/testing_framework/core/functions.rb +26 -0
- data/lib/mac_spec/testing_framework/core/kernel_extension.rb +27 -0
- data/lib/mac_spec/testing_framework/core/test_case_class_methods.rb +90 -0
- data/lib/mac_spec/version.rb +3 -0
- data/test/all.rb +6 -0
- data/test/mac_spec/matcher_system/built_in/change_expectations_test.rb +68 -0
- data/test/mac_spec/matcher_system/built_in/enumerable_expectations_test.rb +91 -0
- data/test/mac_spec/matcher_system/built_in/error_expectations_test.rb +144 -0
- data/test/mac_spec/matcher_system/built_in/operator_expectations_test.rb +136 -0
- data/test/mac_spec/matcher_system/built_in/truth_expectations_test.rb +373 -0
- data/test/mac_spec/matcher_system/core/def_matcher_test.rb +100 -0
- data/test/mac_spec/matcher_system/core/expectation_builder_test.rb +34 -0
- data/test/mac_spec/matcher_system/core/matcher_builder_test.rb +72 -0
- data/test/mac_spec/matcher_system/core/modals_test.rb +39 -0
- data/test/mac_spec/matcher_system/script.rb +29 -0
- data/test/mac_spec/matcher_system/test_helper.rb +2 -0
- data/test/mac_spec/mocking_framework/extensions/kernel_extension_test.rb +37 -0
- data/test/mac_spec/mocking_framework/extensions/object_extension_test.rb +9 -0
- data/test/mac_spec/mocking_framework/message_expectation_test.rb +9 -0
- data/test/mac_spec/mocking_framework/mock_test.rb +9 -0
- data/test/mac_spec/mocking_framework/regression/mocking_class_methods_test.rb +96 -0
- data/test/mac_spec/mocking_framework/regression/negative_expectation_test.rb +33 -0
- data/test/mac_spec/mocking_framework/regression/stub_test.rb +19 -0
- data/test/mac_spec/mocking_framework/test_helper.rb +1 -0
- data/test/mac_spec/test_helper.rb +1 -0
- data/test/mac_spec/testing_framework/performance/x_test_performance.rb +125 -0
- data/test/mac_spec/testing_framework/regression/before_test.rb +32 -0
- data/test/mac_spec/testing_framework/regression/deep_nested_example_groups_test.rb +20 -0
- data/test/mac_spec/testing_framework/regression/description_string_test.rb +13 -0
- data/test/mac_spec/testing_framework/regression/example_name_test.rb +11 -0
- data/test/mac_spec/testing_framework/regression/inherit_not_double_test.rb +39 -0
- data/test/mac_spec/testing_framework/regression/surrounding_module_scope_test.rb +31 -0
- data/test/mac_spec/testing_framework/regression/testing_functions_test.rb +66 -0
- data/test/mac_spec/testing_framework/test_helper.rb +1 -0
- data/test/test_helper.rb +1 -0
- metadata +150 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
module MacSpec
|
2
|
+
module MatcherSystem
|
3
|
+
module DefMatcher
|
4
|
+
include MacSpec::MatcherSystem::MatcherBuilder
|
5
|
+
def def_matcher(matcher_name, &block)
|
6
|
+
Kernel.module_eval do
|
7
|
+
define_method matcher_name do |*args|
|
8
|
+
build_matcher(matcher_name, args, &block)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module MacSpec
|
2
|
+
module MatcherSystem
|
3
|
+
module ExpectationBuilder
|
4
|
+
def self.build_expectation(match, exp, obj)
|
5
|
+
return MacSpec::MatcherSystem::Expectations::OperatorExpectation.new(obj, match) unless exp
|
6
|
+
|
7
|
+
(exp.matches?(obj) != match) ? exp.fail!(match) : exp.pass!(match)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module MacSpec
|
2
|
+
module MatcherSystem
|
3
|
+
module MatcherBuilder
|
4
|
+
def build_matcher(matcher_name=nil, args=[], &block)
|
5
|
+
match_block = lambda do |actual, matcher|
|
6
|
+
block.call(actual, matcher, args)
|
7
|
+
end
|
8
|
+
body = lambda do |klass|
|
9
|
+
include MacSpec.assertions_module
|
10
|
+
@matcher_name = matcher_name.to_s
|
11
|
+
def self.matcher_name
|
12
|
+
@matcher_name
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor :positive_msg, :negative_msg, :msgs
|
16
|
+
alias :positive_failure_message :positive_msg
|
17
|
+
alias :positive_failure_message= :positive_msg=
|
18
|
+
alias :negative_failure_message :negative_msg
|
19
|
+
alias :negative_failure_message= :negative_msg=
|
20
|
+
alias :chained_messages :msgs
|
21
|
+
attr_reader :matcher_name
|
22
|
+
def initialize(match_block, test_case)
|
23
|
+
@match_block, @test_case = match_block, test_case
|
24
|
+
@matcher_name = self.class.matcher_name
|
25
|
+
end
|
26
|
+
|
27
|
+
def method_missing(id, *args, &block)
|
28
|
+
require 'ostruct'
|
29
|
+
(self.msgs ||= []) << OpenStruct.new( "name" => id, "args" => args, "block" => block )
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def matches?(given)
|
34
|
+
@positive_msg ||= "Matching with '#{matcher_name}' failed, although it should match."
|
35
|
+
@negative_msg ||= "Matching with '#{matcher_name}' passed, although it should_not match."
|
36
|
+
@match_block.call(given, self)
|
37
|
+
end
|
38
|
+
|
39
|
+
def fail!(which)
|
40
|
+
@test_case.flunk(which ? failure_message : negative_failure_message)
|
41
|
+
end
|
42
|
+
|
43
|
+
def pass!(which)
|
44
|
+
@test_case.assert true
|
45
|
+
end
|
46
|
+
alias_method :failure_message, :positive_msg
|
47
|
+
alias_method :negative_failure_message, :negative_msg
|
48
|
+
end
|
49
|
+
Class.new(&body).new(match_block, self)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module MacSpec
|
2
|
+
module MatcherSystem
|
3
|
+
module Modals
|
4
|
+
# Tests an expectation against the given object.
|
5
|
+
#
|
6
|
+
# ==== Examples
|
7
|
+
#
|
8
|
+
# "hello".should eql("hello")
|
9
|
+
# 13.should equal(13)
|
10
|
+
# lambda { raise "u r doomed" }.should raise_error
|
11
|
+
#
|
12
|
+
def should(expectation = nil)
|
13
|
+
MacSpec::MatcherSystem::ExpectationBuilder.build_expectation(true, expectation, self)
|
14
|
+
end
|
15
|
+
|
16
|
+
alias :will :should
|
17
|
+
|
18
|
+
# Tests that an expectation doesn't match the given object.
|
19
|
+
#
|
20
|
+
# ==== Examples
|
21
|
+
#
|
22
|
+
# "hello".should_not eql("hi")
|
23
|
+
# 41.should_not equal(13)
|
24
|
+
# lambda { "savd bai da bell" }.should_not raise_error
|
25
|
+
#
|
26
|
+
def should_not(expectation = nil)
|
27
|
+
MacSpec::MatcherSystem::ExpectationBuilder.build_expectation(false, expectation, self)
|
28
|
+
end
|
29
|
+
|
30
|
+
alias :will_not :should_not
|
31
|
+
alias :wont :should_not
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Object.send(:include, MacSpec::MatcherSystem::Modals)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require "mocking_framework/message_expectation"
|
5
|
+
require "mocking_framework/mock"
|
6
|
+
require "mocking_framework/extensions/kernel_extension"
|
7
|
+
require "mocking_framework/extensions/object_extension"
|
8
|
+
|
9
|
+
module MacSpec
|
10
|
+
module MockingFramework
|
11
|
+
# doc
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module MacSpec
|
2
|
+
module MockingFramework
|
3
|
+
module KernelExtension
|
4
|
+
def mock(name, options={})
|
5
|
+
mock_options = {}
|
6
|
+
mock_options[:null_object] = options.delete(:null_object)
|
7
|
+
mock_options[:stubs] = options
|
8
|
+
MacSpec::MockingFramework::Mock.new(name,mock_options)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
Kernel.send(:include, MacSpec::MockingFramework::KernelExtension)
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module MacSpec
|
2
|
+
module MockingFramework
|
3
|
+
module ObjectExtension
|
4
|
+
def should_receive(msg)
|
5
|
+
@__macspec__message_expectations ||= []
|
6
|
+
options = {
|
7
|
+
:receiver => self,
|
8
|
+
:positive => true,
|
9
|
+
:msg => msg,
|
10
|
+
:stub => false
|
11
|
+
}
|
12
|
+
message_expectation = MacSpec::MockingFramework::MessageExpectation.new(options)
|
13
|
+
@__macspec__message_expectations << message_expectation
|
14
|
+
return message_expectation
|
15
|
+
# @__macspec__mock ||= MacSpec::MockingFramework::Mock.new(self.to_s, :belongs_to => self)
|
16
|
+
# __macspec__proxy_service(@__macspec__mock.__add_positive_message_expectation(msg))
|
17
|
+
end
|
18
|
+
|
19
|
+
def should_not_receive(msg)
|
20
|
+
@__macspec__message_expectations ||= []
|
21
|
+
options = {
|
22
|
+
:receiver => self,
|
23
|
+
:positive => false,
|
24
|
+
:msg => msg,
|
25
|
+
:stub => false
|
26
|
+
}
|
27
|
+
message_expectation = MacSpec::MockingFramework::MessageExpectation.new(options)
|
28
|
+
@__macspec__message_expectations << message_expectation
|
29
|
+
return message_expectation
|
30
|
+
end
|
31
|
+
|
32
|
+
def stub!(hash)
|
33
|
+
@__macspec__message_expectations ||= []
|
34
|
+
hash.each do |meth_to_stub, ret_val|
|
35
|
+
options = {
|
36
|
+
:receiver => self,
|
37
|
+
:positive => true,
|
38
|
+
:msg => meth_to_stub,
|
39
|
+
:stub => true,
|
40
|
+
:stub_return_value => ret_val
|
41
|
+
}
|
42
|
+
message_expectation = MacSpec::MockingFramework::MessageExpectation.new(options)
|
43
|
+
@__macspec__message_expectations << message_expectation
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def __macspec__verify
|
48
|
+
begin
|
49
|
+
@__macspec__message_expectations && @__macspec__message_expectations.each do |me|
|
50
|
+
me && me.verify
|
51
|
+
end
|
52
|
+
ensure
|
53
|
+
__macspec__reset!
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def __macspec__reset!
|
58
|
+
@__macspec__message_expectations && @__macspec__message_expectations.each do |me|
|
59
|
+
if respond_to?(me.unique_alias) && respond_to?(me.msg)
|
60
|
+
(class<<self;self;end).instance_eval do
|
61
|
+
undef_method me.msg
|
62
|
+
alias_method me.msg, me.unique_alias
|
63
|
+
undef_method me.unique_alias
|
64
|
+
end
|
65
|
+
else
|
66
|
+
end
|
67
|
+
end
|
68
|
+
@__macspec__message_expectations = nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
Object.send(:include, MacSpec::MockingFramework::ObjectExtension)
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module MacSpec
|
2
|
+
module MockingFramework
|
3
|
+
class MessageExpectation
|
4
|
+
@register = []
|
5
|
+
attr_reader :msg, :return_value, :unique_alias
|
6
|
+
def initialize(options)
|
7
|
+
@receiver = options[:receiver]
|
8
|
+
@msg = options[:msg]
|
9
|
+
@positive = options[:positive]
|
10
|
+
@stub = options[:stub]
|
11
|
+
@stub_return_value = options[:stub_return_value]
|
12
|
+
|
13
|
+
@unique_alias = "__macspec__alias_for_#{@msg}".to_sym
|
14
|
+
me = self
|
15
|
+
if respond_to?(@msg) && !respond_to?(@unique_alias)
|
16
|
+
# todo refactor to singletonclass.instance_eval
|
17
|
+
(class<<@receiver;self;end).send(:alias_method, @unique_alias, @msg)
|
18
|
+
(class<<@receiver;self;end).send(:define_method, @msg) do |*args|
|
19
|
+
received_args = args == [] ? nil : args
|
20
|
+
me.received_with_args!(received_args)
|
21
|
+
me.return_value_for_args(received_args)
|
22
|
+
end
|
23
|
+
elsif !respond_to?(@msg) && !respond_to?(@unique_alias)
|
24
|
+
(class<<@receiver;self;end).send(:define_method, me.msg) do |*args|
|
25
|
+
received_args = args == [] ? nil : args
|
26
|
+
|
27
|
+
me.received_with_args!(received_args)
|
28
|
+
me.return_value_for_args(received_args)
|
29
|
+
end
|
30
|
+
else
|
31
|
+
#
|
32
|
+
end
|
33
|
+
MessageExpectation.register_for_verification(@receiver)
|
34
|
+
@return_value = {}
|
35
|
+
@received = {}
|
36
|
+
@args_expectation = :__macspec_anyargs
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.register_for_verification(obj)
|
40
|
+
@register << obj
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.register
|
44
|
+
@register
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.verify
|
48
|
+
begin
|
49
|
+
@register.uniq.each do |obj|
|
50
|
+
obj && obj.__macspec__verify
|
51
|
+
end
|
52
|
+
ensure
|
53
|
+
@register = []
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def verify
|
58
|
+
unless self.stub?
|
59
|
+
@return_value.each do |args,value|
|
60
|
+
args_string = (args == :__macspec_anyargs) ? "Any Args" : args.inspect
|
61
|
+
if (@received[args] && @positive) || (!@received[args] && !@positive)
|
62
|
+
MacSpec.assert(true)
|
63
|
+
elsif (!@received[args] && @positive)
|
64
|
+
received_with_args_string = if !@received.keys.include?(:__macspec_anyargs)
|
65
|
+
"not at all."
|
66
|
+
else
|
67
|
+
@received.delete(:__macspec_anyargs)
|
68
|
+
"#{@received.keys}"
|
69
|
+
end
|
70
|
+
|
71
|
+
err_msg = """
|
72
|
+
'#{@receiver}' should have received '#{msg}' with '#{args_string}'.
|
73
|
+
But received it #{received_with_args_string}
|
74
|
+
"""
|
75
|
+
MacSpec.flunk err_msg
|
76
|
+
elsif (@received[args] && !@positive)
|
77
|
+
err_msg = "'#{@receiver}' should *not* have received '#{msg}' with '#{args_string}'."
|
78
|
+
MacSpec.flunk err_msg
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
@return_value = {}
|
83
|
+
end
|
84
|
+
|
85
|
+
def stub?
|
86
|
+
@stub
|
87
|
+
end
|
88
|
+
|
89
|
+
def negative?
|
90
|
+
!@positive
|
91
|
+
end
|
92
|
+
|
93
|
+
def received_with_args!(args)
|
94
|
+
@received[args] = true unless args == nil
|
95
|
+
@received[:__macspec_anyargs] = true
|
96
|
+
@return_value[:__macspec_anyargs] ||= true
|
97
|
+
end
|
98
|
+
|
99
|
+
def return_value_for_args(args)
|
100
|
+
return @stub_return_value if stub?
|
101
|
+
args ||= :__macspec_anyargs
|
102
|
+
received_args = @return_value.keys
|
103
|
+
unless received_args.include?(args) || received_args.include?(:__macspec_anyargs)
|
104
|
+
args_string = args == :__macspec_anyargs ? "No Args" : args
|
105
|
+
err_msg = "Wrong Argument(s): '#{args_string}' For message '#{msg}'. Receiver: '#{@receiver}'"
|
106
|
+
MacSpec.flunk err_msg
|
107
|
+
end
|
108
|
+
@return_value[args]
|
109
|
+
end
|
110
|
+
|
111
|
+
def with(*args)
|
112
|
+
unless stub?
|
113
|
+
@args_expectation = args
|
114
|
+
@return_value[@args_expectation] = nil
|
115
|
+
self
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def and_return(value)
|
120
|
+
unless stub? || negative?
|
121
|
+
@return_value[@args_expectation] = value
|
122
|
+
self
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module MacSpec
|
2
|
+
module MockingFramework
|
3
|
+
class Mock
|
4
|
+
def initialize(name, options={})
|
5
|
+
(class<<self;self;end).instance_eval do
|
6
|
+
if options[:null_object]
|
7
|
+
define_method :method_missing do |name, *args, &block|
|
8
|
+
Mock.new(:null_object, :null_object => true)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
options[:stubs] && options[:stubs].each do |stub_method, return_value|
|
12
|
+
define_method stub_method do |*args|
|
13
|
+
return_value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
|
5
|
+
require "testing_framework/core/test_case_class_methods"
|
6
|
+
require "testing_framework/core/kernel_extension"
|
7
|
+
require "testing_framework/core/functions"
|
8
|
+
|
9
|
+
module MacSpec
|
10
|
+
module TestingFramework
|
11
|
+
# todo doc
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module MacSpec
|
2
|
+
module TestingFramework
|
3
|
+
# == Temporary
|
4
|
+
# A temporary module that holds functionality
|
5
|
+
# that awaits to be refactored to the right place.
|
6
|
+
module Functions
|
7
|
+
|
8
|
+
def self.string?(string)
|
9
|
+
string.is_a?(String) ? true : false
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.determine_class_name(name) #:nodoc:
|
13
|
+
name.to_s.split(/\W+/).map { |s| s[0..0].upcase + s[1..-1] }.join
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.make_constantizeable(string)
|
17
|
+
return string unless self.string?(string)
|
18
|
+
string = string.gsub(/[^\w\s]/,"").gsub(/^[\d\s]*/,"")
|
19
|
+
raise ArgumentError.new(
|
20
|
+
"Invalid argument: #{string}. Must not be empty after removing '\W'-class chars."
|
21
|
+
) if string.gsub(/\s/,"").empty?
|
22
|
+
string
|
23
|
+
end
|
24
|
+
end # Functions
|
25
|
+
end # TestingFramework
|
26
|
+
end #MacSpec
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
module Kernel
|
3
|
+
def describe(*args, &block)
|
4
|
+
super_class = (Hash === args.last && (args.last[:type] || args.last[:testcase])) || MacSpec.test_case_class
|
5
|
+
super_class.class_eval {extend MacSpec::TestingFramework::TestCaseClassMethods}
|
6
|
+
cls = Class.new(super_class)
|
7
|
+
cnst, desc = args
|
8
|
+
cnst = MacSpec::TestingFramework::Functions.make_constantizeable(cnst)
|
9
|
+
Object.const_set MacSpec::TestingFramework::Functions::determine_class_name(cnst.to_s + "Test"), cls
|
10
|
+
cls.desc = String === desc ? desc : cnst.to_s
|
11
|
+
if self.class.to_s == "Module"
|
12
|
+
orig_block = block
|
13
|
+
mod_context = self
|
14
|
+
#mods = self.ancestors.select {|m| m.class.to_s == "Module"}
|
15
|
+
block = lambda {include mod_context; instance_eval(&orig_block)}
|
16
|
+
end
|
17
|
+
cls.teardown_chained = lambda {MacSpec::MockingFramework::MessageExpectation.verify}
|
18
|
+
cls.macspec_superclass = super_class
|
19
|
+
cls.class_eval(&block)
|
20
|
+
cls.testcases.each do |testcase|
|
21
|
+
for test in cls.all_tests.reject {|t| testcase.own_tests.include?(t)}
|
22
|
+
testcase.send(:undef_method, test) if testcase.send(:method_defined?, test)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
private :describe
|
27
|
+
end # Kernel
|