spectroscope 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.ruby ADDED
@@ -0,0 +1,53 @@
1
+ ---
2
+ source:
3
+ - Profile
4
+ authors:
5
+ - name: Trans
6
+ email: transfire@gmail.com
7
+ copyrights:
8
+ - holder: Rubyworks
9
+ year: '2012'
10
+ license: BSD-2-Clause
11
+ requirements:
12
+ - name: rubytest
13
+ - name: detroit
14
+ groups:
15
+ - build
16
+ development: true
17
+ - name: reap
18
+ groups:
19
+ - build
20
+ development: true
21
+ - name: mast
22
+ groups:
23
+ - build
24
+ development: true
25
+ - name: ae
26
+ groups:
27
+ - test
28
+ development: true
29
+ dependencies: []
30
+ alternatives: []
31
+ conflicts: []
32
+ repositories:
33
+ - uri: git://github.com/proutils/spectroscope.git
34
+ scm: git
35
+ name: upstream
36
+ resources:
37
+ home: http://rubyworks.github.com/spectroscope
38
+ code: http://github.com/rubyworks/spectroscope
39
+ mail: http://groups.google.com/groups/rubyworks-mailinglist
40
+ extra: {}
41
+ load_path:
42
+ - lib
43
+ revision: 0
44
+ name: spectroscope
45
+ title: Spectroscope
46
+ version: 0.1.0
47
+ summary: RSpec-like BDD on RubyTest
48
+ created: '2012-02-22'
49
+ description: Spectroscope is a BDD framework built on RubyTest designed to emulate
50
+ RSpec in most respects. It is assertion framework independent so any number of assertion
51
+ systems can be used, such as Assay or AE.
52
+ organization: RubyWorks
53
+ date: '2012-02-23'
@@ -0,0 +1,36 @@
1
+ = COPYRIGHT
2
+
3
+ == NOTICES
4
+
5
+ === Spectra
6
+
7
+ Copyright:: (c) 2011 RubyWorks
8
+ License:: BSD-2-Clause
9
+ Website:: http://rubyworks.github.com/spectra
10
+
11
+
12
+ == LICENSES
13
+
14
+ === BSD-2-Clause
15
+
16
+ Redistribution and use in source and binary forms, with or without
17
+ modification, are permitted provided that the following conditions are met:
18
+
19
+ 1. Redistributions of source code must retain the above copyright notice,
20
+ this list of conditions and the following disclaimer.
21
+
22
+ 2. Redistributions in binary form must reproduce the above copyright
23
+ notice, this list of conditions and the following disclaimer in the
24
+ documentation and/or other materials provided with the distribution.
25
+
26
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
27
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
28
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
33
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+
@@ -0,0 +1,10 @@
1
+ # Release History
2
+
3
+ ## 0.1.0 / 2012-02-27
4
+
5
+ This is the first usable release of Spectroscope.
6
+
7
+ Changes:
8
+
9
+ * Happy Birthday.
10
+
@@ -0,0 +1,25 @@
1
+ Spectra, Copyright 2012 Rubyworks. All rights reserved.
2
+
3
+ BSD-2-Clause License
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice,
9
+ this list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
18
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
@@ -0,0 +1,77 @@
1
+ # Spectroscope
2
+
3
+ FreeBSD Copyright (c) 2012 Rubyworks
4
+
5
+ [Homepage](http://rubyworks.github.com/spectroscope) /
6
+ [Report Issue](http://github.com/rubyworks/spectroscope/issues) /
7
+ [Source Code](http://github.com/rubyworks/spectroscope)
8
+
9
+ [![Build Status](https://secure.travis-ci.org/rubyworks/spectroscope.png)](http://travis-ci.org/rubyworks/spectroscope)
10
+
11
+
12
+ ## Description
13
+
14
+ Spectroscope is an RSpec-style BDD framework that runs on top of the [Ruby Test](http://rubyworks.github.com/rubytest),
15
+ the Ruby universal test harness. It supports all of RSpec's syntax, with a
16
+ few exceptions.
17
+
18
+
19
+ ## Installation
20
+
21
+ $ gem install spectroscope
22
+
23
+
24
+ ## Instruction
25
+
26
+ ### Writing Specifications
27
+
28
+ Specifications are written as block of `describe` and `it` definitions.
29
+
30
+ Here's RSpec classic example:
31
+
32
+ describe Order do
33
+ it "sums the prices of its line items" do
34
+ order = Order.new
35
+ order.add_entry(LineItem.new(:item => Item.new(
36
+ :price => Money.new(1.11, :USD)
37
+ )))
38
+ order.add_entry(LineItem.new(:item => Item.new(
39
+ :price => Money.new(2.22, :USD),
40
+ :quantity => 2
41
+ )))
42
+ order.total.should eq(Money.new(5.55, :USD))
43
+ end
44
+ end
45
+
46
+ Spectroscope only handle the specification structure, it does not provide an
47
+ assertions system. For that use any of a number of available libraries,
48
+ such [Assay-RSpec](http://rubyworks.github.com/assay-rspec) or [AE](http://rubyworks.github.com/ae).
49
+ You can require these in a helper script, or in Ruby Test configuration (see below).
50
+
51
+ ### Running Specifications
52
+
53
+ Running specification is done with the `rubytest` command line utility.
54
+
55
+ $ rubytest -Ilib -rae/should spec/*_spec.rb
56
+
57
+ To make things simpler, create a `.test` configuration file.
58
+
59
+ require 'ae/should'
60
+
61
+ Test.run :default do |run|
62
+ run.files << 'spec/*_spec.rb'
63
+ end
64
+
65
+ Then simply use:
66
+
67
+ $ rubytest
68
+
69
+
70
+ ## Copyrights
71
+
72
+ Copyright (c) 2012 Rubyworks
73
+
74
+ Spectroscope is distributable according to the terms of the **FreeBSD** license.
75
+
76
+ See COPYING.rdoc for details.
77
+
@@ -0,0 +1,68 @@
1
+ $TEST_SUITE ||= []
2
+
3
+ module Spectroscope
4
+
5
+ require 'spectroscope/world'
6
+ require 'spectroscope/hooks'
7
+ require 'spectroscope/example'
8
+ require 'spectroscope/context'
9
+
10
+ # The DSL module extends the toplevel.
11
+ #
12
+ module DSL
13
+
14
+ #
15
+ # Define an example group.
16
+ #
17
+ def describe(topic, *tags, &block)
18
+ settings = {}
19
+
20
+ if Class === topic
21
+ settings[:subject] = topic
22
+ settings[:label] = topic.name
23
+ else
24
+ settings[:label] = topic
25
+ end
26
+
27
+ $TEST_SUITE << Spectroscope::Context.new(settings, &block)
28
+ end
29
+
30
+ #
31
+ #
32
+ #
33
+ def shared_examples_for(label, &block)
34
+ Spectroscope.shared_examples[label] = block
35
+ end
36
+ end
37
+
38
+ #
39
+ # Store for shared examples.
40
+ #
41
+ # @return [Hash] shared examples
42
+ #
43
+ def self.shared_examples
44
+ @shared_examples ||= {}
45
+ end
46
+
47
+ #
48
+ # Access to project metadata.
49
+ #
50
+ # @return [Hash] metadata
51
+ #
52
+ def self.metadata
53
+ @metadata ||= (
54
+ require 'yaml'
55
+ YAML.load_file(File.dirname(__FILE__), '/spectrascope.yml')
56
+ )
57
+ end
58
+
59
+ #
60
+ # If constant is missing, check for it in project metadata.
61
+ #
62
+ def self.const_missing(name)
63
+ metadata[name.to_s.downcase] || super(name)
64
+ end
65
+
66
+ end
67
+
68
+ extend Spectroscope::DSL
@@ -0,0 +1,53 @@
1
+ ---
2
+ source:
3
+ - Profile
4
+ authors:
5
+ - name: Trans
6
+ email: transfire@gmail.com
7
+ copyrights:
8
+ - holder: Rubyworks
9
+ year: '2012'
10
+ license: BSD-2-Clause
11
+ requirements:
12
+ - name: rubytest
13
+ - name: detroit
14
+ groups:
15
+ - build
16
+ development: true
17
+ - name: reap
18
+ groups:
19
+ - build
20
+ development: true
21
+ - name: mast
22
+ groups:
23
+ - build
24
+ development: true
25
+ - name: ae
26
+ groups:
27
+ - test
28
+ development: true
29
+ dependencies: []
30
+ alternatives: []
31
+ conflicts: []
32
+ repositories:
33
+ - uri: git://github.com/proutils/spectroscope.git
34
+ scm: git
35
+ name: upstream
36
+ resources:
37
+ home: http://rubyworks.github.com/spectroscope
38
+ code: http://github.com/rubyworks/spectroscope
39
+ mail: http://groups.google.com/groups/rubyworks-mailinglist
40
+ extra: {}
41
+ load_path:
42
+ - lib
43
+ revision: 0
44
+ name: spectroscope
45
+ title: Spectroscope
46
+ version: 0.1.0
47
+ summary: RSpec-like BDD on RubyTest
48
+ created: '2012-02-22'
49
+ description: Spectroscope is a BDD framework built on RubyTest designed to emulate
50
+ RSpec in most respects. It is assertion framework independent so any number of assertion
51
+ systems can be used, such as Assay or AE.
52
+ organization: RubyWorks
53
+ date: '2012-02-23'
@@ -0,0 +1,431 @@
1
+ module Spectroscope
2
+
3
+ # This is the BDD form of a test case. It encapsulates a collection
4
+ # of examples.
5
+ #
6
+ # This is the `describe` in your specs.
7
+ #
8
+ class Context
9
+
10
+ #
11
+ # The parent context in which this describe resides.
12
+ #
13
+ attr :parent
14
+
15
+ #
16
+ # A description of the describe clause.
17
+ #
18
+ attr :label
19
+
20
+ #
21
+ # A target class, if any.
22
+ #
23
+ attr :subject
24
+
25
+ #
26
+ # Array and/or metadata Hash of tags.
27
+ #
28
+ attr :tags
29
+
30
+ #
31
+ # List of examples and sub-specifications.
32
+ #
33
+ attr :specs
34
+
35
+ #
36
+ # The before and after hooks.
37
+ #
38
+ attr :hooks
39
+
40
+ #
41
+ # Skip critera.
42
+ #
43
+ # @return [Array<String,Proc>]
44
+ #
45
+ attr :skips
46
+
47
+ #
48
+ # Omit criteria.
49
+ #
50
+ # @return [Array<String,Proc>]
51
+ #
52
+ attr :omits
53
+
54
+ #
55
+ # DSL module for evaluating `describe` blocks.
56
+ #
57
+ attr :scope
58
+
59
+ #
60
+ # A test case +target+ is a class or module.
61
+ #
62
+ def initialize(settings={}, &block)
63
+ @parent = settings[:parent]
64
+ @subject = settings[:subject]
65
+ @label = settings[:label]
66
+ @tags = settings[:tags]
67
+ #@skips = settings[:skips]
68
+ #@hooks = settings[:hooks]
69
+
70
+ if @parent
71
+ @hooks = parent.hooks.clone
72
+ @skips = parent.skips.clone
73
+ @omits = parent.omits.clone
74
+ else
75
+ @hooks = Hooks.new
76
+ @skips = []
77
+ @omits = []
78
+ end
79
+
80
+ @specs = []
81
+
82
+ @scope = Scope.new(self)
83
+
84
+ evaluate(&block)
85
+ end
86
+
87
+ #
88
+ # Evalute a block of code in the context of the Context's scope.
89
+ # When finished it iterates over `omits` and `skips`, removing and
90
+ # marks examples to be skipped respectively.
91
+ #
92
+ def evaluate(&block)
93
+ @scope.module_eval(&block)
94
+
95
+ specs.delete_if do |spec|
96
+ omits.any?{ |reason, block| block.call(spec) }
97
+ end
98
+
99
+ specs.each do |spec|
100
+ skips.each do |reason, block|
101
+ if spec.match?(match)
102
+ spec.skip = reason
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ #
109
+ # Shared runtime scope for specs.
110
+ #
111
+ def it_scope
112
+ @it_scope ||= Example::Scope.new(self)
113
+ end
114
+
115
+ #
116
+ # Add `it` or sub-`describe` to group.
117
+ #
118
+ def <<(spec)
119
+ @specs << spec
120
+ end
121
+
122
+ #
123
+ # Iterate over each test and subcase.
124
+ #
125
+ def each(&block)
126
+ specs.each(&block)
127
+ end
128
+
129
+ #
130
+ # Run before-all and after-all advice around yeilding
131
+ # to test runss.
132
+ #
133
+ def call
134
+ hooks.run(self, :before, :all, it_scope)
135
+ yield
136
+ hooks.run(self, :after, :all, it_scope)
137
+ end
138
+
139
+ #
140
+ # Number of specs plus subcases.
141
+ #
142
+ def size
143
+ specs.size
144
+ end
145
+
146
+ #
147
+ # Ruby Test supports `type` to describe the nature of
148
+ # the underlying test system.
149
+ #
150
+ def type
151
+ 'describe'
152
+ end
153
+
154
+ alias :inspect :to_s
155
+
156
+ #
157
+ # Returns the subject/label as string.
158
+ #
159
+ def to_s
160
+ label.to_s
161
+ end
162
+
163
+ #
164
+ # Skip this group?
165
+ #
166
+ def skip?
167
+ @skip
168
+ end
169
+
170
+ #
171
+ #
172
+ #
173
+ def skip=(reason)
174
+ @skip = reason
175
+ end
176
+
177
+ #
178
+ # Run test in the parent of this case.
179
+ #
180
+ # @param [TestProc] test
181
+ # The test unit to run.
182
+ #
183
+ def run(test, &block)
184
+ #hooks[:before].each do |match, block|
185
+ # next if Symbol == match
186
+ # if test.match?(match)
187
+ # scope.instance_exec(test, &block) #block.call(unit)
188
+ # end
189
+ #end
190
+
191
+ block.call
192
+
193
+ #hooks[:after].each do |match, block|
194
+ # next if Symbol == match
195
+ # if test.match?(match)
196
+ # scope.instance_exec(test, &block) #block.call(unit)
197
+ # end
198
+ #end
199
+ end
200
+
201
+ # Context scope is used for defining sepcifications.
202
+ #
203
+ class Scope < World
204
+
205
+ #
206
+ # Setup new evaluation scope.
207
+ #
208
+ def initialize(group)
209
+ @_group = group
210
+ @_hooks = group.hooks
211
+ @_skips = group.skips
212
+ @_omits = group.omits
213
+
214
+ if group.parent
215
+ include(group.parent.scope)
216
+ end
217
+ end
218
+
219
+ #
220
+ # Create a new sub-specification.
221
+ #
222
+ def describe(topic, *tags, &block)
223
+ settings = {}
224
+ settings[:parent] = @_group
225
+ settings[:subject] = @_group.subject
226
+ settings[:tags] = tags
227
+
228
+ if Class === topic
229
+ settings[:subject] = topic
230
+ settings[:label] = topic.name
231
+ else
232
+ settings[:label] = topic
233
+ end
234
+
235
+ group = Context.new(settings, &block)
236
+
237
+ @_group.specs << group
238
+
239
+ return group
240
+ end
241
+
242
+ alias_method :context, :describe
243
+
244
+ #
245
+ # Create an example behavior.
246
+ #
247
+ # If tags or keys are given, so must a label.
248
+ #
249
+ def it(label=nil, *tags, &procedure)
250
+ keys = (Hash===tags ? tags.pop : {})
251
+
252
+ settings = {
253
+ :parent => @_group,
254
+ :hooks => @_hooks,
255
+ :skips => @_skips,
256
+ :omits => @_omits,
257
+ :topic => @_topic,
258
+ :label => label,
259
+ :tags => tags,
260
+ :keys => keys
261
+ }
262
+
263
+ spec = Example.new(settings, &procedure)
264
+
265
+ @_group.specs << spec
266
+
267
+ spec
268
+ end
269
+
270
+ #
271
+ #
272
+ #
273
+ alias_method :example, :it
274
+
275
+ #
276
+ # Define before procedure.
277
+ #
278
+ # @example
279
+ # describe '#puts' do
280
+ # it "gives standard output" do
281
+ # puts "Hello"
282
+ # end
283
+ #
284
+ # before do
285
+ # $stdout = StringIO.new
286
+ # end
287
+ #
288
+ # after do
289
+ # $stdout = STDOUT
290
+ # end
291
+ # end
292
+ #
293
+ # @param [Symbol] which
294
+ # Must be either `:all` or `:each`, the later being the default.
295
+ #
296
+ # @param [Array<Symbol>] tags
297
+ # List of match critera that must be matched
298
+ # against tags to trigger the before procedure.
299
+ #
300
+ def before(which=:each, *tags, &procedure)
301
+ @_hooks.add(:before, which, *tags, &procedure)
302
+ end
303
+
304
+ #
305
+ # Define a _complex_ after procedure. The #before method allows
306
+ # before procedures to be defined that are triggered by a match
307
+ # against the unit's target method name or _aspect_ description.
308
+ # This allows groups of specs to be defined that share special
309
+ # teardown code.
310
+ #
311
+ # @example
312
+ # describe '#puts' do
313
+ # it "gives standard output (@stdout)" do
314
+ # puts "Hello"
315
+ # end
316
+ #
317
+ # before do
318
+ # $stdout = StringIO.new
319
+ # end
320
+ #
321
+ # after do
322
+ # $stdout = STDOUT
323
+ # end
324
+ # end
325
+ #
326
+ # @param [Symbol] which
327
+ # Must be either `:all` or `:each`, the later being the default.
328
+ #
329
+ # @param [Array<Symbol>] tags
330
+ # List of match critera that must be matched
331
+ # to trigger the after procedure.
332
+ #
333
+ def after(which=:each, *tags, &procedure)
334
+ @_hooks.add(:after, which, *tags, &procedure)
335
+ end
336
+
337
+ #
338
+ # Mark specs or sub-cases to be skipped.
339
+ #
340
+ # @example
341
+ # it "should do something" do
342
+ # ...
343
+ # end
344
+ # skip(/something/, "reason for skipping") if jruby?
345
+ #
346
+ def skip(reason, &block)
347
+ @_skips << [reason, block]
348
+ end
349
+
350
+ #
351
+ # Mark specs or sub-cases to be omitted. Omitting a test is different
352
+ # from skipping, in tha the later is still sent up to the test harness,
353
+ # where as omitted tests never get added at all.
354
+ #
355
+ # @example
356
+ # it "should do something" do
357
+ # ...
358
+ # end
359
+ # omit(/something/) if jruby?
360
+ #
361
+ def omit(reason=true, &block)
362
+ @_omits << [reason, block]
363
+ end
364
+
365
+ #
366
+ #
367
+ #
368
+ def let(name, &block)
369
+ define_method(name) do
370
+ #_let[name] ||= block.call
371
+ @_let.fetch(name){ |k| @_let[k] = instance_eval(&block) }
372
+ end
373
+ end
374
+
375
+ #
376
+ #
377
+ #
378
+ def let!(name, &block)
379
+ let(name, &block)
380
+ before { __send__(name) }
381
+ end
382
+
383
+ #
384
+ #
385
+ #
386
+ def subject(topic=nil, &block)
387
+ @_topic = topic
388
+ define_method(:subject, &block)
389
+ end
390
+
391
+ #
392
+ # Subject-oriented example.
393
+ #
394
+ # RSpec itself wraps this whole thing in another `describe(invocation)`
395
+ # clause, but that seems completely extraneous.
396
+ #
397
+ def its(invocation, &block)
398
+ case invocation
399
+ when Symbol
400
+ it(invocation.to_s) do
401
+ subject.__send__(invocation).instance_eval(&block)
402
+ end
403
+ else
404
+ it(invocation.to_s) do
405
+ #eval("subject.#{invocation}", binding).instance_eval(&block)
406
+ calls = invocation.to_s.split('.')
407
+ calls.inject(subject){ |s,m| s.__send__(invocation) }.instance_eval(&block)
408
+ end
409
+ end
410
+ end
411
+
412
+ #
413
+ #
414
+ #
415
+ #def shared_examples_for(label, &block)
416
+ # @_shared_examples[label] = block
417
+ #end
418
+
419
+ #
420
+ #
421
+ #
422
+ def it_behaves_like(label)
423
+ proc = Spectroscope.shared_examples[label]
424
+ module_eval(&proc)
425
+ end
426
+
427
+ end
428
+
429
+ end
430
+
431
+ end