spectroscope 0.1.0

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/.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