tokyo 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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