citron 0.2.0 → 0.3.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 CHANGED
@@ -1,50 +1,47 @@
1
- ---
2
- authors:
1
+ ---
2
+ source:
3
+ - PROFILE
4
+ authors:
3
5
  - name: Thomas Sawyer
4
6
  email: transfire@gmail.com
5
- copyrights:
7
+ copyrights:
6
8
  - holder: Thomas Sawyer
7
- year: "2011"
9
+ year: '2011'
8
10
  license: BSD-2-Clause
9
- replacements: []
10
-
11
- conflicts: []
12
-
13
- requirements:
14
- - name: test
11
+ requirements:
12
+ - name: rubytest
15
13
  - name: ae
16
14
  - name: detroit
17
- groups:
15
+ groups:
18
16
  - build
19
17
  development: true
20
18
  - name: reap
21
- groups:
19
+ groups:
22
20
  - build
23
21
  development: true
24
22
  - name: qed
25
- groups:
23
+ groups:
26
24
  - test
27
25
  development: true
28
26
  dependencies: []
29
-
30
- repositories:
27
+ alternatives: []
28
+ conflicts: []
29
+ repositories:
31
30
  - uri: git://github.com/proutils/citron.git
32
31
  scm: git
33
32
  name: upstream
34
- resources:
33
+ resources:
35
34
  home: http://rubyworks.github.com/citron
36
35
  code: http://github.com/rubyworks/citron
37
- load_path:
36
+ extra: {}
37
+ load_path:
38
38
  - lib
39
- extra:
40
- manifest: MANIFEST
41
- alternatives: []
42
-
43
39
  revision: 0
44
40
  name: citron
45
41
  title: Citron
42
+ version: 0.3.0
46
43
  summary: Classic Unit-style Test Framework
47
- description: Citron is a unit testing framework with a classic test-case/test-unit style.
44
+ description: Citron is a unit testing framework with a classic test-case/test-unit
45
+ style.
48
46
  organization: RubyWorks
49
- version: 0.2.0
50
- date: "2011-08-12"
47
+ date: '2012-02-25'
@@ -1,12 +1,18 @@
1
- = COPYRIGHT NOTICES
1
+ # COPYRIGHT
2
2
 
3
- == Citron
4
3
 
5
- Copyright:: (c) 2011 Thomas Sawyer, RubyWorks
6
- License:: BSD-2-Clause
7
- Website:: http://rubyworks.github.com/citron
4
+ ## NOTICES
8
5
 
9
- Copyright 2011 Thomas Sawyer. All rights reserved.
6
+ ### Citron
7
+
8
+ http://rubyworks.github.com/citron
9
+
10
+ * Copyright (c) 2011 Rubyworks (BSD-2-Clause)
11
+
12
+
13
+ ## LICENSES
14
+
15
+ ### BSD-2-Clause
10
16
 
11
17
  Redistribution and use in source and binary forms, with or without
12
18
  modification, are permitted provided that the following conditions are met:
@@ -0,0 +1,22 @@
1
+ # Release History
2
+
3
+ ## 0.3.0 / 2012-02-25
4
+
5
+ This release cleans up the code, deprecates the complex Before and After
6
+ advice, adds soem additional support for RubyTests lesser known features.
7
+
8
+ Changes:
9
+
10
+ * Deprecated Before and After advice.
11
+ * Add support for #unit and #source_location.
12
+ * Setup/terdown is inherited by subcases.
13
+
14
+
15
+ ## 0.2.0 / 2011-08-11
16
+
17
+ This is the first usable release of Citron.
18
+
19
+ Changes:
20
+
21
+ * General improvements.
22
+
@@ -1,20 +1,17 @@
1
- = Citron
1
+ # Citron
2
2
 
