pork 0.1.0 → 0.9.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.
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)