pork 0.1.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bcad9c9f6829b54485ba10be4c5f66f353c55b15
4
- data.tar.gz: e4e717a01aa1816bbdcb916d55cb062cc1f0ca34
3
+ metadata.gz: 0720abd3578e820759c2cec35d565a41e41d6f79
4
+ data.tar.gz: 3abb0dc9d216004aa1fa11590fef142671111168
5
5
  SHA512:
6
- metadata.gz: edcf6930fe9463137140ef9ed0f6ff7693d6d45d710c15a86fe8332e9ac8d2e60b37b7d39467ecf09c86d7dfe82ea60d229ed1a231c2dcc1519bdadf0de57220
7
- data.tar.gz: ab819c314b0fbca15889e258fefadb68238d50bded7fa105a4fa882216038cbb5140959e8cf6bb7eeb05f8a00634740b1b54ac612987f05527307a44470998eb
6
+ metadata.gz: 6387d2c2049e7bbab044bcfba005616e3a236b9f58f2303c06fbd6b47613ee277c8219f098b49671e5011f94c3dab80aa449ffa8effb139da8885a1fc138355f
7
+ data.tar.gz: e4e2189fc58eede08bdcf3d65580ef1728474728fce82db3dae57f5ab013b6611b4385b5b16700ab54feba4b97e9cd1ed18470ea05ad633622f78222bdbc09a4
@@ -0,0 +1 @@
1
+ /pkg/
@@ -0,0 +1,9 @@
1
+ # CHANGES
2
+
3
+ ## Pork 0.9.0 -- 2014-07-11
4
+
5
+ * First serious release! Bunch of updates. Nearly complete.
6
+
7
+ ## Pork 0.1.0 -- 2014-07-09
8
+
9
+ * Birthday!
data/README.md CHANGED
@@ -10,13 +10,140 @@ by Lin Jen-Shin ([godfat](http://godfat.org))
10
10
 
11
11
  ## DESCRIPTION:
12
12
 
13
- [Bacon][] reimplemented in an even more lightweight manner.
13
+ Pork -- Simple and clean and modular testing library.
14
+
15
+ [Bacon][] reimplemented around 250 lines of code.
14
16
 
15
17
  [Bacon]: https://github.com/chneukirchen/bacon
16
18
 
19
+ ## DESIGN:
20
+
21
+ * Consistency over convenience.
22
+ * Avoid polluting anything by default to make integration easier.
23
+ * The less codes the better.
24
+
17
25
  ## WHY?
18
26
 
19
- [Bacon][] has some issues which can't be easily worked around.
27
+ [Bacon][] has some issues which can't be easily worked around. For example,
28
+ the context of the running test is not consistent in nested describe block.
29
+
30
+ This won't work in Bacon:
31
+
32
+ ``` ruby
33
+ require 'bacon'
34
+ Bacon.summary_on_exit
35
+
36
+ # This would include to all context,
37
+ # so that we don't have to include in all describe block.
38
+ Bacon::Context.include Module.new{
39
+ def in_module
40
+ object_id
41
+ end
42
+ }
43
+
44
+ describe 'A' do
45
+ def in_describe
46
+ object_id
47
+ end
48
+
49
+ describe 'B' do
50
+ should 'have the same context' do
51
+ in_module.should == in_describe # FAIL!
52
+ end
53
+ end
54
+ end
55
+ ```
56
+
57
+ But this works in Pork:
58
+
59
+ ``` ruby
60
+ require 'pork/auto'
61
+
62
+ describe 'A' do
63
+ include Module.new{
64
+ def in_module
65
+ object_id
66
+ end
67
+ }
68
+
69
+ def in_describe
70
+ object_id
71
+ end
72
+
73
+ describe 'B' do
74
+ would 'have the same context' do
75
+ in_module.should == in_describe
76
+ end
77
+
78
+ def in_nested_describe
79
+ object_id
80
+ end
81
+
82
+ would 'respond_to? in_nested_describe' do
83
+ should.respond_to?(:in_nested_describe)
84
+ end
85
+ end
86
+
87
+ # Pork is completely tree structured, nested methods can't be accessed
88
+ # from outside of the scope.
89
+ would 'not respond_to? in_nested_describe' do
90
+ should.not.respond_to?(:in_nested_describe)
91
+ end
92
+ end
93
+
94
+ describe 'C' do
95
+ # Also, we're not forced to include something in all describe blocks.
96
+ # If we want, we could do this instead: `Pork::Executor.include(Module.new)`
97
+ # That would be the same as including in `Bacon::Context`
98
+ would 'not respond_to? in_module nor in_describe' do
99
+ should.not.respond_to?(:in_module)
100
+ should.not.respond_to?(:in_describe)
101
+ end
102
+ end
103
+ ```
104
+
105
+ Also, Bacon won't clear instance variables as well.
106
+
107
+ ``` ruby
108
+ require 'bacon'
109
+ Bacon.summary_on_exit
110
+
111
+ describe 'instance variables in tests' do
112
+ before do
113
+ @a ||= 0
114
+ @a += 1
115
+ end
116
+
117
+ should 'always be 1' do
118
+ @a.should == 1
119
+ end
120
+
121
+ should 'always be 1' do
122
+ @a.should == 1 # FAIL!
123
+ end
124
+ end
125
+ ```
126
+
127
+ Every tests would be a whole new instance for Pork as expected:
128
+
129
+ ``` ruby
130
+ require 'pork/auto'
131
+
132
+ describe 'instance variables in tests' do
133
+ before do
134
+ @a ||= 0
135
+ @a += 1
136
+ end
137
+
138
+ would 'always be 1' do
139
+ @a.should == 1
140
+ end
141
+
142
+ would 'always be 1' do
143
+ @a.should == 1
144
+ end
145
+ end
146
+ ```
20
147
 
21
148
  ## REQUIREMENTS:
22
149
 
@@ -28,6 +155,457 @@ by Lin Jen-Shin ([godfat](http://godfat.org))
28
155
 
29
156
  ## SYNOPSIS:
30
157
 
158
+ A simple example:
159
+
160
+ ``` ruby
161
+ require 'pork/auto'
162
+
163
+ describe Array do
164
+ before do
165
+ @array = []
166
+ end
167
+
168
+ after do
169
+ @array.clear
170
+ end
171
+
172
+ would 'be empty' do
173
+ @array.should.empty?
174
+ @array.should.not.include? 1
175
+ end
176
+
177
+ would 'have zero size' do
178
+ # We prefer `eq` here over `==` to avoid warnings from Ruby
179
+ @array.size.should.eq 0
180
+ end
181
+
182
+ would 'raise IndexError for fetching from non-existing index' do
183
+ should.raise(IndexError){ @array.fetch(0) }.message.
184
+ should.match(/\d+/)
185
+
186
+ # Alternatively:
187
+ lambda{ @array.fetch(0) }.should.raise(IndexError).message.
188
+ should.match(/\d+/)
189
+ end
190
+ end
191
+ ```
192
+
193
+ Copy and paste for modularity:
194
+
195
+ ``` ruby
196
+ require 'pork/auto'
197
+
198
+ copy 'empty test' do |error|
199
+ after do
200
+ @data.clear
201
+ end
202
+
203
+ would 'be empty' do
204
+ @data.should.empty?
205
+ @data.should.not.include? 1
206
+ end
207
+
208
+ would 'have zero size' do
209
+ # We prefer `eq` here over `==` to avoid warnings from Ruby
210
+ @data.size.should.eq 0
211
+ end
212
+
213
+ would "raise #{error} for fetching from non-existing index" do
214
+ should.raise(error){ @data.fetch(0) }.message.
215
+ should.match(/\d+/)
216
+
217
+ # Alternatively:
218
+ lambda{ @data.fetch(0) }.should.raise(error).message.
219
+ should.match(/\d+/)
220
+ end
221
+ end
222
+
223
+ describe Array do
224
+ before do
225
+ @data = []
226
+ end
227
+
228
+ paste 'empty test', IndexError
229
+ end
230
+
231
+ describe Hash do
232
+ before do
233
+ @data = {}
234
+ end
235
+
236
+ paste 'empty test', KeyError
237
+ end
238
+ ```
239
+
240
+ Context sensitive paste:
241
+
242
+ ``` ruby
243
+ require 'pork/auto'
244
+
245
+ copy 'empty test' do |error|
246
+ paste :setup_data # it would search from the pasted context
247
+
248
+ would "raise #{error} for fetching from non-existing index" do
249
+ should.raise(error){ @data.fetch(0) }.message.
250
+ should.match(/\d+/)
251
+ end
252
+ end
253
+
254
+ describe Array do
255
+ copy :setup_data do
256
+ before do
257
+ @data = []
258
+ end
259
+ end
260
+
261
+ paste 'empty test', IndexError
262
+ end
263
+
264
+ describe Hash do
265
+ copy :setup_data do
266
+ before do
267
+ @data = {}
268
+ end
269
+ end
270
+
271
+ paste 'empty test', KeyError
272
+ end
273
+ ```
274
+
275
+ ## The API
276
+
277
+ ### Pork::API.describe
278
+
279
+ So this creates a test suite which should be containing various test cases
280
+ (`Pork::API.would`). The argument represents the description of the test
281
+ suite, which accepts anything could be converted to a string. The _default_
282
+ description is `:default` (which would be converted to `'default: '`)
283
+
284
+ Each `describe` block would create a new subclass of `Pork::Executor` for
285
+ isolating test suites. Each nested `describe` block would be a subclass of
286
+ its parent `Pork::Executor`.
287
+
288
+ ``` ruby
289
+ require 'pork/auto'
290
+
291
+ describe do
292
+ would 'be default: for the default description' do
293
+ self.class.desc.should.eq 'default: '
294
+ end
295
+ end
296
+ ```
297
+
298
+ ### Pork::API.would
299
+
300
+ Essentially runs a test case. It could also be called in the top-level
301
+ without being contained in a `describe` block. The argument represents the
302
+ description of the test case, which accepts anything could be converted to
303
+ a string. The _default_ description is also `:default`.
304
+
305
+ Each `would` block would be run inside a new instance of the describing
306
+ `Pork::Executor` to isolate instance variables.
307
+
308
+ ``` ruby
309
+ require 'pork/auto'
310
+
311
+ would do
312
+ desc.should.eq :default
313
+ end
314
+ ```
315
+
316
+ ### Pork::API.before
317
+
318
+ Each `before` block would be called before each `would` block (test case).
319
+ You would probably want to setup stuffs inside `before` blocks.
320
+
321
+ Each nested `describe` would also run parents' `before` blocks as well.
322
+
323
+ ``` ruby
324
+ require 'pork/auto'
325
+
326
+ describe do
327
+ before do
328
+ @a = 0
329
+ end
330
+
331
+ describe do
332
+ before do
333
+ @a.should.eq 0
334
+ @a += 1
335
+ end
336
+
337
+ would do
338
+ @a.should.eq 1
339
+ end
340
+ end
341
+ end
342
+ ```
343
+
344
+ ### Pork::API.after
345
+
346
+ Each `after` block would be called after each `would` block (test case).
347
+ You would probably want to cleanup stuffs inside `after` blocks.
348
+
349
+ Each nested `describe` would also run parents' `after` block as well.
350
+
351
+ ``` ruby
352
+ require 'pork/auto'
353
+
354
+ describe do
355
+ after do
356
+ @a.should.eq 1
357
+ @a += 1
358
+ end
359
+
360
+ describe do
361
+ after do
362
+ @a.should.eq 2
363
+ end
364
+
365
+ would do
366
+ @a = 1
367
+ @a.should.eq 1
368
+ end
369
+ end
370
+ end
371
+ ```
372
+
373
+ ### Pork::API.copy and Pork::API.paste
374
+
375
+ It could be a bit confusing at first, but just think of `copy` as a way to
376
+ store the block with a name (default is `:default`), and whenever we `paste`,
377
+ the stored block would be called at the context where we paste.
378
+
379
+ The name could be anything, strings, symbols, numbers, classes, anything.
380
+
381
+ The block passed to `copy` could have parameters. The second through the last
382
+ arguments passed to `paste` would be passing to the block saved in copy.
383
+
384
+ ``` ruby
385
+ require 'pork/auto'
386
+
387
+ copy :default do |a=0, b=1|
388
+ before do
389
+ @a, @b = a, b
390
+ end
391
+
392
+ def f
393
+ @a + @b
394
+ end
395
+ end
396
+
397
+ describe do
398
+ paste :default, 1, 0
399
+
400
+ would do
401
+ f.should.eq 1
402
+ end
403
+ end
404
+ ```
405
+
406
+ ### Pork::Executor#skip
407
+
408
+ At times we might want to skip some tests while leave the codes there without
409
+ removing them or commenting them out. This is where `skip` would be helpful.
410
+
411
+ ``` ruby
412
+ require 'pork/auto'
413
+
414
+ describe do
415
+ would do
416
+ skip
417
+ end
418
+ end
419
+ ```
420
+
421
+ ### Pork::Executor#ok
422
+
423
+ Because Pork would complain if a test case does not have any assertions,
424
+ sometimes we might want to tell Pork that it's ok because we've already
425
+ made some assertions without using Pork's assertions. Then we'll want `ok`.
426
+
427
+ The reason why complaining about missing assertions is useful is because
428
+ sometimes we might expect some assertions would be made in a certain flow.
429
+ If the flow is not correctly called, we could miss assertions. So it's good
430
+ to explicitly claim that we don't care about assertions rather than letting
431
+ them slip through implicitly.
432
+
433
+ ``` ruby
434
+ require 'pork/auto'
435
+
436
+ describe do
437
+ would do
438
+ 'verify with mocks, and pork has no idea about that'.to_s
439
+ ok
440
+ end
441
+ end
442
+ ```
443
+
444
+ ### Pork::Executor#flunk
445
+
446
+ If we're writing program carefully, there are a few cases where a condition
447
+ would never meet. We could `raise "IMPOSSIBLE"` or we could simply call
448
+ `flunk`.
449
+
450
+ ``` ruby
451
+ require 'pork/auto'
452
+
453
+ describe do
454
+ would do
455
+ should.raise(Pork::Error){ flunk }
456
+ end
457
+ end
458
+ ```
459
+
460
+ ### Pork::Should#satisfy
461
+
462
+ If we want to have custom verifier, that is it.
463
+
464
+ ``` ruby
465
+ require 'pork/auto'
466
+
467
+ describe do
468
+ divided_by_2 = lambda{ |n| n % 2 == 0 }
469
+
470
+ would do
471
+ 2.should.satisfy(&divided_by_2)
472
+ end
473
+ end
474
+ ```
475
+
476
+ ### Pork::Should#not
477
+
478
+ An easy way to negate the expectation.
479
+
480
+ ``` ruby
481
+ require 'pork/auto'
482
+
483
+ would{ 1.should.not.eq 2 }
484
+ ```
485
+
486
+ ### Pork::Should#eq
487
+
488
+ To avoid warnings from Ruby, using `eq` instead of `==`. It's fine if you
489
+ still prefer using `==` if you don't care about warnings.
490
+
491
+ ``` ruby
492
+ require 'pork/auto'
493
+
494
+ would{ 1.should.eq 1 }
495
+ ```
496
+
497
+ ### Pork::Should#lt
498
+
499
+ To avoid warnings from Ruby, using `lt` instead of `<`. It's fine if you
500
+ still prefer using `<` if you don't care about warnings.
501
+
502
+ ``` ruby
503
+ require 'pork/auto'
504
+
505
+ would{ 1.should.lt 2 }
506
+ ```
507
+
508
+ ### Pork::Should#gt
509
+
510
+ To avoid warnings from Ruby, using `gt` instead of `>`. It's fine if you
511
+ still prefer using `>` if you don't care about warnings.
512
+
513
+ ``` ruby
514
+ require 'pork/auto'
515
+
516
+ would{ 1.should.gt 0 }
517
+ ```
518
+
519
+ ### Pork::Should#lte
520
+
521
+ To avoid warnings from Ruby, using `lte` instead of `<=`. It's fine if you
522
+ still prefer using `<=` if you don't care about warnings.
523
+
524
+ ``` ruby
525
+ require 'pork/auto'
526
+
527
+ would{ 1.should.lte 1 }
528
+ ```
529
+
530
+ ### Pork::Should#gte
531
+
532
+ To avoid warnings from Ruby, using `gte` instead of `>=`. It's fine if you
533
+ still prefer using `>=` if you don't care about warnings.
534
+
535
+ ``` ruby
536
+ require 'pork/auto'
537
+
538
+ would{ 1.should.gte 1 }
539
+ ```
540
+
541
+ ### Pork::Should#raise
542
+
543
+ Expect for exceptions! There are two ways to call it. Either you could use
544
+ lambda to wrap the questioning expression, or you could simply pass a block
545
+ as the questioning expression.
546
+
547
+ ``` ruby
548
+ require 'pork/auto'
549
+
550
+ describe 'Pork::Should#raise' do
551
+ would 'check with a block' do
552
+ e = should.raise(RuntimeError){ raise "nnf" }
553
+ e.should.message.include?("nnf")
554
+ end
555
+
556
+ would 'check with a lambda' do
557
+ e = lambda{ raise "nnf" }.should.raise(RuntimeError)
558
+ e.should.message.include?("nnf")
559
+ end
560
+ end
561
+ ```
562
+
563
+ ### Pork::Should#throw
564
+
565
+ Expect for something to be thrown. There are two ways to call it. Either
566
+ you could use lambda to wrap the questioning expression, or you could
567
+ simply pass a block as the questioning expression.
568
+
569
+ ``` ruby
570
+ require 'pork/auto'
571
+
572
+ describe 'Pork::Should#throw' do
573
+ would 'check with a block' do
574
+ e = should.throw(:nnf){ throw :nnf, 0 }
575
+ e.should.eq [:nnf, 0]
576
+ end
577
+
578
+ would 'check with a lambda' do
579
+ e = lambda{ throw :nnf, 1 }.should.throw(:nnf)
580
+ e.should.eq [:nnf, 1]
581
+ end
582
+ end
583
+ ```
584
+
585
+ ### Pork.report
586
+
587
+ Report the summary from the tests. Usually you would want to call this at
588
+ program exit, therefore most of the time you would want `Pork.report_at_exit`
589
+ instead, unless you want to report the summary without exiting.
590
+
591
+ Note that you would probably want to run `Pork.stats.start` at the beginning
592
+ of your tests as well if you want to handle `Pork.report` manually.
593
+
594
+ ### Pork.report_at_exit
595
+
596
+ Basically simply call `Pork.stats.start` and setup `Pork.report` at exit,
597
+ and exit with 0 if no error occurs or N for N errors and failures.
598
+
599
+ If you also plan to pollute the top-level namespace so that you could simply
600
+ call `describe` on top-level instead of calling it `Pork::API.describe`,
601
+ you would probably want to simply `require 'pork/auto'` which is essentially:
602
+
603
+ ``` ruby
604
+ require 'pork'
605
+ extend Pork::API
606
+ Pork.report_at_exit
607
+ ```
608
+
31
609
  ## CONTRIBUTORS:
32
610
 
33
611
  * Lin Jen-Shin (@godfat)