3
- {Homepage}[http://rubyworks.github.com/citron] -
4
- {Development}[http://github.com/rubyworks/citron]
3
+ [Website](http://rubyworks.github.com/citron) /
4
+ [Development](http://github.com/rubyworks/citron) /
5
+ [Report Issue](http://github.com/rubyworks/citron/issues) /
5
6
 
6
- Author:: Thomas Sawyer
7
- License:: FreeBSD
8
- Copyright:: (c) 2011 Thomas Sawyer, Rubyworks
9
7
 
8
+ ## Description
10
9
 
11
- == Description
10
+ Citron is a traditional unit test framework. It defines a simple
11
+ domain language for creating classically styled unit tests.
12
12
 
13
- Citron is a classic unit test framework. It defines a simple
14
- domain language for create classic-style tests.
15
13
 
16
-
17
- == Example
14
+ ## Example
18
15
 
19
16
  Here's a fun example.
20
17
 
@@ -55,11 +52,11 @@ Here's a fun example.
55
52
  end
56
53
 
57
54
 
58
- == License
55
+ ## Copyrights
59
56
 
60
- Copyright (c) 2011 Thomas Sawyer, Rubyworks
57
+ Copyright (c) 2011 Rubyworks
61
58
 
62
- Citron is distributed according to the terms of the FreeBSD license.
59
+ Citron is distributable according to the terms of the **FreeBSD** license.
63
60
 
64
- See COPYING.rd for details.
61
+ See COPYING.md for details.
65
62
 
@@ -1,16 +1,16 @@
1
- module Citron
2
- $TEST_SUITE ||= []
1
+ $TEST_SUITE ||= []
3
2
 
4
- require 'citron/test_case'
5
- require 'citron/test_proc'
6
- require 'citron/test_advice'
3
+ module Citron
4
+ require 'citron/world'
7
5
  require 'citron/test_setup'
8
- end
6
+ require 'citron/test_teardown'
7
+ require 'citron/test_proc'
8
+ require 'citron/test_case'
9
9
 
10
- module Citron
11
10
  module DSL
12
-
11
+ #
13
12
  # Define a general test case.
13
+ #
14
14
  def test_case(label, &block)
15
15
  $TEST_SUITE << Citron::TestCase.new(:label=>label, &block)
16
16
  end
@@ -18,6 +18,8 @@ module Citron
18
18
  alias :TestCase :test_case
19
19
  alias :testcase :test_case
20
20
  end
21
+
21
22
  end
22
23
 
23
24
  extend Citron::DSL
25
+
@@ -1,10 +1,3 @@
1
- #require 'citron/pending'
2
- #require 'citron/test_context'
3
- require 'citron/test_advice'
4
- require 'citron/test_setup'
5
- require 'citron/test_proc'
6
- require 'citron/world'
7
-
8
1
  module Citron
9
2
 
10
3
  # Test Case encapsulates a collection of
@@ -18,30 +11,41 @@ module Citron
18
11
  # Brief description of the test case.
19
12
  attr :label
20
13
 
14
+ # Symbol list of tags. Trailing element may be Hash
15
+ # of `symbol => object`.
16
+ attr :tags
17
+
21
18
  # List of tests and sub-cases.
22
19
  attr :tests
23
20
 
24
- # The setup and teardown advice.
21
+ # The setup advice.
25
22
  attr :setup
26
23
 
27
- # Pattern mathing before and after advice.
28
- attr :advice
24
+ # The teardown advice.
25
+ attr :teardown
26
+
27
+ # Code unit that is subject of test case.
28
+ attr :unit
29
29
 
30
30
  # Module for evaluating tests.
31
31
  attr :scope
32
32
 
33
- # A test case +target+ is a class or module.
33
+ private
34
+
35
+ # Initialize new TestCase.
34
36
  #
35
37
  def initialize(settings={}, &block)
36
38
  @context = settings[:context]
37
39
  @label = settings[:label]
38
- @setup = settings[:setup]
40
+ @tags = settings[:tags]
41
+ #@setup = settings[:setup]
39
42
  @skip = settings[:skip]
40
43
 
41
- if @context
42
- @advice = context.advice.clone
43
- else
44
- @advice = TestAdvice.new
44
+ @unit = calc_unit
45
+
46
+ if context
47
+ @setup = context.setup.copy(self) if context.setup
48
+ @teardown = context.teardown.copy(self) if context.teardown
45
49
  end
46
50
 
47
51
  @tests = []
@@ -51,141 +55,235 @@ module Citron
51
55
  @scope.module_eval(&block) if block
52
56
  end
53
57
 
58
+ #
59
+ def calc_unit
60
+ case @label
61
+ when Module, Class
62
+ @label
63
+ when /^(\.|\#|\:\:)\w+/
64
+ if @context && Module === @context.unit
65
+ [@context.unit, @label].join('')
66
+ else
67
+ @label
68
+ end
69
+ end
70
+ end
71
+
72
+ public
73
+
74
+ #
75
+ # Assign the setup procedure
76
+ #
77
+ # @param [TestSetup] test_setup
78
+ #
79
+ def setup=(test_setup)
80
+ @setup = test_setup
81
+ end
82
+
83
+ #
84
+ # Assign the teardown procedure.
85
+ #
86
+ # @param [TestTeardown] test_teardown
87
+ #
88
+ def teardown=(test_teardown)
89
+ @teardown = test_teardown
90
+ end
91
+
92
+ #
93
+ # Add new test or sub-case.
94
+ #
95
+ # @param [TestCase,TestProc] test_obejct
96
+ # Test sub-case or procedure to add to this case.
54
97
  #
55
98
  def <<(test_object)
56
99
  @tests << test_object
57
100
  end
58
101
 
59
- # Iterate over each test and subcase.
102
+ #
103
+ # Iterate over each test and sub-case.
104
+ #
105
+ # @param [Proc] block
106
+ # Iteration procedure.
107
+ #
60
108
  def each(&block)
61
109
  tests.each(&block)
62
110
  end
63
111
 
64
- # Number of tests plus subcases.
112
+ #
113
+ #def call
114
+ # yield
115
+ #end
116
+
117
+ #
118
+ # Number of tests and sub-cases.
119
+ #
120
+ # @return [Fixnum] size
121
+ #
65
122
  def size
66
123
  tests.size
67
124
  end
68
125
 
126
+ #
69
127
  # Subclasses of TestCase can override this to describe
70
128
  # the type of test case they define.
71
- def type
72
- 'Case'
73
- end
129
+ #
130
+ # @return [String]
131
+ #
132
+ #def type
133
+ # 'TestCase'
134
+ #end
74
135
 
136
+ #
137
+ # Test case label.
138
+ #
139
+ # @return [String]
75
140
  #
76
141
  def to_s
77
142
  label.to_s
78
143
  end
79
144
 
145
+ #
146
+ # Is test case to be skipped?
147
+ #
148
+ # @return [Boolean,String]
149
+ # If +false+ or +nil+ if not skipped, otherwise
150
+ # +true+ or a string explain why to skip.
80
151
  #
81
152
  def skip?
82
153
  @skip
83
154
  end
84
155
 
156
+ #
157
+ # Set test case to be skipped.
158
+ #
159
+ # @param [Boolean,String] reason
160
+ # Set to +false+ or +nil+ if not skipped, otherwise
161
+ # +true+ or a string explain why to skip.
85
162
  #
86
163
  def skip=(reason)
87
164
  @skip = reason
88
165
  end
89
166
 
90
- # Run test in the context of this case.
167
+ def test_scope
168
+ @test_scope ||= TestProc::Scope.new(scope)
169
+ end
170
+
171
+ #
172
+ # Run +test+ in the context of this case.
91
173
  #
92
174
  # @param [TestProc] test
93
175
  # The test unit to run.
94
176
  #
95
- def run(test, &block)
96
- advice[:before].each do |matches, block|
97
- if matches.all?{ |match| test.match?(match) }
98
- scope.instance_exec(test, &block) #block.call(unit)
99
- end
100
- end
101
-
102
- block.call
103
-
104
- advice[:after].each do |matches, block|
105
- if matches.all?{ |match| test.match?(match) }
106
- scope.instance_exec(test, &block) #block.call(unit)
107
- end
108
- end
177
+ def run(test)
178
+ setup.call(test_scope) if setup
179
+ #scope.instance_exec(*arguments, &procedure)
180
+ test_scope.instance_eval(&test.procedure)
181
+ teardown.call(test_scope) if teardown
109
182
  end
110
183
 
184
+ # The evaluation scope for a test case.
111
185
  #
112
186
  class Scope < World
113
187
 
114
- # Setup new evaluation scope.
188
+ #
189
+ # Initialize new evaluation scope.
190
+ #
191
+ # @param [TestCase] testcase
192
+ # The test case this scope belongs.
193
+ #
115
194
  def initialize(testcase) #, &code)
116
195
  @_case = testcase
117
196
  @_setup = testcase.setup
118
197
  @_skip = false
119
198
 
120
199
  if testcase.context
121
- extend(testcase.context.scope)
200
+ include(testcase.context.scope)
122
201
  end
123
202
  end
124
203
 
125
- #--
126
- # TODO: Instead of reusing TestCase can we have a TestContext
127
- # that more generically mimics it's context context?
128
- #++
129
-
204
+ #
130
205
  # Create a sub-case.
131
- def Context(label, &block)
206
+ #
207
+ # @param [String] label
208
+ # The breif description of the test case.
209
+ #
210
+ # @param [Array<Symbol,Hash>] tags
211
+ # List of symbols with optional trailing `symbol=>object` hash.
212
+ # These can be used as a means of filtering tests.
213
+ #
214
+ def Context(label, *tags, &block)
132
215
  settings = {
133
216
  :context => @_case,
134
- :setup => @_setup,
217
+ #:setup => @_setup,
135
218
  :skip => @_skip,
136
- :label => label
219
+ :label => label,
220
+ :tags => tags
137
221
  }
222
+
138
223
  testcase = TestCase.new(settings, &block)
224
+
139
225
  @_case.tests << testcase
226
+
140
227
  testcase
141
228
  end
142
229
 
143
230
  alias :context :Context
144
231
 
145
- # Create a test.
146
- def Test(label=nil, &procedure)
232
+ #
233
+ # Create a test, or a parameterized test.
234
+ #
235
+ # @param [String] label
236
+ # The breif description of the test case.
237
+ #
238
+ # @param [Array<Symbol,Hash>] tags
239
+ # List of symbols with optional trailing `symbol=>object` hash.
240
+ # These can be used as a means of filtering tests.
241
+ #
242
+ def Test(label=nil, *tags, &procedure)
243
+ file, line, _ = *caller[0].split(':')
244
+
147
245
  settings = {
148
246
  :context => @_case,
149
- :setup => @_setup,
247
+ #:setup => @_setup,
150
248
  :skip => @_skip,
151
- :label => label
249
+ :label => label,
250
+ :tags => tags,
251
+ :file => file,
252
+ :line => line
152
253
  }
153
- testunit = TestProc.new(settings, &procedure)
154
- if procedure.arity == 0
155
- @_case.tests << testunit
254
+
255
+ if procedure.arity == 0 || (RUBY_VERSION < '1.9' && procedure.arity == -1)
256
+ test = TestProc.new(settings, &procedure)
257
+ @_case.tests << test
258
+ @_test = nil
259
+ test
156
260
  else
157
- @_test = testunit
261
+ @_test = [settings, procedure]
158
262
  end
159
- testunit
160
263
  end
161
264
 
162
265
  alias :test :Test
163
266
 
164
267
  #
268
+ # Actualize a parameterized test.
269
+ #
270
+ # @todo Better name than `Ok` ?
165
271
  #
166
272
  def Ok(*args)
167
- test = @_test
168
- test.arguments = args
169
- @_case << test
170
- @_test = nil
171
- return test
172
- end
273
+ settings, procedure = *@_test
173
274
 
174
- alias :ok :Ok
275
+ test = TestProc.new(settings) do
276
+ procedure.call(*args)
277
+ end
175
278
 
176
- #
177
- #
178
- def No(*args)
179
- test = @_test
180
- test.arguments = args
181
- test.negate = true
182
279
  @_case << test
183
- @_test = nil
280
+
184
281
  return test
185
282
  end
186
283
 
187
- alias :no :No
284
+ alias :ok :Ok
188
285
 
286
+ #
189
287
  # Setup is used to set things up for each unit test.
190
288
  # The setup procedure is run before each unit.
191
289
  #
@@ -193,97 +291,59 @@ module Citron
193
291
  # A brief description of what the setup procedure sets-up.
194
292
  #
195
293
  def Setup(label=nil, &proc)
196
- @_setup = TestSetup.new(@_case, label, &proc)
294
+ if proc
295
+ @_case.setup = TestSetup.new(@_case, label, &proc)
296
+ @_case.teardown = nil # if the setup is reset, then so it the teardown
297
+ else
298
+ @_case.setup
299
+ end
197
300
  end
198
301
 
199
302
  alias :setup :Setup
200
303
 
201
- #alias_method :Concern, :Setup
202
- #alias_method :concern, :Setup
203
-
304
+ #
204
305
  # Teardown procedure is used to clean-up after each unit test.
205
306
  #
206
307
  def Teardown(&proc)
207
- @_setup.teardown = proc
308
+ if proc
309
+ @_case.teardown = TestTeardown.new(@_case, &proc)
310
+ else
311
+ @_case.teardown
312
+ end
208
313
  end
209
314
 
210
315
  alias :teardown :Teardown
211
316
 
212
- # Define a _complex_ before procedure. The #before method allows
213
- # before procedures to be defined that are triggered by a match
214
- # against the unit's target method name or _aspect_ description.
215
- # This allows groups of tests to be defined that share special
216
- # setup code.
217
- #
218
- # @example
219
- # Method :puts do
220
- # Test "standard output (@stdout)" do
221
- # puts "Hello"
222
- # end
223
- #
224
- # Before /@stdout/ do
225
- # $stdout = StringIO.new
226
- # end
227
- #
228
- # After /@stdout/ do
229
- # $stdout = STDOUT
230
- # end
231
- # end
232
317
  #
233
- # @param [Array<Symbol,Regexp>] matches
234
- # List of match critera that must _all_ be matched
235
- # to trigger the before procedure.
318
+ # Mark tests or sub-cases to be skipped. If block is given, then
319
+ # tests defined within the block are skipped. Without a block
320
+ # all subsquent tests defined in a context will be skipped.
236
321
  #
237
- def Before(*matches, &procedure)
238
- @_case.advice[:before][matches] = procedure
239
- end
240
-
241
- alias :before :Before
242
-
243
- # Define a _complex_ after procedure. The #before method allows
244
- # before procedures to be defined that are triggered by a match
245
- # against the unit's target method name or _aspect_ description.
246
- # This allows groups of tests to be defined that share special
247
- # teardown code.
322
+ # @param [Boolean,String] reason
323
+ # Set to +false+ or +nil+ if not skipped, otherwise
324
+ # +true+ or a string explain why to skip.
248
325
  #
249
326
  # @example
250
- # Method :puts do
251
- # Test "standard output (@stdout)" do
252
- # puts "Hello"
253
- # end
254
- #
255
- # Before /@stdout/ do
256
- # $stdout = StringIO.new
257
- # end
258
- #
259
- # After /@stdout/ do
260
- # $stdout = STDOUT
327
+ # skip("awaiting new feature") do
328
+ # test "some test" do
329
+ # ...
261
330
  # end
262
331
  # end
263
332
  #
264
- # @param [Array<Symbol,Regexp>] matches
265
- # List of match critera that must _all_ be matched
266
- # to trigger the after procedure.
267
- #
268
- def After(*matches, &procedure)
269
- @_case.advice[:after][matches] = procedure
270
- end
271
-
272
- alias :after :After
273
-
274
- # Mark tests or subcases to be skipped.
275
- #
276
333
  # @example
277
- # skip("reason for skipping") do
278
- # test "some test" do
279
- # ...
280
- # end
334
+ # skip("not on jruby") if jruby?
335
+ # test "some test" do
336
+ # ...
281
337
  # end
282
338
  #
283
339
  def Skip(reason=true, &block)
284
- @_skip = reason
285
- block.call
286
- @_skip = false
340
+ if block
341
+ @_skip = reason
342
+ block.call if block
343
+ @_skip = false
344
+ else
345
+ @_skip = reason
346
+ end
287
347
  end
288
348
 
289
349
  alias :skip :Skip