tokyo 0.0.5

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 69ea25a5800b85ee00d0af3c0129aec353c1fa95
4
+ data.tar.gz: 9bf8e1ae90ce5094fa1c9bb3a15e736c151fe491
5
+ SHA512:
6
+ metadata.gz: b03505ddcac1cc3a69ed2eca8dee762d35872d0063dec027214894c06263be54de8a160b9f0c0d36cea1cda2aa51995060f814e0c763daa33eb94ce8f633fbf7
7
+ data.tar.gz: 8a2971ff0047dcd9ec8a28c62211bc0f39aa327fd11165faf53775e20bcde6b7945538c8667abde0b84debc6f87f12347373d0db400985ccbab79e7d34c62cfb
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .DS_Store
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tokyo.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Slee Woo
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,335 @@
1
+ [![Build Status](https://travis-ci.org/sleewoo/tokyo.svg)](https://travis-ci.org/sleewoo/tokyo)
2
+
3
+ ## Tokyo - super-simple testing library for Ruby
4
+
5
+ Its base API consist of just 10 memorable methods:
6
+
7
+ - spec, context
8
+ - before, around, after
9
+ - test
10
+ - assert, refute
11
+ - skip, fail
12
+
13
+
14
+ Assertions uses native Ruby methods so no need to remember contrived ones.
15
+
16
+ Forget about repeatedly scanning documentation, just use methods Ruby already provides.
17
+
18
+ Want to check whether something is nil? Use `nil?` method:
19
+
20
+ ```ruby
21
+ assert(something).nil?
22
+ ```
23
+
24
+ Want to check whether some array contains some value? Use `include?` method:
25
+
26
+ ```ruby
27
+ assert(some_array).include? some_value
28
+ ```
29
+
30
+ Need to check equality? Nothing simpler:
31
+
32
+ ```ruby
33
+ assert(something) == something_else
34
+ ```
35
+
36
+ Perhaps match?
37
+
38
+ ```ruby
39
+ assert(something) =~ something_else
40
+ ```
41
+
42
+ Or any?
43
+
44
+ ```ruby
45
+ assert(some_array).any? {|v| v > 0}
46
+ ```
47
+
48
+ Whatever. Use Ruby rather than contrived APIs.
49
+
50
+
51
+ And when you need to cook your own assertions simply use `assert` method to define them:
52
+
53
+ ```ruby
54
+ # defining a custom assertion
55
+ assert :is_a_pizza do |something|
56
+ something =~ /Cheese/ && something =~ /Olives/
57
+ end
58
+
59
+ # using it inside tests
60
+ test 'food' do
61
+ assert(something).is_a_pizza
62
+ end
63
+ ```
64
+
65
+ ## Installation
66
+
67
+ Add this line to your application's Gemfile:
68
+
69
+ ```ruby
70
+ gem 'tokyo'
71
+ ```
72
+
73
+ And then execute:
74
+
75
+ $ bundle
76
+
77
+ Or install it yourself as:
78
+
79
+ $ gem install tokyo
80
+
81
+ ## Usage
82
+
83
+ Add `require 'tokyo'` to your `Rakefile`.
84
+
85
+ Then create a task and use `Tokyo.run`:
86
+
87
+ ```ruby
88
+ task :test do
89
+ Tokyo.run
90
+ end
91
+ ```
92
+
93
+ By default it will load `*_spec.rb` and `*_test.rb` files from `./spec` and `./test` folders.
94
+
95
+ If you named your test files differently use `Tokyo.run` with your pattern:
96
+
97
+ ```ruby
98
+ # search for test_*.rb files in ./tests folder
99
+ task :test do
100
+ Tokyo.run 'tests/test_*.rb'
101
+ end
102
+ ```
103
+
104
+ If you want to run tests directly just use `tokyo` in your terminal:
105
+
106
+ ```bash
107
+ tokyo
108
+ ```
109
+
110
+ This will load `*_spec.rb` and `*_test.rb` files from `./spec` and `./test` folders.<br>
111
+ If your tests have different naming conventions call `tokyo` command with a pattern.<br>
112
+ For ex. load `test_*.rb` files in `./tests` folder:
113
+
114
+ ```bash
115
+ tokyo tests/test_*.rb
116
+ ```
117
+
118
+
119
+ ## Specs
120
+
121
+ Specs are defined by using `spec` method. It requires a single argument - the spec label.<br>
122
+ It can be whatever but `nil`(which is used for another purpose, as shown below).
123
+
124
+ ```ruby
125
+ # defining a spec
126
+ spec Apple do
127
+
128
+ # and tests inside it
129
+ test :color do
130
+ end
131
+ end
132
+ ```
133
+
134
+ Nested contexts can be used for splitting logic:
135
+
136
+ ```ruby
137
+ spec Greens do
138
+
139
+ context Fruits do
140
+
141
+ context Apple do
142
+
143
+ end
144
+ end
145
+ end
146
+ ```
147
+
148
+ ## Specs are modules
149
+
150
+ `spec` method returns a module. Specs including that module will inherit all tests:
151
+
152
+ ```ruby
153
+ FruitsTests = spec Fruits do
154
+ # some tests
155
+ end
156
+
157
+ spec Apple do
158
+ # inheriting tests from FruitsTests spec
159
+ include FruitsTests
160
+
161
+ # defining own specs
162
+ end
163
+ ```
164
+
165
+ If you want a module that just holds tests without run them, use `nil` for label:
166
+
167
+
168
+ ```ruby
169
+ FruitsTests = spec nil do
170
+ # tests defined here will run only on specs that includes FruitsTests
171
+ end
172
+ ```
173
+
174
+ ## Global setups
175
+
176
+ `spec` method can also be used for defining a superset of instructions that will be run by all specs.
177
+
178
+ For this to work `spec` method should be called without arguments.<br>
179
+ Then the given block will run equally on all consequent specs.<br>
180
+ Multiple global setups can be defined and they will run inside specs in the order they was defined.
181
+
182
+ ```ruby
183
+ # supposedly in setup.rb
184
+ spec do
185
+ include SomeModule
186
+ end
187
+
188
+ # somewhere in test files
189
+ spec Fruits do
190
+ # this spec will include SomeModule implicitly
191
+ end
192
+ ```
193
+
194
+ ## Before, around, after
195
+
196
+ Run some code before every test:
197
+
198
+ ```ruby
199
+ spec 'Fruits' do
200
+ before { @fruit = Fruit.new }
201
+
202
+ # tests here will have @fruit variable defined
203
+ end
204
+ ```
205
+
206
+ When you need to run some code after every test simply use `after` method same way as `before`.
207
+
208
+ There is also an `around` method that will wrap each test into a block.<br>
209
+ The difference is you have to call test manually:
210
+
211
+ ```ruby
212
+ spec 'Fruits' do
213
+ around do |test|
214
+ # initialization stuff
215
+ test.call
216
+ # teardown stuff
217
+ end
218
+
219
+ # tests here will run inside around block
220
+ end
221
+ ```
222
+
223
+ There is no way to run code before/around/after specific tests.<br>
224
+ If you have tests that needs specific initialization/teardown logic put them into a separate `context`.
225
+
226
+
227
+ ## Skipping tests and specs
228
+
229
+ When you need to skip a test simply use `skip` method with a reason provided as first argument:
230
+
231
+ ```ruby
232
+ test 'something' do
233
+ # any code before skip will still run
234
+ skip 'will test this later'
235
+ # code here wont run
236
+ end
237
+ ```
238
+
239
+ `skip` also works for entire specs:
240
+
241
+ ```ruby
242
+ spec Fruits do
243
+
244
+ skip 'concentrating on Vegetables for now...'
245
+
246
+ # tests here wont run
247
+ end
248
+ ```
249
+
250
+ ## Explicit failures
251
+
252
+ When you need to throw a failure with a custom message use `fail` method:
253
+
254
+ ```ruby
255
+ test 'something' do
256
+ @a > @b || fail("#a should be greater than #b")
257
+ # code here wont run
258
+ end
259
+ ```
260
+
261
+ ## `raise` helper
262
+
263
+ `raise` allows to check whether some code raises a specific or any exception.
264
+
265
+ Check the block raises whatever exception:
266
+
267
+ ```ruby
268
+ assert {some code}.raise
269
+ ```
270
+
271
+ Check the block raises a NameError exception:
272
+
273
+ ```ruby
274
+ assert {some code}.raise NameError
275
+ ```
276
+
277
+ Check the block raises a FruitError exception that match /apple/:
278
+
279
+ ```ruby
280
+ assert {some code}.raise FruitError, /apple/
281
+ ```
282
+
283
+ Use a block to check raised exception:
284
+
285
+ ```ruby
286
+ assert {some code}.raise {|e| e.is_a? FruitError}
287
+ ```
288
+
289
+ Also alternative syntax available:
290
+
291
+ ```ruby
292
+ expect {some code}.to_raise ...
293
+ ```
294
+
295
+
296
+ ## `throw` helper
297
+
298
+ Check the block throws whatever symbol:
299
+
300
+ ```ruby
301
+ assert {some code}.throw
302
+ ```
303
+
304
+ Check the block throws `:ok` symbol:
305
+
306
+ ```ruby
307
+ assert {some code}.throw :ok
308
+ ```
309
+
310
+ Use a block to validate thrown symbol:
311
+
312
+ ```ruby
313
+ assert {some code}.throw {|s| s == :ok}
314
+ ```
315
+
316
+ Also alternative syntax available:
317
+
318
+ ```ruby
319
+ expect {some code}.to_throw ...
320
+ ```
321
+
322
+ ## Development
323
+
324
+ Make sure `bundler` is installed then run `bundle install` to install all dependencies.
325
+
326
+ Make your changes and run `rake` to check all tests pass.
327
+
328
+
329
+ ## Contributing
330
+
331
+ 1. Fork it ( https://github.com/[my-github-username]/tokyo/fork )
332
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
333
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
334
+ 4. Push to the branch (`git push origin my-new-feature`)
335
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'bundler/gem_tasks'
4
+
5
+ root = File.expand_path('..', __FILE__)
6
+ Rake::TestTask.new do |t|
7
+ t.ruby_opts << '-r "%s/test/setup" -I "%s/lib"' % [root, root]
8
+ t.pattern = 'test/**/*_test.rb'
9
+ t.verbose = true
10
+ end
11
+ task default: :test
data/bin/tokyo ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.expand_path('../../lib', __FILE__))
3
+ require 'tokyo'
4
+ Tokyo.run(*$*)
@@ -0,0 +1,148 @@
1
+ module Tokyo
2
+ class Assert
3
+
4
+ def initialize object, action = :assert, caller = nil
5
+ @object = object
6
+ @caller = caller
7
+ @assert = action == :assert
8
+ @refute = action == :refute
9
+ @assert || @refute || Kernel.raise(ArgumentError, 'action should be either :assert or :refute')
10
+ end
11
+
12
+ instance_methods.each do |m|
13
+ # overriding all instance methods so received messages to be passed to tested object.
14
+ #
15
+ # @example
16
+ # assert(x).frozen?
17
+ # # `assert` returns a object that receives `frozen?` message and pass it to x
18
+ #
19
+ define_method m do |*a, &b|
20
+ __assert__(m, a, b)
21
+ end
22
+ end
23
+
24
+ # forward any missing method to tested object.
25
+ #
26
+ # @example
27
+ # assert(some_array).include? x
28
+ # # object returned by `assert` does not respond to `include?`
29
+ # # so `include?` is passed to `some_array`
30
+ #
31
+ def method_missing m, *a, &b
32
+ __assert__(m, a, b)
33
+ end
34
+
35
+ # ensure the given block raises as expected
36
+ #
37
+ # @note if block given it will have precedence over arguments
38
+ #
39
+ # @example assertion pass if block raises whatever
40
+ # assert {some code}.raise
41
+ #
42
+ # @example assertion pass if block raises NameError
43
+ # assert {some code}.raise NameError
44
+ #
45
+ # @example assertion pass if block raises NameError and error message matches /blah/
46
+ # assert {some code}.raise NameError, /blah/
47
+ #
48
+ # @example assertion pass if block raises whatever error that matches /blah/
49
+ # assert {some code}.raise nil, /blah/
50
+ #
51
+ # @example assertion pass if validation block returns a positive value
52
+ # assert {some code}.raise {|e| e.is_a?(NameError) && e.message =~ /blah/}
53
+ #
54
+ #
55
+ # @example assertion pass if nothing raised
56
+ # refute {some code}.raise
57
+ # # same
58
+ # fail_if {some code}.raise
59
+ #
60
+ # @example assertion fails only if block raises a NameError.
61
+ # it may raise whatever but NameError. if nothing raised assertion will fail.
62
+ #
63
+ # fail_if {some code}.raise NameError
64
+ #
65
+ # @example assertion pass if raised error does not match /blah/
66
+ # if nothing raised assertion will fail.
67
+ #
68
+ # fail_if {some code}.raise nil, /blah/
69
+ #
70
+ # @example assertion will pass if raised error is not a NameError
71
+ # and error message does not match /blah/
72
+ # if nothing raised assertion will fail as well.
73
+ #
74
+ # fail_if {some code}.raise NameError, /blah/
75
+ #
76
+ def raise type = nil, message = nil, &block
77
+ failure = Tokyo.__send__(
78
+ @assert ? :assert_raised_as_expected : :refute_raised_as_expected,
79
+ @object, type, message, block
80
+ )
81
+ Tokyo.fail(failure, caller[0]) if failure
82
+ end
83
+ alias to_raise raise
84
+
85
+ # ensure given block thrown as expected
86
+ #
87
+ # @note if block given it will have precedence over arguments
88
+ #
89
+ # @example assertion pass if any symbol thrown
90
+ # assert {some code}.throw
91
+ #
92
+ # @example assertion pass only if :x symbol thrown
93
+ # assert {some code}.throw(:x)
94
+ #
95
+ # @example assertion pass only if given block validates thrown symbol
96
+ # assert {some code}.throw {|sym| sym == :x}
97
+ #
98
+ def throw expected_symbol = nil, &block
99
+ failure = Tokyo.__send__(
100
+ @assert ? :assert_thrown_as_expected : :refute_thrown_as_expected,
101
+ @object, expected_symbol ? expected_symbol.to_sym : nil, block
102
+ )
103
+ Tokyo.fail(failure, caller[0]) if failure
104
+ end
105
+ alias to_throw throw
106
+
107
+ # ensure given mock will receive expected message by the end of test
108
+ #
109
+ # @example
110
+ # test :auth do
111
+ # user = mock(User.new)
112
+ # expect(user).to_receive(:password)
113
+ # user.authenticate
114
+ # # by the end of test user should receive :password message,
115
+ # # otherwise the test will fail
116
+ # end
117
+ #
118
+ # @param Symbol expected message
119
+ # @return [Expectation]
120
+ #
121
+ def receive expected_message
122
+ Kernel.throw(:__tokyo_status__, @object[:raised]) if @object[:raised]
123
+ @__expectation__ = Expectation.new(@object[:returned], expected_message.to_sym, @assert, caller[0])
124
+ end
125
+ alias to_receive receive
126
+
127
+ def __validate_expectations__
128
+ return unless @__expectation__
129
+ @__expectation__.validate
130
+ end
131
+
132
+ private
133
+ def __assert__ message, arguments, block
134
+ Tokyo.total_assertions << true
135
+ Kernel.throw(:__tokyo_status__, @object[:raised]) if @object[:raised]
136
+ result = __send_message__(@object[:returned], message, arguments, block)
137
+ return true if (@assert && result) || (@refute && !result)
138
+ Kernel.throw(:__tokyo_status__, AssertionFailure.new(@object[:returned], arguments, @caller))
139
+ end
140
+
141
+ def __send_message__ object, message, arguments, block
142
+ if assertion = Tokyo.assertions[message.to_sym]
143
+ return assertion.call(object, *arguments, &block)
144
+ end
145
+ object.__send__(message, *arguments, &block)
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,103 @@
1
+ module Kernel
2
+
3
+ # when called with a no-nil no-false argument it defines, register and returns a spec.
4
+ # when called with a nil or false argument it defines and returns a spec but does not register it.
5
+ # when called without arguments it defines a global setup that will run on each new created spec/context.
6
+ #
7
+ # @note a Unit Module is a regular Ruby Module that when included will execute the Unit's block on base
8
+ #
9
+ # @example define regular specs
10
+ # spec :some_spec do
11
+ # # ...
12
+ # end
13
+ #
14
+ # @example define a spec that will run on its own and can also be included into another specs/contexts
15
+ # shared = spec :some_shared_spec do
16
+ # # ...
17
+ # end
18
+ # # `shared` is now a spec good for inclusion in another specs/contexts.
19
+ #
20
+ # @example define a spec that wont run on itself but can be included into another specs/contexts
21
+ # Shared = spec nil do
22
+ # # ...
23
+ # end
24
+ # # `Shared` is now a module good for inclusion in another specs/contexts
25
+ # # but because `nil` used as first argument it wont run as a spec itself
26
+ #
27
+ # @example define a global setup, i.e. a block that will run inside any new defined spec/context
28
+ # spec do
29
+ # include Rack::Test # now Rack::Test will be included in any spec/context
30
+ # end
31
+ #
32
+ def spec label = (noargs=true; nil), &block
33
+ block || raise(ArgumentError, 'missing block')
34
+
35
+ if noargs
36
+ # no arguments given, defining a global setup and returning
37
+ Tokyo::GLOBAL_SETUPS.include?(block) || Tokyo::GLOBAL_SETUPS.push(block)
38
+ return
39
+ end
40
+
41
+ if label
42
+ # a no-nil no-false argument given, defining a regular spec
43
+ Tokyo.define_and_register_a_spec(label, block)
44
+ end
45
+
46
+ # defining a shared spec that wont run itself
47
+ # but can be included in another specs/contexts
48
+ Tokyo.define_unit_module(block)
49
+ end
50
+
51
+ # when used out of tests it defines a assertion helper.
52
+ # the block should return a no-false no-nil value for assertion to pass.
53
+ # the block will receive tested object as first argument
54
+ # and any arguments passed to assertion as consequent ones.
55
+ # it will also receive the passed block.
56
+ #
57
+ # @example checks whether two arrays has same keys, orderlessly
58
+ # assert :has_same_keys_as do |a, b|
59
+ # a.keys.sort == b.keys.sort
60
+ # end
61
+ #
62
+ # spec :some_spec do
63
+ # test :some_test do
64
+ # a = [1, 2]
65
+ # b = [2, 1]
66
+ # assert(a).has_same_keys_as(b) # => true
67
+ # end
68
+ # end
69
+ #
70
+ # @example same assertion by multiple names
71
+ # assert :includes, :to_include do |a, b|
72
+ # a.keys.sort == b.keys.sort
73
+ # end
74
+ #
75
+ # spec :some_spec do
76
+ # test :some_test do
77
+ # a = [1, 2]
78
+ # assert(a).includes(1) # => true
79
+ # # same
80
+ # expect(a).to_include(1) # => true
81
+ # end
82
+ # end
83
+ #
84
+ # @param [Array] *labels
85
+ #
86
+ def assert *labels, &block
87
+ labels.any? || raise(ArgumentError, 'Wrong number of arguments, 0 for 1+')
88
+ block || raise(ArgumentError, 'missing block')
89
+ labels.each {|label| Tokyo.assertions[label.to_sym] = block}
90
+ end
91
+
92
+ # stop executing any code and report a failure
93
+ #
94
+ # @example
95
+ # x > y || fail('x should be greater than y')
96
+ #
97
+ # @param reason
98
+ #
99
+ def fail *reason
100
+ reason.empty? && raise(ArgumentError, 'Wrong number or arguments, 0 for 1+')
101
+ Tokyo.fail(reason.flatten, caller[0])
102
+ end
103
+ end
@@ -0,0 +1,32 @@
1
+ module Tokyo
2
+ class Expectation
3
+
4
+ # ensure received message raises as expected
5
+ #
6
+ # @note if block given it will have precedence over arguments
7
+ #
8
+ # @example
9
+ # x = mock(X.new)
10
+ # expect(x).to_receive(:y).and_raise(NoMethodError)
11
+ # # call `x.y` for test to pass
12
+ #
13
+ def and_raise type = nil, message = nil, &block
14
+ @raise = block || [type, message]
15
+ end
16
+
17
+ def assert_message_raised_as_expected
18
+ return unless @raise
19
+ if @raise.is_a?(Proc)
20
+ received_messages.find {|log| @raise.call(log[:raised])} || Tokyo.fail([
21
+ 'Looks like :%s message never raised as expected' % expected_message,
22
+ 'See validation block'
23
+ ], @caller)
24
+ else
25
+ received_messages.each do |log|
26
+ next unless f = Tokyo.assert_raised_as_expected(log, *@raise)
27
+ Tokyo.fail(f, log[:caller])
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end