Peeja-for_each_row 0.0.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.
@@ -0,0 +1,102 @@
1
+ `for_each_row`: Tables for your specs
2
+ =====================================
3
+
4
+ This gem provides a single method, `#for_each_row`, which lets you run a block with the values from a table. It's ideal for specs or tests (though in theory it could be used for anything). It looks like this:
5
+
6
+ for_each_row <<-TABLE do |number1, number2, sum|
7
+ |1, 2, 3 |
8
+ |5, 7, 12 |
9
+ TABLE
10
+ (number2 + number2).should == sum
11
+ end
12
+
13
+ Getting it
14
+ ----------
15
+
16
+ First, install the gem
17
+
18
+ sudo gem install Peeja-for_each_row -s http://gems.github.com"
19
+
20
+ Then include the module in your spec or test environment. For RSpec, this looks like:
21
+
22
+ Spec::Runner.configure do |config|
23
+ config.include ForEachRow
24
+ end
25
+
26
+ I'm not sure what the official way to do this in Test::Unit is, since I don't use it, but you'll figure it out. You're a smart one, you.
27
+
28
+
29
+ Example
30
+ -------
31
+
32
+ A good spec is not written to be read by Ruby. A good spec is written to be read by people. Specs are not merely tests; they are a tool for communicating with other developers. A good test exercises the full behavior of an object. A good spec also explains the behavior.
33
+
34
+ Sometimes, though, a spec has to get wordy to be complete. For instance, let's say we're spec'ing a bomb detonator. The detonator has two keys which need to be turned and a safety which needs to be turned off for the big red button to function. The spec looks something like this (full spec in `examples/detonator`):
35
+
36
+ describe Detonator do
37
+ before(:each) do
38
+ @detonator = Detonator.new
39
+ end
40
+
41
+ it "should not work if the first key hasn't been turned" do
42
+ @detonator.turn_key(2)
43
+ lambda { @detonator.push_big_red_button }.should_not raise_error
44
+ end
45
+
46
+ # ...
47
+
48
+ it "should work if both keys have been turned and the safety is turned off" do
49
+ @detonator.turn_key(1)
50
+ @detonator.turn_key(2)
51
+ @detonator.turn_off_safety
52
+ lambda { @detonator.push_big_red_button }.should raise_error(Explosion)
53
+ end
54
+ end
55
+
56
+ We're doing the same thing over and over again. It would be nice to be able to express all of this in a single table, where each row describes a case. That's what `for_each_row` is for. Here's the same thing, using `for_each_row`:
57
+
58
+ describe Detonator do
59
+
60
+ # Note that this table checks more cases than wordy_detonator_spec.rb.
61
+
62
+ it "should only work if both keys have been turned and the safety is turned off" do
63
+ for_each_row <<-TABLE do |turned_key1, turned_key2, safety_on, explosion|
64
+ |false, false, true, false |
65
+ |true, false, true, false |
66
+ |false, true, true, false |
67
+ |true, true, true, false |
68
+ |false, false, false, false |
69
+ |true, false, false, false |
70
+ |false, true, false, false |
71
+ |true, true, false, true |
72
+ TABLE
73
+ detonator = Detonator.new
74
+
75
+ detonator.turn_key(1) if turned_key1
76
+ detonator.turn_key(2) if turned_key2
77
+ detonator.turn_off_safety unless safety_on
78
+
79
+ if explosion
80
+ lambda { detonator.push_big_red_button }.should raise_error(Explosion)
81
+ else
82
+ lambda { detonator.push_big_red_button }.should_not raise_error(Explosion)
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+
89
+ "So this is always more readable than writing out the cases?"
90
+ -------------------------------------------------------------
91
+
92
+ Almost certainly not. This isn't math, this is writing. Every spec and example is a little different, and you'll have to decide what reads better. Whatever is clearest in any particular case is the way to go. This is just another tool in your belt. To be honest, having just written the the thing, I don't know how useful it is yet. But it seems like it's worth trying out.
93
+
94
+
95
+ Credits
96
+ -------
97
+
98
+ Written by Peter Jaros
99
+ Portions &copy; 2009 Peter Jaros
100
+ Portions &copy; 2009 drop.io, Inc.
101
+
102
+ Released under the MIT License. See `LICENSE` for details.
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 0
3
+ :patch: 0
4
+ :major: 0
@@ -0,0 +1,18 @@
1
+ module ForEachRow
2
+ # Example:
3
+ # for_each_row <<-TABLE do |number1, number2, sum|
4
+ # |1, 2, 3 |
5
+ # |5, 7, 12 |
6
+ # TABLE
7
+ # (number2 + number2).should == sum
8
+ # end
9
+
10
+ def for_each_row(table, &block)
11
+ table.split("\n").each do |row|
12
+ if row.strip =~ /^\|(.*)\|$/
13
+ cell_values = $1.split(",").map { |cell| eval(cell, block) }
14
+ block.call *cell_values
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,42 @@
1
+ $: << File.dirname(__FILE__) + "/../lib"
2
+
3
+ require 'rubygems'
4
+ require 'spec'
5
+ require 'for_each_row'
6
+
7
+ describe ForEachRow do
8
+ include ForEachRow
9
+
10
+ it "should call the block once with each row" do
11
+ should_receive(:called_with).once.with("foo", "bar", "foobar")
12
+ should_receive(:called_with).once.with("baz", "bax", "bazbax")
13
+
14
+ for_each_row <<-TABLE do |string1, string2, full_string|
15
+ |"foo", "bar", "foobar" |
16
+ |"baz", "bax", "bazbax" |
17
+ TABLE
18
+ called_with(string1, string2, full_string)
19
+ end
20
+ end
21
+
22
+ describe "should interpret" do
23
+ def should_interpret(from, to, some_local=nil)
24
+ should_receive(:called_with) { |value| value.should eql(to) }
25
+
26
+ for_each_row <<-TABLE do |value |
27
+ |#{from}|
28
+ TABLE
29
+ called_with(value)
30
+ end
31
+ end
32
+
33
+ specify "strings" do should_interpret(%|"foo"|, "foo") end
34
+ specify "integers" do should_interpret(%|5|, 5) end
35
+ specify "floats" do should_interpret(%|5.0|, 5.0) end
36
+ specify "symbols" do should_interpret(%|:bar|, :bar) end
37
+
38
+ specify "local varables" do should_interpret(%|some_local|, :bar, :bar) end
39
+ specify "self" do should_interpret(%|self|, self) end
40
+ specify "methods of self" do should_interpret(%|object_id|, self.object_id) end
41
+ end
42
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: Peeja-for_each_row
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Peter Jaros
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-03 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A method for specifying Fit-esque tables in Ruby
17
+ email: peter.a.jaros@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - Readme.markdown
26
+ - VERSION.yml
27
+ - lib/for_each_row.rb
28
+ - spec/for_each_row_spec.rb
29
+ - spec/spec.opts
30
+ has_rdoc: true
31
+ homepage:
32
+ post_install_message:
33
+ rdoc_options:
34
+ - --inline-source
35
+ - --charset=UTF-8
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: "0"
43
+ version:
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ requirements: []
51
+
52
+ rubyforge_project:
53
+ rubygems_version: 1.2.0
54
+ signing_key:
55
+ specification_version: 2
56
+ summary: A method for specifying Fit-esque tables in Ruby
57
+ test_files: []
58
+