testme 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ pkg
2
+ doc
3
+ .yardoc
4
+ .DS_Store
5
+ /Gemfile.lock
6
+ /notes
7
+ /*.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format documentation
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.3
data/.testme ADDED
@@ -0,0 +1,5 @@
1
+ require "testme"
2
+
3
+ TESTME_DIR = '/test/'
4
+ TESTME_FORMAT = :console
5
+ TESTME_COLORS = :default
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ gem 'rake'
6
+ gem 'rspec', '>= 2.11.0'
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2012 Daniel Shuey
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,341 @@
1
+ # Test Me
2
+ *A minimalistic testing framework*
3
+
4
+ test Me
5
+ given simple: true
6
+ is? :simple
7
+
8
+ ## Detailed Example
9
+
10
+ test Pizza
11
+ given owner: 'Santoni', style: 'Pepperoni' # Set the context
12
+ is? :name, "Santoni's Pepperoni Pizza"
13
+
14
+ given name: 'Michel' # Reset the context
15
+ is? :name, "Santoni's Pepperoni Pizza"
16
+
17
+ also :hawaiian_style, style: 'Hawaiian' # Add on to previous context and save it
18
+ is? :name, "Michels's Hawaiian Pizza"
19
+
20
+ given :hawaiian_style # Reload the saved context
21
+ also { topic.owner = 'Santoni' } # Use a block instead
22
+ is? :name, "Santoni's Hawaiian Pizza"
23
+
24
+ > ### Output
25
+
26
+ > test Pizza
27
+ > given owner: 'Santoni', style: 'Pepperoni'
28
+ > is name, Santoni's Pepperoni Pizza? YES
29
+ >
30
+ > given name: 'Michel'
31
+ > is name, Santoni's Pepperoni Pizza? NO, it was Michel's Pizza!
32
+ >
33
+ > also :hawaiian_style: style: 'Hawaiian'
34
+ > is name, Michel's Hawaiian Pizza? YES
35
+ >
36
+ > given :hawaiian_style:
37
+ > also (block)
38
+ > is name, Santoni's Hawaiian Pizza? YES
39
+
40
+ ## Setup
41
+
42
+ `gem install testme`
43
+
44
+ *Then in your project root directory*
45
+
46
+ `testme setup`
47
+
48
+ /.testme
49
+ /test/
50
+ /test/app.test.rb
51
+
52
+ *Default .testme boiler plate on setup*
53
+ *this might need to be reconfigured to cater to your project*
54
+
55
+ require "testme"
56
+
57
+ TESTME_DIR = '/test/'
58
+ TESTME_FORMAT = :console
59
+ TESTME_COLORS = :default
60
+
61
+ #### Example config with bundler
62
+
63
+ require "rubygems"
64
+ require "bundler"
65
+ require "bundler/setup"
66
+ Bundler.require :default, :test
67
+
68
+ TESTME_DIR = '/test/'
69
+ TESTME_FORMAT = :console
70
+ TESTME_COLORS = :default
71
+
72
+ ## Config
73
+
74
+ In your project root will be a `.testme` file, this is your bootstrap that runs before your tests
75
+
76
+ The `/test/` folder will house all your test files, you can change this in your bootstrap
77
+
78
+ ### Config options
79
+
80
+ TESTME_DIR = '/test/'
81
+ * default: '/test/'
82
+
83
+ TESTME_FORMAT = :console
84
+ * choose how results are displayed
85
+ * options: :none, :text, :console
86
+ * default: :console
87
+
88
+ TESTME_COLORS = :default
89
+ * color scheme for console output
90
+ * options: :default
91
+ * default: :default
92
+
93
+ ***
94
+
95
+ ## Run
96
+
97
+ #### Test all
98
+ default test folder: `/test/**/*`
99
+
100
+ $ testme
101
+
102
+ #### Test all in directory
103
+
104
+ $ testme test/features
105
+
106
+ #### Test file
107
+
108
+ $ testme test/account.test.rb
109
+
110
+ #### Inline testing
111
+
112
+ $ testme app/models
113
+
114
+ ##### Inline testing examples
115
+
116
+ >
117
+
118
+ class Account
119
+ end
120
+
121
+ testme do
122
+ test Account
123
+ end
124
+
125
+ >
126
+
127
+ class Account
128
+
129
+ field :name
130
+
131
+ def what_is_my_name
132
+ return name
133
+ end
134
+
135
+ testme {
136
+ test Account
137
+ given name: 'Fred'
138
+ is? what_is_my_name: 'Fred'
139
+ }
140
+
141
+ end
142
+
143
+ >
144
+
145
+ class Account
146
+ extend TestMe; test Account
147
+
148
+ field :name
149
+
150
+ def what_is_my_name
151
+ return name
152
+ end
153
+
154
+ #what_is_my_name
155
+ given name: 'Fred'
156
+ is? what_is_my_name: 'Fred'
157
+ end
158
+
159
+ ## Keywords
160
+ #### `test`
161
+ > Defines the topic of the test
162
+
163
+ test Account
164
+
165
+ >
166
+
167
+ test App::Account
168
+
169
+ > This automatically creates an instance which you access with `topic`
170
+
171
+ topic.name
172
+
173
+ > Both modules and classes can be used for the test topic
174
+
175
+ test AccountHelper
176
+
177
+ > (At the moment you can only test instance methods, class methods will also be testable in a later update)
178
+
179
+ ***
180
+
181
+ #### `given`
182
+ > Set the context
183
+
184
+ given first_name: 'Deckard', surname: 'Cain'
185
+
186
+ $ topic.first_name
187
+ $ => "Deckard"
188
+
189
+ $ topic.surname
190
+ $ => "Cain"
191
+
192
+ > Clear any previous context
193
+
194
+ given first_name: 'Deckard'
195
+ given first_name: 'Flavie'
196
+
197
+ $ topic.first_name
198
+ $ => "Flavie"
199
+
200
+ > Create or Overwrite methods that can return anything on the topic (Stubbing)
201
+
202
+ given non_existent_method: "this never existed before"
203
+
204
+ $ topic.non_existent_method
205
+ $ => "this never existed before"
206
+
207
+ > Create a context using a block
208
+
209
+ given { topic.talk_to 'Flavie' }
210
+
211
+ > Code run inside a block will still automatically stub for you
212
+
213
+ given { topic.non_existent_method = "this never existed before" }
214
+
215
+ > Store a context
216
+
217
+ given :deckard_cains_name, name: Name.new(first: 'Deckard', last: 'Cain')
218
+
219
+ > Load a context
220
+
221
+ given :deckard_cains_name
222
+
223
+ > Create a stub chain
224
+
225
+ given { topic.name.first = 'Deckard' }
226
+
227
+ > Stub chains will also only override the method you stub, while keeping the remaining associations intact
228
+
229
+ given :deckard_cains_name { topic.name.first = 'Flavie' }
230
+
231
+ $ topic.name.last
232
+ $ => "Cain"
233
+
234
+ ***
235
+
236
+ #### `also`
237
+ > Provides a context over the existing context
238
+
239
+ given first_name: 'Deckard'
240
+ also surname: 'Cain'
241
+
242
+ $ topic.first_name
243
+ $ => "Deckard"
244
+
245
+ $ topic.surname
246
+ $ => "Cain"
247
+
248
+ > Anything you can do in `given` you can also do in `also`
249
+
250
+ given name: Name.new(first: 'Deckard', last: 'Cain')
251
+ also :flavies_name { topic.name.first = 'Flavie' }
252
+
253
+ given name: Name.new(first: 'Deckard', last: 'Cain')
254
+ also :flavies_name
255
+
256
+ $ topic.name.first
257
+ $ => "Flavie"
258
+
259
+ ***
260
+
261
+ #### `is?`
262
+ > Creates an assertion
263
+
264
+ is? :first_name, 'Deckard'
265
+
266
+ > If there are arguments, do like so
267
+
268
+ is? :sum[2,2], 4
269
+
270
+ > Or you can also use a block
271
+
272
+ is? {topic.sum(2, 2) == 4}
273
+
274
+ > If the expected value is `true` you don't have to state it
275
+
276
+ is? :simple?
277
+
278
+ ***
279
+
280
+ #### `before`
281
+ > Creates a base context
282
+
283
+ > Remains until `test` is invoked again
284
+
285
+ before { topic.do_some_factory_stuff }
286
+
287
+ ## "This is too easy! How can I make this more challenging?"
288
+
289
+ There is something about you that troubles me. Your manner is strange for a lonely code warrior.
290
+
291
+ ## How long till version 1.0?
292
+
293
+ When these features are completed
294
+
295
+ - Test class methods (only instance methods can be tested at this time)
296
+ - Blocks need to parsed back into a string
297
+ - Test more complex method stubbing
298
+ - Console color schemes
299
+ - HTML reporting
300
+
301
+ ## Design Decisions
302
+
303
+ #### Context Sensitive
304
+
305
+ I found that a lot of complexity with setting up tests is due to wrapping things in contexts. As tests are often executed sequentially from the top down anyway, this is often unnecessary.
306
+
307
+ This also eliminates teardown and tearup sequences, and can save a lot of time. Instead of executing our setup for every single test case, we only setup exactly what is needed once, and adjust as necessary between test cases. This works because we often readjust every state required to run the next test in order to maintain clarity. Meaning being able to hop in-between contexts is often unnecessary.
308
+
309
+ #### Self Documenting Tests
310
+
311
+ TestMe aims to reduce the use of code comments and test descriptions, and instead focusing more on self documenting code to describe our functionality.
312
+
313
+ Especially when describing contexts there is no need to re-describe them. Abstracting explicit tests and describing them with behaviour also makes tests much more difficult to maintain or delete.
314
+
315
+ #### DRY Contexts
316
+
317
+ In order to get around not having wrapped contexts we use re-usable contexts, that can be defined during the creation of the context itself. With other testing frameworks we have to define a method, however if you want to stay BDD this means you have to re-describe the context when you re-use it.
318
+
319
+ Cucumber solves this issue by allowing you to use a sentence structure to load a context. The only problem with this is you have to create steps for even the most specific contexts which are often un-reusable, and these contexts are specified away from the tests. This causes a lot of disorganisation and fragmentation without even the most diligent testers. It makes your test code bloat really fast, and makes it difficult to control. Even in professional teams, you will often see thousands of lines of dormant test code in a large project that nobody knew even existed.
320
+
321
+ TestMe draws on Cucumber's style while staying concise by allowing you to optionally define a description for the context, and just re-specify the description when re-using the context. Allowing the test to be self documenting. Keeping tests cases and logic together reduces fragmentation and makes tests easier to maintain.
322
+
323
+ ## Credit
324
+
325
+ Daniel Shuey - daniel.shuey@gmail.com
326
+
327
+ ## License
328
+
329
+ Copyright 2012 Daniel Shuey
330
+
331
+ Licensed under the Apache License, Version 2.0 (the "License");
332
+ you may not use this file except in compliance with the License.
333
+ You may obtain a copy of the License at
334
+
335
+ http://www.apache.org/licenses/LICENSE-2.0
336
+
337
+ Unless required by applicable law or agreed to in writing, software
338
+ distributed under the License is distributed on an "AS IS" BASIS,
339
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
340
+ See the License for the specific language governing permissions and
341
+ limitations under the License.
data/bin/testme ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if ARGV[0] == 'setup'
4
+
5
+ puts 'Creating bootstrap "/.testme"'
6
+
7
+ File.open('./.testme', 'w') {|f| f.write(
8
+ %q[require "testme"
9
+
10
+ TESTME_DIR = '/test/'
11
+ TESTME_FORMAT = :console
12
+ TESTME_COLORS = :default]
13
+ )}
14
+
15
+ puts 'Creating test folder "/test"'
16
+
17
+ Dir::mkdir('./test/') unless File.directory?("./test/") || File.exists?("./test/")
18
+
19
+ puts 'Creating empty test file "/app.test.rb"'
20
+
21
+ File.open('./test/app.test.rb', 'w') {|f| f.write(
22
+ ""
23
+ )}
24
+
25
+ puts 'Setup complete'
26
+
27
+ else
28
+
29
+ TESTME_RUNNING = true
30
+
31
+ if File.exists?("#{Dir.pwd}/.testme")
32
+ load "#{Dir.pwd}/.testme"
33
+ else
34
+ require "testme"
35
+ end
36
+
37
+ if ARGV.empty?
38
+ testme do
39
+ Dir["#{Dir.pwd}/#{TestMe::TESTME_DIR}/**/*.rb"].each{|f| load f }
40
+ end
41
+
42
+ else
43
+ ARGV.each do |arg|
44
+ @file = "#{Dir.pwd}/#{arg}"
45
+
46
+ # Check if directory
47
+ if File.directory? @file
48
+ Dir["#{@file}/**/*.rb"].each{|f| load f }
49
+ elsif File.exists? @file
50
+ if @file.include? '.test.rb'
51
+ testme do
52
+ load @file
53
+ end
54
+ else
55
+ require @file
56
+ end
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ end
data/lib/double.rb ADDED
@@ -0,0 +1,23 @@
1
+ module TestMe
2
+ class Double
3
+ def initialize subject=nil
4
+ @subject = subject if subject
5
+ @dict = {}
6
+ end
7
+
8
+ def method_missing(method, *args, &block)
9
+ if @subject
10
+ if @subject.respond_to?(method) && !@dict.key?(method)
11
+ return @subject.send(method, *args, &block)
12
+ end
13
+ end
14
+
15
+ if method.to_s =~ /=$/
16
+ return @dict[method.to_s.match(/^(.*)=$/)[1].to_sym] = args.first
17
+ else
18
+ return @dict[method] ||= Double.new
19
+ end
20
+ end
21
+
22
+ end
23
+ end
data/lib/formatter.rb ADDED
@@ -0,0 +1,143 @@
1
+ module TestMe
2
+ module Formatter
3
+
4
+ def self.create format
5
+ case format
6
+ when :none
7
+ return Formatter::None.new
8
+ when :text
9
+ return Formatter::Text.new
10
+ when :console
11
+ return Formatter::Console.new
12
+ when :html
13
+ return Formatter::HTML.new
14
+ end
15
+ end
16
+
17
+ class None
18
+ def test topic; end
19
+ def given *args, █ end
20
+ def also *args, █ end
21
+ def is? *args; end
22
+ def compile; end
23
+ end
24
+
25
+ class Html
26
+ def test topic; end
27
+ def given *args, █ end
28
+ def also *args, █ end
29
+ def is? *args; end
30
+ def compile; end
31
+ end
32
+
33
+ class Text
34
+ def test topic
35
+ log "test " + topic.name
36
+ end
37
+
38
+ def given desc=nil, stubs=nil, &block
39
+ log "given " + context_to_string(desc, stubs, &block)
40
+ end
41
+
42
+ def also desc=nil, stubs=nil, &block
43
+ log "also " + context_to_string(desc, stubs, &block)
44
+ end
45
+
46
+ def is? method, actual, expected
47
+ success = actual == expected
48
+
49
+ log 'is ' + method.to_s + ', ' + expected.to_s + '? ' + (success ? 'YES' : "NO, it was '#{actual}'")
50
+ end
51
+
52
+ def compile
53
+ #do nothing
54
+ end
55
+
56
+ private
57
+ def block_to_string &block
58
+ "(block)"
59
+ end
60
+
61
+ def context_to_string desc=nil, stubs=nil, &block
62
+ str = ""
63
+
64
+ if desc.class == String || desc.class == Symbol
65
+ str += ":#{desc}: "
66
+ end
67
+
68
+ if desc.class == Hash
69
+ stubs = desc
70
+ end
71
+
72
+ if stubs
73
+ str += stubs.map{|k,v| (k.to_s + ': ' + v.to_s)}.join(', ')
74
+ end
75
+
76
+ if block
77
+ str += block_to_string(&block)
78
+ end
79
+
80
+ return str
81
+ end
82
+ end
83
+
84
+ class Console
85
+ #TODO color_scheme
86
+
87
+ def test topic
88
+ log "\n test ".bright + topic.name.bright.color(250, 37, 115)
89
+ end
90
+
91
+ def given desc=nil, stubs=nil, &block
92
+ log " given " + context_to_string(desc, stubs, &block)
93
+ end
94
+
95
+ def also desc=nil, stubs=nil, &block
96
+ log " also " + context_to_string(desc, stubs, &block)
97
+ end
98
+
99
+ def is? method, actual, expected
100
+ success = actual == expected
101
+
102
+ log ' is '.bright + method.to_s + ', ' + expected.to_s.yellow + '? ' + (success ? 'YES'.bright.green : "NO, it was '#{actual}'".bright.red) + "\n\n"
103
+ end
104
+
105
+ def compile
106
+ #do nothing
107
+ end
108
+
109
+ private
110
+ def block_to_string &block
111
+ "(block)"
112
+ end
113
+
114
+ def log msg
115
+ puts msg
116
+ end
117
+
118
+ def context_to_string desc=nil, stubs=nil, &block
119
+ str = ""
120
+
121
+ if desc.class == String || desc.class == Symbol
122
+ str += ":#{desc}: ".blue
123
+ end
124
+
125
+ if desc.class == Hash
126
+ stubs = desc
127
+ end
128
+
129
+ if stubs
130
+ str += stubs.map{|k,v| (k.to_s + ': ' + v.to_s).bright}.join(', ') + ' '
131
+ end
132
+
133
+ if block
134
+ str += block_to_string(&block)
135
+ end
136
+
137
+ return str
138
+ end
139
+
140
+ end
141
+
142
+ end
143
+ end
data/lib/logic.rb ADDED
@@ -0,0 +1,141 @@
1
+ def testme &block
2
+ extend TestMe
3
+ block.call
4
+ end
5
+
6
+ module TestMe
7
+
8
+ def topic
9
+ @topic
10
+ end
11
+
12
+ def test topic
13
+ @topic = nil
14
+ @before = nil
15
+ @contexts = {}
16
+
17
+ @@formatter ||= Formatter::create(TESTME_FORMAT)
18
+ @@formatter.test topic
19
+
20
+ @topic_class = topic
21
+
22
+ if topic.instance_of? Module
23
+ o = Object.new
24
+ o.extend topic
25
+ @topic = Double.new(o)
26
+ end
27
+
28
+ if topic.instance_of? Class
29
+ @topic = Double.new(topic.new)
30
+ end
31
+
32
+ raise Exception, "Topic needs to be a Class or a Module" unless @topic
33
+ end
34
+
35
+ def given desc=nil, stubs=nil, &block
36
+ @before.call if @before
37
+
38
+ @@formatter.given desc, stubs, &block
39
+
40
+ @topic = Double.new(@topic_class.new)
41
+
42
+ if desc.class == String || desc.class == Symbol
43
+ if stubs == nil and block == nil
44
+ load_context desc
45
+ return
46
+ end
47
+
48
+ save_context desc, stubs, &block
49
+ elsif desc.class == Hash
50
+ stubs = desc
51
+ end
52
+
53
+ set_context stubs, &block
54
+ end
55
+
56
+ def also desc=nil, stubs=nil, &block
57
+ @@formatter.also desc, stubs, &block
58
+
59
+ if desc.class == String || desc.class == Symbol
60
+ if stubs == nil and block == nil
61
+ load_context desc
62
+ return
63
+ end
64
+
65
+ save_context desc, stubs, &block
66
+ elsif desc.class.name == 'Hash'
67
+ stubs = desc
68
+ end
69
+
70
+ set_context stubs, &block
71
+ end
72
+
73
+ def is? *args, &block
74
+ if block
75
+ method = block
76
+ result = block.call
77
+ else
78
+ if args[0].class == Hash
79
+ method = args[0].first[0]
80
+ expected = args[0].first[1]
81
+ actual = topic.send(method)
82
+ end
83
+
84
+ if args[0].class == Symbol
85
+ params = args[0].args
86
+ expected = args[1]
87
+ actual = topic.send(args[0], *params)
88
+
89
+ method = args[0].to_s + (params ? '(' + params.join(',') + ')' : '')
90
+ end
91
+
92
+ expected = true if expected.nil?
93
+ result = actual == expected
94
+ end
95
+
96
+ @@formatter.is? method, actual, expected
97
+
98
+ result
99
+ end
100
+
101
+ def before &block
102
+ @before = block
103
+ end
104
+
105
+ private
106
+ class Context
107
+ attr_accessor :name, :block, :stubs
108
+ end
109
+
110
+ def class_from_string(str)
111
+ str.split('::').inject(Object) do |mod, class_name|
112
+ mod.const_get(class_name)
113
+ end
114
+ end
115
+
116
+ def save_context name, stubs, &block
117
+ c = Context.new
118
+ c.name = name
119
+ c.stubs = stubs if stubs
120
+ c.block = block if block
121
+
122
+ @contexts[name] = c
123
+ end
124
+
125
+ def load_context name
126
+ c = @contexts[name]
127
+ set_context c.stubs, &c.block
128
+ end
129
+
130
+ def set_context stubs=nil, &block
131
+ if stubs
132
+ stubs.each do |k, v|
133
+ @topic.send("#{k}=".to_sym, v)
134
+ end
135
+ end
136
+
137
+ if block
138
+ block.call
139
+ end
140
+ end
141
+ end
data/lib/symbol.rb ADDED
@@ -0,0 +1,10 @@
1
+ class Symbol
2
+ def [] *args
3
+ @args = *args
4
+ self
5
+ end
6
+
7
+ def args
8
+ @args || []
9
+ end
10
+ end
data/lib/testme.rb ADDED
@@ -0,0 +1,87 @@
1
+ #********************************************************************#
2
+ #* *#
3
+ #* Test Me *#
4
+ #* *#
5
+ #********************************************************************#
6
+
7
+ module TestMe
8
+
9
+ # ---------------------------------------------------------------- #
10
+ # Alleviate the 'the big ball of mud'
11
+ # Test what you mean
12
+ # Pure Ruby DSL
13
+ # ---------------------------------------------------------------- #
14
+
15
+ # Retrieve the topic of the test
16
+ def topic; end
17
+ # ---------------------------------------------------------------- #
18
+
19
+ # Set the topic of the test
20
+ # ` test Player `
21
+ def test topic; end
22
+ # ---------------------------------------------------------------- #
23
+
24
+ # Provide a context
25
+ # stubbing an attribute
26
+ # ` given name: 'Flavie', class: 'Rogue' `
27
+ # ` given { topic.name = 'Flavie; topic.class = 'Rogue' } `
28
+ # calling a method
29
+ # ` given { topic.talk_to 'Deckard' } `
30
+ def given *args, █ end
31
+ # ---------------------------------------------------------------- #
32
+
33
+ # Provide a context over the existing context
34
+ # ` given name: 'Flavie' `
35
+ # ` also class: 'Rogue' `
36
+ def also *args, █ end
37
+ # ---------------------------------------------------------------- #
38
+
39
+ # Create an assertion
40
+ # ` is? name: 'Flavie' `
41
+ # ` is? :inventory[1], 'Arrows' `
42
+ # ` is? { topic.inventory(1) == 'Arrows' } `
43
+ def is? *args, █ end
44
+ # ---------------------------------------------------------------- #
45
+
46
+ end
47
+
48
+ # ---------------------------------------------------------------- #
49
+ # Inline Testing
50
+ # ---------------------------------------------------------------- #
51
+ def testme █ end
52
+
53
+ # ---------------------------------------------------------------- #
54
+ # Optional configuration
55
+ # ---------------------------------------------------------------- #
56
+ module TestMe
57
+ TESTME_DIR = '/test/' unless defined? TESTME_DIR
58
+ # default: '/test/'
59
+
60
+ TESTME_FORMAT = :console unless defined? TESTME_FORMAT
61
+ # choose how results are displayed
62
+ # options: :none, :text, :console
63
+ # default: :console
64
+
65
+ TESTME_COLORS = :default unless defined? TESTME_COLORS
66
+ # color scheme for console output
67
+ # options: :default
68
+ # default: :default
69
+ end
70
+
71
+ # ---------------------------------------------------------------- #
72
+
73
+ # ---------------------------------------------------------------- #
74
+ # This is here to disable inline tests at runtime
75
+ # ---------------------------------------------------------------- #
76
+ if defined? TESTME_RUNNING
77
+ # Gems
78
+ require 'rainbow'
79
+ require 'colorize'
80
+
81
+ # TestMe Library
82
+ require 'symbol'
83
+ require 'double'
84
+ require 'formatter'
85
+ require 'logic'
86
+ end
87
+ # ---------------------------------------------------------------- #
@@ -0,0 +1,54 @@
1
+ require File.expand_path('..', __FILE__) + '/spec_helper.rb'
2
+
3
+ describe TestMe::Double do
4
+ before :each do
5
+ @topic = TestMe::Double.new
6
+ end
7
+
8
+ describe '#method_missing' do
9
+ context 'with stub that returns 5' do
10
+ before :each do
11
+ @topic.test = 5
12
+ end
13
+
14
+ specify ('stub should == 5') { @topic.test.should == 5 }
15
+ end
16
+
17
+ context 'with stub chain that returns 5' do
18
+ before :each do
19
+ @topic.test.test2 = 5
20
+ end
21
+
22
+ specify ('stub chain should return 5') { @topic.test.test2.should == 5 }
23
+ end
24
+
25
+ context 'stub chaining over an object' do
26
+ before :each do
27
+ class TestObject
28
+ def hello
29
+ return 'hello'
30
+ end
31
+
32
+ def world
33
+ return 'world'
34
+ end
35
+ end
36
+
37
+ @topic.test = TestMe::Double.new(TestObject.new)
38
+ @topic.test.test2 = 5
39
+ end
40
+
41
+ specify ('stub chain should return 5') { @topic.test.test2.should == 5 }
42
+ specify ('original methods are still callable') { @topic.test.hello.should == 'hello' }
43
+
44
+ context 'overriding a method over an object with stub' do
45
+ before :each do
46
+ @topic.test.hello = 'goodbye'
47
+ end
48
+
49
+ specify ('method is overridden') { @topic.test.hello.should == 'goodbye' }
50
+ specify ('original methods are still callable') { @topic.test.world.should == 'world' }
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,6 @@
1
+ TESTME_RUNNING = true
2
+ TESTME_FORMAT = :none
3
+
4
+ require 'rubygems'
5
+ require 'bundler/setup'
6
+ Bundler.require :default
@@ -0,0 +1,159 @@
1
+ require File.expand_path('..', __FILE__) + '/spec_helper.rb'
2
+
3
+ class Mock; end
4
+
5
+ describe 'TestMe' do
6
+ before :each do
7
+ extend TestMe
8
+ test Mock
9
+ end
10
+
11
+ describe '#topic' do
12
+ specify('is created') {topic.class.name.should == 'TestMe::Double'}
13
+ end
14
+
15
+ describe '#given' do
16
+ it 'stubs one' do
17
+ given name: 'bob'
18
+ topic.name.should == 'bob'
19
+ end
20
+
21
+ it 'stubs multiple' do
22
+ given name: 'bob', surname: 'smith'
23
+ topic.name.should == 'bob'
24
+ topic.surname.should == 'smith'
25
+ end
26
+
27
+ context 'when given is repeated' do
28
+ before :each do
29
+ given name: 'bob'
30
+ given surname: 'smith'
31
+ end
32
+
33
+ it 'should clear previous context' do
34
+ topic.respond_to?(:name).should == false
35
+ end
36
+
37
+ it 'should create a new context' do
38
+ topic.surname.should == 'smith'
39
+ end
40
+ end
41
+
42
+ context 'when block is given' do
43
+ before :each do
44
+ given {topic.name = 'bob'}
45
+ end
46
+
47
+ it 'stubs one' do
48
+ given name: 'bob'
49
+ topic.name.should == 'bob'
50
+ end
51
+ end
52
+
53
+ context 'when description is given' do
54
+ before :each do
55
+ given :name_is_bob, name: 'bob'
56
+ end
57
+
58
+ it 'should save the context' do
59
+ given name: 'fred'
60
+ given :name_is_bob
61
+
62
+ topic.name.should == 'bob'
63
+ end
64
+ end
65
+ end
66
+
67
+ describe '#also' do
68
+ it 'retains the context' do
69
+ given name: 'bob'
70
+
71
+ topic.name.should == 'bob'
72
+ topic.surname.should_not == 'smith'
73
+
74
+ also surname: 'smith'
75
+
76
+ topic.name.should == 'bob'
77
+ topic.surname.should == 'smith'
78
+ end
79
+ end
80
+
81
+ describe '#is?' do
82
+ context 'when name is bob' do
83
+ before :each do
84
+ given name: 'bob'
85
+ end
86
+
87
+ it 'asserts name is bob' do
88
+ result = is? name: 'bob'
89
+ result.should == true
90
+ end
91
+
92
+ it 'asserts name is not fred' do
93
+ result = is? name: 'fred'
94
+ result.should_not == true
95
+ end
96
+ end
97
+
98
+ context 'when Block is given' do
99
+ before :each do
100
+ given name: 'bob'
101
+ @result = is? {topic.name == 'bob'}
102
+ end
103
+
104
+ specify('asserts correct result') { @result.should == true }
105
+ end
106
+ end
107
+
108
+ context 'class methods' do
109
+ before :each do
110
+ class ClassMethods
111
+ def self.hello
112
+ end
113
+ end
114
+
115
+ test ClassMethods, :self
116
+ end
117
+ end
118
+
119
+
120
+ context 'modified topic' do
121
+
122
+ before :each do
123
+ class ArgCounter
124
+ def count *args; return args.size; end
125
+ def true; return true; end
126
+ end
127
+
128
+ test ArgCounter
129
+ end
130
+
131
+ describe '#is?' do
132
+ context 'when Symbol is given' do
133
+ specify('parses 0 arguments'){(is? :true).should == true}
134
+ specify('parses 0 arguments'){(is? :count, 0).should == true}
135
+ specify('parses 1 argument with auto-true'){(is? :count[1]).should == false}
136
+ specify('parses 1 argument (string) with auto-true'){(is? :count['1']).should == false}
137
+ specify('parses 1 argument with answer'){(is? :count[1], 1).should == true}
138
+ specify('parses multiple arguments'){(is? :count[1,1,1], 3).should == true}
139
+ end
140
+ end
141
+
142
+ end
143
+
144
+ describe '#test' do
145
+ before :each do
146
+ module Mock2
147
+ def hello; return 'hello'; end
148
+ end
149
+ end
150
+
151
+ it 'test double of Module' do
152
+ test Mock2
153
+ topic.hello.should == 'hello'
154
+ end
155
+ end
156
+
157
+ end
158
+
159
+
data/test/app.test.rb ADDED
File without changes
data/testme.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.unshift(File.expand_path("../lib", __FILE__))
3
+ require 'date'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'testme'
7
+
8
+ s.version = begin
9
+ revision = (`git log --pretty=format:'' | wc -l`.to_f / 20).round(2).to_s
10
+ "0.#{revision}"
11
+ end
12
+
13
+ s.date = Date.today.to_s
14
+ s.authors = ['Daniel Shuey']
15
+ s.email = ['daniel.shuey@gmail.com']
16
+ s.summary = 'Minimalistic testing framework'
17
+
18
+ s.description = <<-END
19
+ Minimalistic testing framework
20
+ END
21
+
22
+ s.homepage = 'http://github.com/danielshuey/testme'
23
+
24
+ s.files = `git ls-files`.split("\n")
25
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
26
+ s.require_paths = %w(lib)
27
+
28
+ s.add_runtime_dependency('rainbow', ['>= 1.1.3'])
29
+ s.add_runtime_dependency('colorize', ['>= 0.5.8'])
30
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: testme
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.6
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Daniel Shuey
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rainbow
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.1.3
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.1.3
30
+ - !ruby/object:Gem::Dependency
31
+ name: colorize
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.5.8
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.5.8
46
+ description: ! ' Minimalistic testing framework
47
+
48
+ '
49
+ email:
50
+ - daniel.shuey@gmail.com
51
+ executables:
52
+ - testme
53
+ extensions: []
54
+ extra_rdoc_files: []
55
+ files:
56
+ - .gitignore
57
+ - .rspec
58
+ - .rvmrc
59
+ - .testme
60
+ - Gemfile
61
+ - LICENSE
62
+ - README.md
63
+ - bin/testme
64
+ - lib/double.rb
65
+ - lib/formatter.rb
66
+ - lib/logic.rb
67
+ - lib/symbol.rb
68
+ - lib/testme.rb
69
+ - spec/double_spec.rb
70
+ - spec/spec_helper.rb
71
+ - spec/testme_spec.rb
72
+ - test/app.test.rb
73
+ - testme.gemspec
74
+ homepage: http://github.com/danielshuey/testme
75
+ licenses: []
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ segments:
87
+ - 0
88
+ hash: 1026832301
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ segments:
96
+ - 0
97
+ hash: 1026832301
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 1.8.24
101
+ signing_key:
102
+ specification_version: 3
103
+ summary: Minimalistic testing framework
104
+ test_files: []