crispy 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +150 -0
- data/Rakefile +2 -0
- data/crispy.gemspec +30 -0
- data/lib/crispy.rb +41 -0
- data/lib/crispy/crispy/received_message.rb +25 -0
- data/lib/crispy/crispy_internal/double.rb +25 -0
- data/lib/crispy/crispy_internal/spy.rb +52 -0
- data/lib/crispy/crispy_internal/spy_mixin.rb +37 -0
- data/lib/crispy/crispy_internal/stubber.rb +31 -0
- data/lib/crispy/crispy_internal/with_stubber.rb +22 -0
- data/lib/crispy/version.rb +3 -0
- data/test/doctest-fixtures/your_cool_class.rb +10 -0
- data/test/test_crispy.rb +145 -0
- metadata +134 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ce5cdae0bd61dc34b874f0d39aff7633c43e7418
|
4
|
+
data.tar.gz: 4865b17724178158276ea6e1134fd614e1cdffb8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e42a8e7746d256b99f4f9fa07ae84f55a154cce1c41a55a41812736249e2b5a49483eeff86d7315de0abd502ad4996ce455605c9283469a400510b81429fa7c3
|
7
|
+
data.tar.gz: a0b29456ff5b7a4b993716c3fbebce7b6c0d71fa1cbc0e8f4ec58cfa5d70448306bb464d8eaf782b3c4d801a6ac2a4fc3595990d62ecfe07fb4a1d0558fc0ad5
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Yamamoto Yuji
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
# Crispy
|
2
|
+
|
3
|
+
Test Spy for Any Object in Ruby.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
- Test spy for any object by using `prepend` (Sorry, it runs by Ruby 2.0 or higher!)
|
8
|
+
- Extremely flexible query for received messages with `received_messages` method.
|
9
|
+
- By using Array and Enumerable's methods, you never have to remember the complex API and tons of the argument matchers in RSpec anymore!
|
10
|
+
- Makes mocks obsolete so you don't have to be worried about where to put the expectations (i.e. *before or after the subject method*).
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
gem 'crispy'
|
17
|
+
|
18
|
+
And then execute:
|
19
|
+
|
20
|
+
$ bundle
|
21
|
+
|
22
|
+
Or install it yourself as:
|
23
|
+
|
24
|
+
$ gem install crispy
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
|
28
|
+
<!--
|
29
|
+
# Sample class for doctest.
|
30
|
+
doctest_require: './test/doctest-fixtures/your_cool_class.rb'
|
31
|
+
-->
|
32
|
+
|
33
|
+
### Spy on a Object
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
>> require 'crispy'
|
37
|
+
>> include Crispy # import spy, spy_into and any other functions from Crispy namespace.
|
38
|
+
|
39
|
+
>> object = YourCoolClass.new
|
40
|
+
>> spy = spy_into object
|
41
|
+
|
42
|
+
>> object.your_cool_method 1, 2, 3
|
43
|
+
>> object.your_method_without_argument
|
44
|
+
>> object.your_lovely_method 'great', 'arguments'
|
45
|
+
>> object.your_lovely_method 'great', 'arguments', 'again'
|
46
|
+
>> object.your_finalizer 'resource to release'
|
47
|
+
```
|
48
|
+
|
49
|
+
#### Spy methods with no arguments
|
50
|
+
|
51
|
+
Call query methods through the spy object, instead of YourCoolClass's instance.
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
>> spy(object).received? :your_cool_method
|
55
|
+
=> true
|
56
|
+
>> spy(object).received? :your_method_without_argument
|
57
|
+
=> true
|
58
|
+
>> spy(object).received? :your_lovely_method
|
59
|
+
=> true
|
60
|
+
>> spy(object).received? :your_ugly_method
|
61
|
+
=> false
|
62
|
+
```
|
63
|
+
|
64
|
+
#### Spy methods with arguments
|
65
|
+
|
66
|
+
Each argument is compared by `==` method.
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
>> spy(object).received? :your_cool_method, 1, 2, 3
|
70
|
+
=> true
|
71
|
+
>> spy(object).received? :your_cool_method, 0, 0, 0
|
72
|
+
=> false
|
73
|
+
>> spy(object).received? :your_method_without_argument, :not, :given, :arguments
|
74
|
+
=> false
|
75
|
+
>> spy(object).received? :your_lovely_method, 'great', 'arguments'
|
76
|
+
=> true
|
77
|
+
>> spy(object).received? :your_ugly_method, 'of course', 'I gave no arguments'
|
78
|
+
=> false
|
79
|
+
```
|
80
|
+
|
81
|
+
#### Spy methods with arguments and a block
|
82
|
+
|
83
|
+
*Sorry, I'm still thinking of the specification for that case.*
|
84
|
+
|
85
|
+
#### Count method calls
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
>> spy(object).count_received :your_cool_method
|
89
|
+
=> 1
|
90
|
+
>> spy(object).count_received :your_cool_method, 1, 2, 3
|
91
|
+
=> 1
|
92
|
+
>> spy(object).count_received :your_cool_method, 0, 0, 0
|
93
|
+
=> 0
|
94
|
+
```
|
95
|
+
|
96
|
+
#### Get more detailed log
|
97
|
+
|
98
|
+
You can check arbitrary received methods with the familliar Array's (and of course including Enumerable's!) methods such as `any?`, `all`, `first`, `[]`, `index`.
|
99
|
+
Because `spy(object).received_messages` returns an array of `Crispy::ReceivedMessage` instances.
|
100
|
+
**You don't have to remember the tons of matchers for received arguments any more!!**
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
>>
|
104
|
+
spy(object).received_messages.any? do|m|
|
105
|
+
m.method_name == :your_cool_method && m.arguments.all? {|arg| arg.is_a? Integer }
|
106
|
+
end
|
107
|
+
=> true
|
108
|
+
|
109
|
+
>> last_method_call = spy(object).received_messages.last
|
110
|
+
>>
|
111
|
+
last_method_call.method_name == :your_finalizer &&
|
112
|
+
last_method_call.arguments == ['resource to release']
|
113
|
+
=> true
|
114
|
+
```
|
115
|
+
|
116
|
+
### Stub Methods of a Spy
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
>> spy(object).stub(:your_cool_method, 'Awesome!')
|
120
|
+
>> object.your_cool_method
|
121
|
+
=> "Awesome!"
|
122
|
+
|
123
|
+
>> spy(object).stub(your_lovely_method: 'I love this method!', your_finalizer: 'Finalized!')
|
124
|
+
>> object.your_lovely_method
|
125
|
+
=> "I love this method!"
|
126
|
+
>> object.your_finalizer
|
127
|
+
=> "Finalized!"
|
128
|
+
```
|
129
|
+
|
130
|
+
### Stub Methods of a Double
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
>> your_awesome_double = double('your awesome double', nice!: '+1!', sexy?: true)
|
134
|
+
>> your_awesome_double.nice!
|
135
|
+
=> "+1!"
|
136
|
+
>> your_awesome_double.sexy?
|
137
|
+
=> true
|
138
|
+
|
139
|
+
>> your_awesome_double.stub(:another_method, 'can be stubbed.')
|
140
|
+
>> your_awesome_double.another_method
|
141
|
+
=> "can be stubbed."
|
142
|
+
```
|
143
|
+
|
144
|
+
## Contributing
|
145
|
+
|
146
|
+
1. Fork it ( https://github.com/igrep/crispy/fork )
|
147
|
+
2. Create your feature branch (`git checkout -b your-new-feature`)
|
148
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
149
|
+
4. Push to the branch (`git push origin your-new-feature`)
|
150
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/crispy.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'crispy/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "crispy"
|
7
|
+
spec.version = Crispy::VERSION
|
8
|
+
spec.authors = ["Yamamoto Yuji"]
|
9
|
+
spec.email = ["whosekiteneverfly@gmail.com"]
|
10
|
+
spec.summary = %q{Test spy for any object in Ruby.}
|
11
|
+
spec.description =
|
12
|
+
"Test spy for any object in Ruby.\n" \
|
13
|
+
"It makes mocks obsolete so you don't have to be worried about " \
|
14
|
+
"where to put the expectations (i.e. before or after the subject method)."
|
15
|
+
spec.homepage = "https://github.com/igrep/crispy"
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0")
|
19
|
+
spec.executables = []
|
20
|
+
spec.test_files = spec.files.grep(%r{^test/})
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "minitest", "~> 5.4"
|
26
|
+
spec.add_development_dependency "pry"
|
27
|
+
spec.add_development_dependency "rubydoctest"
|
28
|
+
|
29
|
+
spec.required_ruby_version = '>= 2.0'
|
30
|
+
end
|
data/lib/crispy.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require "crispy/version"
|
2
|
+
require "crispy/crispy_internal/spy"
|
3
|
+
require "crispy/crispy_internal/double"
|
4
|
+
|
5
|
+
module Crispy
|
6
|
+
# All methods of this module should be module_function.
|
7
|
+
module_function
|
8
|
+
|
9
|
+
# Returns a Spy object to wrap all methods of the object.
|
10
|
+
def spy_into object, stubs_map = {}
|
11
|
+
::Crispy::CrispyInternal::Spy.new object, stubs_map
|
12
|
+
end
|
13
|
+
|
14
|
+
def double name_or_stubs_map = nil, stubs_map = {}
|
15
|
+
::Crispy::CrispyInternal::Double.new name_or_stubs_map, stubs_map
|
16
|
+
end
|
17
|
+
|
18
|
+
# Make and returns a Crispy::ClassSpy's instance to spy all instances of a class.
|
19
|
+
def spy_on_any_instance_of klass
|
20
|
+
raise NotImplementedError, "Sorry, this feature is under construction :("
|
21
|
+
::Crispy::CrispyInternal::ClassSpy.new klass
|
22
|
+
end
|
23
|
+
|
24
|
+
def spy object
|
25
|
+
object.__CRISPY_SPY__
|
26
|
+
end
|
27
|
+
|
28
|
+
# Begins to log all instances and its received messages of a class.
|
29
|
+
# _NOTE_: replace the constant containing the class
|
30
|
+
def spy_into_class! klass
|
31
|
+
raise NotImplementedError, "Sorry, this feature is under construction :("
|
32
|
+
spy_class = spy_on_any_instance_of klass
|
33
|
+
stub_const! klass.name, spy_class
|
34
|
+
spy_class
|
35
|
+
end
|
36
|
+
|
37
|
+
def stub_const! const_name, value
|
38
|
+
raise NotImplementedError, "Sorry, this feature is under construction :("
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Crispy
|
2
|
+
module Crispy
|
3
|
+
class ReceivedMessage
|
4
|
+
|
5
|
+
attr_reader :method_name, :arguments, :attached_block
|
6
|
+
|
7
|
+
class << self
|
8
|
+
alias [] new
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize method_name, *arguments, &attached_block
|
12
|
+
@method_name = method_name
|
13
|
+
@arguments = arguments
|
14
|
+
@attached_block = attached_block
|
15
|
+
end
|
16
|
+
|
17
|
+
def == other
|
18
|
+
@method_name == other.method_name &&
|
19
|
+
@arguments == other.arguments &&
|
20
|
+
@attached_block == other.attached_block
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'crispy/crispy_internal/with_stubber'
|
2
|
+
|
3
|
+
module Crispy
|
4
|
+
module CrispyInternal
|
5
|
+
class Double
|
6
|
+
include WithStubber
|
7
|
+
|
8
|
+
def initialize name_or_stubs_map = nil, stubs_map = {}
|
9
|
+
if name_or_stubs_map.is_a? ::Hash
|
10
|
+
@name = ''.freeze
|
11
|
+
initialize_stubber(name_or_stubs_map)
|
12
|
+
else
|
13
|
+
@name = name_or_stubs_map
|
14
|
+
initialize_stubber(stubs_map)
|
15
|
+
end
|
16
|
+
singleton_class =
|
17
|
+
class << self
|
18
|
+
self
|
19
|
+
end
|
20
|
+
prepend_stubber singleton_class
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'crispy/crispy/received_message'
|
2
|
+
require 'crispy/crispy_internal/spy_mixin'
|
3
|
+
require 'crispy/crispy_internal/with_stubber'
|
4
|
+
|
5
|
+
module Crispy
|
6
|
+
module CrispyInternal
|
7
|
+
class Spy < ::Module
|
8
|
+
include SpyMixin
|
9
|
+
include WithStubber
|
10
|
+
|
11
|
+
def initialize target, stubs_map = {}
|
12
|
+
super()
|
13
|
+
@received_messages = []
|
14
|
+
singleton_class =
|
15
|
+
class << target
|
16
|
+
self
|
17
|
+
end
|
18
|
+
initialize_stubber stubs_map
|
19
|
+
prepend_stubber singleton_class
|
20
|
+
|
21
|
+
prepend_features singleton_class
|
22
|
+
target.__CRISPY_SPY__ = self
|
23
|
+
end
|
24
|
+
|
25
|
+
def prepend_features klass
|
26
|
+
super
|
27
|
+
klass.public_instance_methods.each do|method_name|
|
28
|
+
self.module_eval { public define_wrapper(method_name) }
|
29
|
+
end
|
30
|
+
klass.protected_instance_methods.each do|method_name|
|
31
|
+
self.module_eval { protected define_wrapper(method_name) }
|
32
|
+
end
|
33
|
+
klass.private_instance_methods.each do|method_name|
|
34
|
+
self.module_eval { private define_wrapper(method_name) }
|
35
|
+
end
|
36
|
+
|
37
|
+
# define accessor after prepending to avoid to spy unexpectedly.
|
38
|
+
module_eval { attr_accessor :__CRISPY_SPY__ }
|
39
|
+
end
|
40
|
+
|
41
|
+
private def define_wrapper method_name
|
42
|
+
define_method method_name do|*arguments, &attached_block|
|
43
|
+
@__CRISPY_SPY__.received_messages <<
|
44
|
+
::Crispy::Crispy::ReceivedMessage.new(method_name, *arguments, &attached_block)
|
45
|
+
super(*arguments, &attached_block)
|
46
|
+
end
|
47
|
+
method_name
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'crispy/crispy/received_message'
|
2
|
+
|
3
|
+
module Crispy
|
4
|
+
module CrispyInternal
|
5
|
+
module SpyMixin
|
6
|
+
|
7
|
+
attr_reader :received_messages
|
8
|
+
|
9
|
+
def received? method_name, *arguments, &attached_block
|
10
|
+
if arguments.empty? and attached_block.nil?
|
11
|
+
@received_messages.map(&:method_name).include? method_name
|
12
|
+
else
|
13
|
+
@received_messages.include? ::Crispy::Crispy::ReceivedMessage.new(method_name, *arguments, &attached_block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def received_once? method_name, *arguments, &attached_block
|
18
|
+
if arguments.empty? and attached_block.nil?
|
19
|
+
@received_messages.map(&:method_name).one? {|self_method_name| self_method_name == method_name }
|
20
|
+
else
|
21
|
+
@received_messages.one? do |self_received_message|
|
22
|
+
self_received_message == ::Crispy::Crispy::ReceivedMessage.new(method_name, *arguments, &attached_block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def count_received method_name, *arguments, &attached_block
|
28
|
+
if arguments.empty? and attached_block.nil?
|
29
|
+
@received_messages.map(&:method_name).count method_name
|
30
|
+
else
|
31
|
+
@received_messages.count ::Crispy::Crispy::ReceivedMessage.new(method_name, *arguments, &attached_block)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Crispy
|
2
|
+
module CrispyInternal
|
3
|
+
class Stubber < Module
|
4
|
+
public :prepend_features
|
5
|
+
|
6
|
+
def initialize stubs_map = {}
|
7
|
+
super()
|
8
|
+
stub stubs_map
|
9
|
+
end
|
10
|
+
|
11
|
+
NOT_SPECIFIED = ::Object.new
|
12
|
+
|
13
|
+
def stub method_name_or_hash, returned_value = NOT_SPECIFIED, &definition
|
14
|
+
case method_name_or_hash
|
15
|
+
when Hash
|
16
|
+
hash = method_name_or_hash
|
17
|
+
hash.each do|method_name, value|
|
18
|
+
stub method_name, value
|
19
|
+
end
|
20
|
+
when ::Symbol, ::String
|
21
|
+
self.module_exec method_name_or_hash do|method_name|
|
22
|
+
# TODO: should not ignore arguments?
|
23
|
+
define_method(method_name) {|*_arguments| returned_value }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'crispy/crispy_internal/stubber'
|
2
|
+
|
3
|
+
module Crispy
|
4
|
+
module CrispyInternal
|
5
|
+
module WithStubber
|
6
|
+
|
7
|
+
private def initialize_stubber stubs_map = {}
|
8
|
+
@__CRISPY_STUBBER__ = Stubber.new(stubs_map)
|
9
|
+
end
|
10
|
+
|
11
|
+
private def prepend_stubber klass
|
12
|
+
@__CRISPY_STUBBER__.prepend_features klass
|
13
|
+
end
|
14
|
+
|
15
|
+
def stub *arguments, &definition
|
16
|
+
@__CRISPY_STUBBER__.stub(*arguments, &definition)
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/test/test_crispy.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
$VERBOSE = true # enable warnings
|
2
|
+
|
3
|
+
require 'crispy'
|
4
|
+
require 'minitest/autorun'
|
5
|
+
|
6
|
+
class TestCrispy < MiniTest::Test
|
7
|
+
include ::Crispy
|
8
|
+
|
9
|
+
# Inherit BasicObject because it has fewer meta-programming methods than Object
|
10
|
+
class ObjectClass < BasicObject
|
11
|
+
def hoge a, b, c
|
12
|
+
private_foo a
|
13
|
+
[a, b, c]
|
14
|
+
end
|
15
|
+
def foo
|
16
|
+
123
|
17
|
+
end
|
18
|
+
def bar
|
19
|
+
[]
|
20
|
+
end
|
21
|
+
def method_to_stub1
|
22
|
+
fail "Not stubbed actually! The test fails."
|
23
|
+
end
|
24
|
+
def method_to_stub2
|
25
|
+
fail "Not stubbed actually! The test fails."
|
26
|
+
end
|
27
|
+
|
28
|
+
private def private_foo a
|
29
|
+
:private_foo
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class TestCrispySpyInto < TestCrispy
|
34
|
+
|
35
|
+
def setup
|
36
|
+
@object = ObjectClass.new
|
37
|
+
|
38
|
+
@returned_spy = spy_into(
|
39
|
+
@object, method_to_stub1: :stubbed1, method_to_stub2: :stubbed2
|
40
|
+
)
|
41
|
+
|
42
|
+
@object.hoge 1, 2, 3
|
43
|
+
@object.foo
|
44
|
+
@object.hoge 3, 4, 5
|
45
|
+
|
46
|
+
@subject = spy(@object)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_spy_logs_messages_sent_to_an_object
|
50
|
+
assert_equal(
|
51
|
+
[
|
52
|
+
Crispy::ReceivedMessage[:hoge, 1, 2, 3],
|
53
|
+
Crispy::ReceivedMessage[:private_foo, 1],
|
54
|
+
Crispy::ReceivedMessage[:foo],
|
55
|
+
Crispy::ReceivedMessage[:hoge, 3, 4, 5],
|
56
|
+
Crispy::ReceivedMessage[:private_foo, 3],
|
57
|
+
],
|
58
|
+
@subject.received_messages
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_spy_has_received_messages_sent_to_an_object
|
63
|
+
assert @subject.received?(:hoge)
|
64
|
+
assert @subject.received?(:foo)
|
65
|
+
assert not(@subject.received?(:bar))
|
66
|
+
assert @subject.received?(:private_foo)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_spy_has_received_messages_with_arguments_sent_to_an_object
|
70
|
+
assert @subject.received?(:hoge, 1, 2, 3)
|
71
|
+
assert @subject.received?(:hoge, 3, 4, 5)
|
72
|
+
assert @subject.received?(:private_foo, 1)
|
73
|
+
assert @subject.received?(:private_foo, 3)
|
74
|
+
assert not(@subject.received?(:hoge, 0, 0, 0))
|
75
|
+
assert not(@subject.received?(:private_foo, 0, 0, 0))
|
76
|
+
assert not(@subject.received?(:foo, 1))
|
77
|
+
assert not(@subject.received?(:bar, nil))
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_spy_has_received_messages_once_sent_to_an_object
|
81
|
+
assert not(@subject.received_once?(:hoge))
|
82
|
+
assert not(@subject.received_once?(:private_foo))
|
83
|
+
assert @subject.received_once?(:hoge, 3, 4, 5)
|
84
|
+
assert @subject.received_once?(:private_foo, 3)
|
85
|
+
assert not(@subject.received_once?(:private_foo, 3, 4))
|
86
|
+
assert @subject.received_once?(:foo)
|
87
|
+
assert not(@subject.received_once?(:bar))
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_spy_counts_received_messages_sent_to_an_object
|
91
|
+
assert_equal(1, @subject.count_received(:hoge, 1, 2, 3))
|
92
|
+
assert_equal(1, @subject.count_received(:hoge, 3, 4, 5))
|
93
|
+
assert_equal(0, @subject.count_received(:hoge, 0, 0, 0))
|
94
|
+
assert_equal(2, @subject.count_received(:hoge))
|
95
|
+
|
96
|
+
assert_equal(1, @subject.count_received(:private_foo, 1))
|
97
|
+
assert_equal(1, @subject.count_received(:private_foo, 3))
|
98
|
+
assert_equal(0, @subject.count_received(:private_foo, 0))
|
99
|
+
assert_equal(2, @subject.count_received(:private_foo))
|
100
|
+
|
101
|
+
assert_equal(1, @subject.count_received(:foo))
|
102
|
+
assert_equal(0, @subject.count_received(:bar))
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_spy_changes_stubbed_method
|
106
|
+
assert_equal(:stubbed1, @object.method_to_stub1)
|
107
|
+
assert_equal(:stubbed2, @object.method_to_stub2)
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_spy_is_also_returned_by_spy_into_method
|
111
|
+
assert_same @subject, @returned_spy
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
class TestCrispyDouble < TestCrispy
|
117
|
+
def setup
|
118
|
+
@expected_hoge = Object.new
|
119
|
+
@expected_foo = Object.new
|
120
|
+
@expected_bar = Object.new
|
121
|
+
@expected_baz = Object.new
|
122
|
+
|
123
|
+
@double = double('some double', hoge: @expected_hoge, foo: @expected_foo)
|
124
|
+
@double.stub(bar: @expected_bar, baz: @expected_baz)
|
125
|
+
|
126
|
+
@actual_hoge1 = @double.hoge :with, :any, :arguments do
|
127
|
+
'and a block'
|
128
|
+
end
|
129
|
+
@actual_hoge2 = @double.hoge
|
130
|
+
@actual_foo = @double.foo
|
131
|
+
@actual_bar = @double.bar
|
132
|
+
@actual_baz = @double.baz
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_double_can_stub_specified_methods
|
136
|
+
assert_same @expected_hoge, @actual_hoge1
|
137
|
+
assert_same @expected_hoge, @actual_hoge2
|
138
|
+
assert_same @expected_foo, @actual_foo
|
139
|
+
assert_same @expected_bar, @actual_bar
|
140
|
+
assert_same @expected_baz, @actual_baz
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
metadata
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: crispy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Yamamoto Yuji
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-08-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.4'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.4'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubydoctest
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: |-
|
84
|
+
Test spy for any object in Ruby.
|
85
|
+
It makes mocks obsolete so you don't have to be worried about where to put the expectations (i.e. before or after the subject method).
|
86
|
+
email:
|
87
|
+
- whosekiteneverfly@gmail.com
|
88
|
+
executables: []
|
89
|
+
extensions: []
|
90
|
+
extra_rdoc_files: []
|
91
|
+
files:
|
92
|
+
- ".gitignore"
|
93
|
+
- Gemfile
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- crispy.gemspec
|
98
|
+
- lib/crispy.rb
|
99
|
+
- lib/crispy/crispy/received_message.rb
|
100
|
+
- lib/crispy/crispy_internal/double.rb
|
101
|
+
- lib/crispy/crispy_internal/spy.rb
|
102
|
+
- lib/crispy/crispy_internal/spy_mixin.rb
|
103
|
+
- lib/crispy/crispy_internal/stubber.rb
|
104
|
+
- lib/crispy/crispy_internal/with_stubber.rb
|
105
|
+
- lib/crispy/version.rb
|
106
|
+
- test/doctest-fixtures/your_cool_class.rb
|
107
|
+
- test/test_crispy.rb
|
108
|
+
homepage: https://github.com/igrep/crispy
|
109
|
+
licenses:
|
110
|
+
- MIT
|
111
|
+
metadata: {}
|
112
|
+
post_install_message:
|
113
|
+
rdoc_options: []
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '2.0'
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
requirements: []
|
127
|
+
rubyforge_project:
|
128
|
+
rubygems_version: 2.2.2
|
129
|
+
signing_key:
|
130
|
+
specification_version: 4
|
131
|
+
summary: Test spy for any object in Ruby.
|
132
|
+
test_files:
|
133
|
+
- test/doctest-fixtures/your_cool_class.rb
|
134
|
+
- test/test_crispy.rb
|