citron 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gemspec ADDED
@@ -0,0 +1,152 @@
1
+ # encoding: utf-8
2
+
3
+ require 'yaml'
4
+
5
+ Gem::Specification.new do |gemspec|
6
+
7
+ manifest = Dir.glob('manifest{,.txt)', File::FNM_CASEFOLD).first
8
+
9
+ scm = case
10
+ when File.directory?('.git')
11
+ :git
12
+ end
13
+
14
+ files = case
15
+ when manifest
16
+ File.readlines(manifest).
17
+ map{ |line| line.srtip }.
18
+ reject{ |line| line.empty? || line[0,1] == '#' }
19
+ when scm == :git
20
+ `git ls-files -z`.split("\0")
21
+ else
22
+ Dir.glob('{**/}{.*,*}') # TODO: be more specific using standard locations ?
23
+ end.select{ |path| File.file?(path) }
24
+
25
+ patterns = {
26
+ :bin_files => 'bin/*',
27
+ :lib_files => 'lib/{**/}*.rb',
28
+ :ext_files => 'ext/{**/}extconf.rb',
29
+ :doc_files => '*.{txt,rdoc,md,markdown,tt,textile}',
30
+ :test_files => '{test/{**/}*_test.rb,spec/{**/}*_spec.rb}'
31
+ }
32
+
33
+ glob_files = lambda { |pattern|
34
+ Dir.glob(pattern).select { |path|
35
+ File.file?(path) && files.include?(path)
36
+ }
37
+ }
38
+
39
+ #files = glob_files[patterns[:files]]
40
+
41
+ executables = glob_files[patterns[:bin_files]].map do |path|
42
+ File.basename(path)
43
+ end
44
+
45
+ extensions = glob_files[patterns[:ext_files]].map do |path|
46
+ File.basename(path)
47
+ end
48
+
49
+ metadata = YAML.load_file('.ruby')
50
+
51
+ # build-out the gemspec
52
+
53
+ case metadata['revision']
54
+ when 0
55
+ gemspec.name = metadata['name']
56
+ gemspec.version = metadata['version']
57
+ gemspec.summary = metadata['summary']
58
+ gemspec.description = metadata['description']
59
+
60
+ metadata['authors'].each do |author|
61
+ gemspec.authors << author['name']
62
+
63
+ if author.has_key?('email')
64
+ if gemspec.email
65
+ gemspec.email << author['email']
66
+ else
67
+ gemspec.email = [author['email']]
68
+ end
69
+ end
70
+ end
71
+
72
+ gemspec.licenses = metadata['licenses']
73
+
74
+ metadata['requirements'].each do |req|
75
+ name = req['name']
76
+ version = req['version']
77
+ groups = req['groups'] || []
78
+
79
+ if md = /^(.*?)([+-~])$/.match(version)
80
+ version = case md[2]
81
+ when '+' then ">= #{$1}"
82
+ when '-' then "< #{$1}"
83
+ when '~' then "~> #{$1}"
84
+ else version
85
+ end
86
+ end
87
+
88
+ #development = req['development']
89
+ #if development
90
+ # # populate development dependencies
91
+ # if gemspec.respond_to?(:add_development_dependency)
92
+ # gemspec.add_development_dependency(name,*version)
93
+ # else
94
+ # gemspec.add_dependency(name,*version)
95
+ # end
96
+ #else
97
+ # # populate runtime dependencies
98
+ # if gemspec.respond_to?(:add_runtime_dependency)
99
+ # gemspec.add_runtime_dependency(name,*version)
100
+ # else
101
+ # gemspec.add_dependency(name,*version)
102
+ # end
103
+ #end
104
+
105
+ if groups.empty? or groups.include?('runtime')
106
+ # populate runtime dependencies
107
+ if gemspec.respond_to?(:add_runtime_dependency)
108
+ gemspec.add_runtime_dependency(name,*version)
109
+ else
110
+ gemspec.add_dependency(name,*version)
111
+ end
112
+ else
113
+ # populate development dependencies
114
+ if gemspec.respond_to?(:add_development_dependency)
115
+ gemspec.add_development_dependency(name,*version)
116
+ else
117
+ gemspec.add_dependency(name,*version)
118
+ end
119
+ end
120
+ end
121
+
122
+ # convert external dependencies into a requirements
123
+ if metadata['external_dependencies']
124
+ ##gemspec.requirements = [] unless metadata['external_dependencies'].empty?
125
+ metadata['external_dependencies'].each do |req|
126
+ gemspec.requirements << req.to_s
127
+ end
128
+ end
129
+
130
+ # determine homepage from resources
131
+ homepage = metadata['resources'].find{ |key, url| key =~ /^home/ }
132
+ gemspec.homepage = homepage.last if homepage
133
+
134
+ gemspec.require_paths = metadata['load_path'] || ['lib']
135
+ gemspec.post_install_message = metadata['install_message']
136
+
137
+ # RubyGems specific metadata
138
+ gemspec.files = files
139
+ gemspec.extensions = extensions
140
+ gemspec.executables = executables
141
+
142
+ if Gem::VERSION < '1.7.'
143
+ gemspec.default_executable = gemspec.executables.first
144
+ end
145
+
146
+ gemspec.test_files = glob_files[patterns[:test_files]]
147
+
148
+ unless gemspec.files.include?('.document')
149
+ gemspec.extra_rdoc_files = glob_files[patterns[:doc_files]]
150
+ end
151
+ end
152
+ end
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .yardoc
2
+ doc
3
+ log
4
+ pkg
5
+ site
6
+ tmp
data/.ruby ADDED
@@ -0,0 +1,50 @@
1
+ ---
2
+ authors:
3
+ - name: Thomas Sawyer
4
+ email: transfire@gmail.com
5
+ copyrights:
6
+ - holder: Thomas Sawyer
7
+ year: "2011"
8
+ license: BSD-2-Clause
9
+ replacements: []
10
+
11
+ conflicts: []
12
+
13
+ requirements:
14
+ - name: test
15
+ - name: ae
16
+ - name: detroit
17
+ groups:
18
+ - build
19
+ development: true
20
+ - name: reap
21
+ groups:
22
+ - build
23
+ development: true
24
+ - name: qed
25
+ groups:
26
+ - test
27
+ development: true
28
+ dependencies: []
29
+
30
+ repositories:
31
+ - uri: git://github.com/proutils/citron.git
32
+ scm: git
33
+ name: upstream
34
+ resources:
35
+ home: http://rubyworks.github.com/citron
36
+ code: http://github.com/rubyworks/citron
37
+ load_path:
38
+ - lib
39
+ extra:
40
+ manifest: MANIFEST
41
+ alternatives: []
42
+
43
+ revision: 0
44
+ name: citron
45
+ title: Citron
46
+ suite: RubyWorks
47
+ summary: Classic Unit-style Test Framework
48
+ description: Citron is a unit testing framework with a classic test-case/test-unit style.
49
+ version: 0.1.0
50
+ date: "2011-07-29"
data/.yardopts ADDED
@@ -0,0 +1,7 @@
1
+ --output-dir site
2
+ --protected
3
+ --readme README.md
4
+ lib
5
+ -
6
+ [A-Z]*.*
7
+
data/Assembly ADDED
@@ -0,0 +1,46 @@
1
+ ---
2
+ github:
3
+ active: true
4
+
5
+ gem:
6
+ active: true
7
+
8
+ dnote:
9
+ labels: ~
10
+ output: log/NOTES.rdoc
11
+
12
+ yard:
13
+ yardopts: true
14
+
15
+ qed:
16
+ files : ~
17
+ #exclude : ~
18
+ #loadpath: ~
19
+ #requires: ~
20
+ #live : false
21
+ active : false
22
+
23
+ qedoc:
24
+ files : spec/
25
+ output: QED.rdoc
26
+ active: false
27
+
28
+ vclog:
29
+ output: log/ChangeLog.rdoc
30
+ active: false
31
+
32
+ email:
33
+ service: Email
34
+ file : ~
35
+ subject: ~
36
+ mailto :
37
+ - ruby-talk@ruby-lang.org
38
+ - rubyworks-mailinglist@googlegroups.com
39
+ from : <%= ENV['EMAIL_ACCOUNT'] %>
40
+ server : <%= ENV['EMAIL_SERVER'] %>
41
+ port : <%= ENV['EMAIL_PORT'] %>
42
+ account: <%= ENV['EMAIL_ACCOUNT'] %>
43
+ domain : <%= ENV['EMAIL_DOMAIN'] %>
44
+ login : <%= ENV['EMAIL_LOGIN'] %>
45
+ secure : <%= ENV['EMAIL_SECURE'] %>
46
+
data/COPYING.rdoc ADDED
@@ -0,0 +1,31 @@
1
+ = COPYRIGHT NOTICES
2
+
3
+ == Citron
4
+
5
+ Copyright:: (c) 2011 Thomas Sawyer, RubyWorks
6
+ License:: BSD-2-Clause
7
+ Website:: http://rubyworks.github.com/citron
8
+
9
+ Copyright 2011 Thomas Sawyer. All rights reserved.
10
+
11
+ Redistribution and use in source and binary forms, with or without
12
+ modification, are permitted provided that the following conditions are met:
13
+
14
+ 1. Redistributions of source code must retain the above copyright notice,
15
+ this list of conditions and the following disclaimer.
16
+
17
+ 2. Redistributions in binary form must reproduce the above copyright
18
+ notice, this list of conditions and the following disclaimer in the
19
+ documentation and/or other materials provided with the distribution.
20
+
21
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
23
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+
data/LICENSE.txt ADDED
@@ -0,0 +1,25 @@
1
+ BSD 2 Clause License
2
+
3
+ Copyright 2011 Thomas Sawyer. All rights reserved.
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
+
data/MANIFEST ADDED
@@ -0,0 +1,12 @@
1
+ #!mast .ruby .yaropts bin lib spec test [A-Z][A-Z]*
2
+ .ruby
3
+ lib/citron/test_advice.rb
4
+ lib/citron/test_case.rb
5
+ lib/citron/test_setup.rb
6
+ lib/citron/test_unit.rb
7
+ lib/citron.rb
8
+ PROFILE
9
+ LICENSE.txt
10
+ README.md
11
+ VERSION
12
+ COPYING.rdoc
data/PROFILE ADDED
@@ -0,0 +1,29 @@
1
+ ---
2
+ name : citron
3
+ title : Citron
4
+ suite : RubyWorks
5
+ summary: Classic Unit-style Test Framework
6
+ authors:
7
+ - Thomas Sawyer <transfire@gmail.com>
8
+
9
+ description:
10
+ Citron is a unit testing framework with a classic
11
+ test-case/test-unit style.
12
+
13
+ resources:
14
+ home: http://rubyworks.github.com/citron
15
+ code: http://github.com/rubyworks/citron
16
+
17
+ repositories:
18
+ upstream: git://github.com/proutils/citron.git
19
+
20
+ copyrights:
21
+ - 2011 Thomas Sawyer (BSD-2-Clause)
22
+
23
+ requirements:
24
+ - test
25
+ - ae
26
+ - detroit (build)
27
+ - reap (build)
28
+ - qed (test)
29
+
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # Citron
2
+
3
+ <table>
4
+ <tr><td><b>Author </b></td><td>Thomas Sawyer</td></tr>
5
+ <tr><td><b>License </b></td><td>FreeBSD</td></tr>
6
+ <tr><td><b>Copyright</b></td><td>(c) 2011 Thomas Sawyer, Rubyworks</td></tr>
7
+ </table>
8
+
9
+ ## Description
10
+
11
+ Citron is a classic unit test framework. It defines a simple
12
+ domain language for create classic-style tests.
13
+
14
+ ## Example
15
+
16
+ Here's a fun example.
17
+
18
+ ``` ruby
19
+ TestCase "Show them how to Beat It" do
20
+
21
+ # fail
22
+ test "show them how to funky" do
23
+ "funky".assert != "funky"
24
+ end
25
+
26
+ # pass
27
+ test "show them what's right" do
28
+ "right".assert == "right"
29
+ end
30
+
31
+ # error
32
+ test "no one wants to be defeated" do
33
+ raise SyntaxError
34
+ end
35
+
36
+ # todo
37
+ test "better do what you can" do
38
+ raise NotImplementedError
39
+ end
40
+
41
+ # omit
42
+ test "just beat it" do
43
+ e = NotImplementedError.new
44
+ e.set_assertion(true)
45
+ raise e
46
+ end
47
+
48
+ end
49
+ ```
50
+
51
+ ## License
52
+
53
+ Copyright (c) 2011 Thomas Sawyer, Rubyworks
54
+
55
+ Citron is distributed according to the terms of the FreeBSD license.
56
+
57
+ See COPYING.rd for details.
58
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/citron.rb ADDED
@@ -0,0 +1,23 @@
1
+ module Citron
2
+ $TEST_SUITE ||= []
3
+
4
+ require 'citron/test_case'
5
+ require 'citron/test_unit'
6
+ require 'citron/test_advice'
7
+ require 'citron/test_setup'
8
+ end
9
+
10
+ module Test
11
+ extend self
12
+
13
+ # Define a general test case.
14
+ def Case(label, &block)
15
+ $TEST_SUITE << Citron::TestCase.new(nil, :label=>label, &block)
16
+ end
17
+
18
+ alias :TestCase :Case
19
+ alias :test_case :Case
20
+ alias :case :Case
21
+ end
22
+
23
+ extend Test
@@ -0,0 +1,59 @@
1
+ module Citron
2
+
3
+ # Test Advice
4
+ class TestAdvice
5
+
6
+ # The test case to which this advice belongs.
7
+ #attr :context
8
+
9
+ #
10
+ attr :table
11
+
12
+ # New case instance.
13
+ def initialize
14
+ @table = Hash.new{ |h,k| h[k] = {} }
15
+ end
16
+
17
+ #
18
+ def initialize_copy(original)
19
+ @table = original.table.clone
20
+ end
21
+
22
+ #
23
+ def [](type)
24
+ @table[type.to_sym]
25
+ end
26
+
27
+ =begin
28
+ #
29
+ #def teardown=(procedure)
30
+ # @teardown = procedure
31
+ #end
32
+
33
+ # Setup.
34
+ def setup(scope=nil)
35
+ if scope
36
+ scope.instance_eval(&@setup)
37
+ else
38
+ @setup
39
+ end
40
+ end
41
+
42
+ # Teardown.
43
+ def teardown(scope=nil)
44
+ if scope
45
+ scope.instance_eval(&@teardown) if @teardown
46
+ else
47
+ @teardown
48
+ end
49
+ end
50
+
51
+ # Returns the description with newlines removed.
52
+ def to_s
53
+ description.gsub(/\n/, ' ')
54
+ end
55
+ =end
56
+
57
+ end
58
+
59
+ end
@@ -0,0 +1,297 @@
1
+ #require 'citron/pending'
2
+ #require 'citron/test_context'
3
+ require 'citron/test_advice'
4
+ require 'citron/test_setup'
5
+
6
+ module Citron
7
+
8
+ # Test Case encapsulates a collection of
9
+ # unit tests organized into groups of contexts.
10
+ #
11
+ class TestCase
12
+
13
+ # The parent context in which this case resides.
14
+ attr :context
15
+
16
+ # Brief description of the test case.
17
+ attr :label
18
+
19
+ # List of tests and sub-cases.
20
+ attr :tests
21
+
22
+ # The setup and teardown advice.
23
+ attr :setup
24
+
25
+ # Advice are labeled procedures, such as before
26
+ # and after advice.
27
+ attr :advice
28
+
29
+ # Module for evaluating tests.
30
+ attr :scope
31
+
32
+ # A test case +target+ is a class or module.
33
+ #
34
+ # @param [TestSuite] context
35
+ # The parent case to which this case belongs.
36
+ #
37
+ def initialize(context, settings={}, &block)
38
+ if context
39
+ @context = context
40
+ @advice = context.advice.clone
41
+ else
42
+ @context = nil
43
+ @advice = TestAdvice.new
44
+ end
45
+
46
+ @label = settings[:label]
47
+ @setup = settings[:setup]
48
+ @skip = settings[:skip]
49
+
50
+ @tests = []
51
+
52
+ domain = DSL.new(self, &block)
53
+ @scope = Module.new
54
+ @scope.extend domain
55
+ end
56
+
57
+ #
58
+ def <<(test_object)
59
+ @tests << test_object
60
+ end
61
+
62
+ # Iterate over each test and subcase.
63
+ def each(&block)
64
+ tests.each(&block)
65
+ end
66
+
67
+ # Number of tests plus subcases.
68
+ def size
69
+ tests.size
70
+ end
71
+
72
+ # Subclasses of TestCase can override this to describe
73
+ # the type of test case they define.
74
+ def type
75
+ 'Case'
76
+ end
77
+
78
+ #
79
+ def to_s
80
+ "#{type}: " + @label.to_s
81
+ end
82
+
83
+ #
84
+ def skip?
85
+ @skip
86
+ end
87
+
88
+ #
89
+ def skip=(boolean)
90
+ @skip = !!boolean
91
+ end
92
+
93
+ # Run test in the context of this case.
94
+ #
95
+ # @param [TestProc] test
96
+ # The test unit to run.
97
+ #
98
+ def run(test, &block)
99
+ advice[:before].each do |matches, block|
100
+ if matches.all?{ |match| test.match?(match) }
101
+ scope.instance_exec(test, &block) #block.call(unit)
102
+ end
103
+ end
104
+
105
+ block.call
106
+
107
+ advice[:after].each do |matches, block|
108
+ if matches.all?{ |match| test.match?(match) }
109
+ scope.instance_exec(test, &block) #block.call(unit)
110
+ end
111
+ end
112
+ end
113
+
114
+ #
115
+ #--
116
+ # TODO: Change so that the scope is the DSL
117
+ # and ** includes the DSL of the context ** !!!
118
+ #++
119
+ #def scope
120
+ # @scope ||= (
121
+ # scope = Object.new
122
+ # scope.extend(domain)
123
+ # scope
124
+ # )
125
+ #end
126
+
127
+ #
128
+ class DSL < Module
129
+
130
+ #
131
+ def initialize(testcase, &code)
132
+ @_case = testcase
133
+ @_setup = testcase.setup
134
+
135
+ if testcase.context
136
+ extend(testcase.context.scope)
137
+ end
138
+
139
+ module_eval(&code)
140
+ end
141
+
142
+ # Create a sub-case.
143
+ #--
144
+ # @TODO: Instead of resuing TestCase can we have a TestContext
145
+ # that more generically mimics it's context context?
146
+ #++
147
+ def Context(label, &block)
148
+ settings = {
149
+ :label => label,
150
+ :setup => @_setup
151
+ }
152
+ testcase = TestCase.new(@_case, settings, &block)
153
+ @_case.tests << testcase
154
+ testcase
155
+ end
156
+ alias_method :context, :Context
157
+
158
+ # Create a test.
159
+ def Test(label=nil, &procedure)
160
+ settings = {
161
+ :label => label,
162
+ :setup => @_setup
163
+ }
164
+ testunit = TestUnit.new(@_case, settings, &procedure)
165
+ if procedure.arity == 0
166
+ @_case.tests << testunit
167
+ else
168
+ @_test = testunit
169
+ end
170
+ testunit
171
+ end
172
+ alias_method :test, :Test
173
+
174
+ #
175
+ #
176
+ #
177
+ def Ok(*args)
178
+ test = @_test
179
+ test.arguments = args
180
+ @_case << test
181
+ @_test = nil
182
+ return test
183
+ end
184
+
185
+ #
186
+ #
187
+ #
188
+ def No(*args)
189
+ test = @_test
190
+ test.arguments = args
191
+ test.negate = true
192
+ @_case << test
193
+ @_test = nil
194
+ return test
195
+ end
196
+
197
+ # Setup is used to set things up for each unit test.
198
+ # The setup procedure is run before each unit.
199
+ #
200
+ # @param [String] description
201
+ # A brief description of what the setup procedure sets-up.
202
+ #
203
+ def Setup(description=nil, &procedure)
204
+ if procedure
205
+ @_setup = TestSetup.new(@_case, description, &procedure)
206
+ end
207
+ end
208
+
209
+ alias_method :setup, :Setup
210
+
211
+ #alias_method :Concern, :Setup
212
+ #alias_method :concern, :Setup
213
+
214
+ #alias_method :Subject, :Setup
215
+ #alias_method :subject, :Setup
216
+
217
+ # Teardown procedure is used to clean-up after each unit test.
218
+ #
219
+ def Teardown(&procedure)
220
+ @_setup.teardown = procedure
221
+ end
222
+
223
+ alias_method :teardown, :Teardown
224
+
225
+ # Define a _complex_ before procedure. The #before method allows
226
+ # before procedures to be defined that are triggered by a match
227
+ # against the unit's target method name or _aspect_ description.
228
+ # This allows groups of tests to be defined that share special
229
+ # setup code.
230
+ #
231
+ # @example
232
+ # Method :puts do
233
+ # Test "standard output (@stdout)" do
234
+ # puts "Hello"
235
+ # end
236
+ #
237
+ # Before /@stdout/ do
238
+ # $stdout = StringIO.new
239
+ # end
240
+ #
241
+ # After /@stdout/ do
242
+ # $stdout = STDOUT
243
+ # end
244
+ # end
245
+ #
246
+ # @param [Array<Symbol,Regexp>] matches
247
+ # List of match critera that must _all_ be matched
248
+ # to trigger the before procedure.
249
+ #
250
+ def Before(*matches, &procedure)
251
+ @_case.advice[:before][matches] = procedure
252
+ end
253
+
254
+ alias_method :before, :Before
255
+
256
+ # Define a _complex_ after procedure. The #before method allows
257
+ # before procedures to be defined that are triggered by a match
258
+ # against the unit's target method name or _aspect_ description.
259
+ # This allows groups of tests to be defined that share special
260
+ # teardown code.
261
+ #
262
+ # @example
263
+ # Method :puts do
264
+ # Test "standard output (@stdout)" do
265
+ # puts "Hello"
266
+ # end
267
+ #
268
+ # Before /@stdout/ do
269
+ # $stdout = StringIO.new
270
+ # end
271
+ #
272
+ # After /@stdout/ do
273
+ # $stdout = STDOUT
274
+ # end
275
+ # end
276
+ #
277
+ # @param [Array<Symbol,Regexp>] matches
278
+ # List of match critera that must _all_ be matched
279
+ # to trigger the after procedure.
280
+ #
281
+ def After(*matches, &procedure)
282
+ @_case.advice[:after][matches] = procedure
283
+ end
284
+
285
+ alias_method :after, :After
286
+
287
+ # Mark a test or testcase to be omitted.
288
+ #
289
+ def Omit(test_obect)
290
+ test_object.omit = true
291
+ end
292
+
293
+ end
294
+
295
+ end
296
+
297
+ end
@@ -0,0 +1,51 @@
1
+ module Citron
2
+
3
+ # Test Setup/Concern - Setup and Teardown code.
4
+ class TestSetup
5
+
6
+ # The test case to which this advice belong.
7
+ attr :context
8
+
9
+ # A brief description of this concern.
10
+ attr :label
11
+
12
+ # The setup procedure.
13
+ attr :setup
14
+
15
+ # The teardown procedure.
16
+ attr :teardown
17
+
18
+ # New case instance.
19
+ def initialize(context, label, options={}, &setup)
20
+ @context = context
21
+ @label = label.to_s
22
+ @setup = [setup].flatten
23
+ @teardown = []
24
+ end
25
+
26
+ #
27
+ def teardown=(procedure)
28
+ @teardown = [procedure]
29
+ end
30
+
31
+ # Setup.
32
+ def run_setup(scope)
33
+ setup.each do |proc|
34
+ scope.instance_eval(&proc)
35
+ end
36
+ end
37
+
38
+ # Teardown.
39
+ def run_teardown(scope)
40
+ teardown.each do |proc|
41
+ scope.instance_eval(&proc)
42
+ end
43
+ end
44
+
45
+ # Returns the description with newlines removed.
46
+ def to_s
47
+ label.gsub(/\n/, ' ')
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,123 @@
1
+ module Citron
2
+
3
+ #
4
+ class TestUnit
5
+
6
+ # New unit test procedure.
7
+ #
8
+ def initialize(context, options={}, &procedure)
9
+ @context = context
10
+
11
+ @setup = options[:setup]
12
+ @label = options[:label]
13
+ @skip = options[:skip]
14
+
15
+ @procedure = procedure
16
+ @tested = false
17
+ end
18
+
19
+ public
20
+
21
+ # The parent testcase to which this test belongs.
22
+ attr :context
23
+
24
+ #
25
+ alias :parent :context
26
+
27
+ # Setup and teardown procedures.
28
+ attr :setup
29
+
30
+ # Description of test.
31
+ attr :label
32
+
33
+ # Test procedure, in which test assertions should be made.
34
+ attr :procedure
35
+
36
+ # The before and after advice from the context.
37
+ def advice
38
+ context.advice
39
+ end
40
+
41
+ #
42
+ def type
43
+ 'Unit'
44
+ end
45
+
46
+ #
47
+ def skip? ; @skip ; end
48
+
49
+ #
50
+ def skip=(boolean)
51
+ @skip = !!boolean
52
+ end
53
+
54
+ #
55
+ def tested?
56
+ @tested
57
+ end
58
+
59
+ #
60
+ def tested=(boolean)
61
+ @tested = boolean
62
+ end
63
+
64
+ #
65
+ def to_s
66
+ label.to_s
67
+ end
68
+
69
+ #
70
+ def setup
71
+ @setup
72
+ end
73
+
74
+ #
75
+ alias :subtext :setup
76
+
77
+ #
78
+ def scope
79
+ context.scope
80
+ end
81
+
82
+ #
83
+ def arguments
84
+ @arguments
85
+ end
86
+
87
+ #
88
+ def arguments=(args)
89
+ @arguments = args
90
+ end
91
+
92
+ # TODO: how to handle negated tests?
93
+ def negate
94
+ @negate
95
+ end
96
+
97
+ #
98
+ def negate=(boolean)
99
+ @negate = !!boolean
100
+ end
101
+
102
+ #
103
+ def to_proc
104
+ lambda{ call }
105
+ end
106
+
107
+ #
108
+ def match?(match)
109
+ match == target || match === description
110
+ end
111
+
112
+ #
113
+ def call
114
+ context.run(self) do
115
+ setup.run_setup(scope) if setup
116
+ scope.instance_exec(*arguments, &procedure)
117
+ setup.run_teardown(scope) if setup
118
+ end
119
+ end
120
+
121
+ end
122
+
123
+ end
@@ -0,0 +1,30 @@
1
+ TestCase "Show them how to Beat It" do
2
+
3
+ # will fail
4
+ test "show them how to funky" do
5
+ "funky".assert != "funky"
6
+ end
7
+
8
+ # will pass
9
+ test "show them what's right" do
10
+ "right".assert == "right"
11
+ end
12
+
13
+ # will error
14
+ test "no one wants to be defeated" do
15
+ raise SyntaxError
16
+ end
17
+
18
+ # pending
19
+ test "better do what you can" do
20
+ raise NotImplementedError
21
+ end
22
+
23
+ # omit
24
+ test "just beat it" do
25
+ e = NotImplementedError.new
26
+ e.set_assertion(true)
27
+ raise e
28
+ end
29
+
30
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: citron
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Thomas Sawyer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-07-29 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: test
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: ae
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :runtime
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: detroit
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: reap
50
+ prerelease: false
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ type: :development
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: qed
61
+ prerelease: false
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ type: :development
69
+ version_requirements: *id005
70
+ description: Citron is a unit testing framework with a classic test-case/test-unit style.
71
+ email:
72
+ - transfire@gmail.com
73
+ executables: []
74
+
75
+ extensions: []
76
+
77
+ extra_rdoc_files:
78
+ - LICENSE.txt
79
+ - COPYING.rdoc
80
+ - README.md
81
+ files:
82
+ - .gemspec
83
+ - .gitignore
84
+ - .ruby
85
+ - .yardopts
86
+ - Assembly
87
+ - COPYING.rdoc
88
+ - LICENSE.txt
89
+ - MANIFEST
90
+ - PROFILE
91
+ - README.md
92
+ - VERSION
93
+ - lib/citron.rb
94
+ - lib/citron/test_advice.rb
95
+ - lib/citron/test_case.rb
96
+ - lib/citron/test_setup.rb
97
+ - lib/citron/test_unit.rb
98
+ - try/case_example.rb
99
+ homepage: http://rubyworks.github.com/citron
100
+ licenses: []
101
+
102
+ post_install_message:
103
+ rdoc_options: []
104
+
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: "0"
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: "0"
119
+ requirements: []
120
+
121
+ rubyforge_project:
122
+ rubygems_version: 1.8.2
123
+ signing_key:
124
+ specification_version: 3
125
+ summary: Classic Unit-style Test Framework
126
+ test_files: []
127
+