rspec 0.5.11 → 0.5.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/CHANGES +12 -0
  2. data/README +4 -2
  3. data/Rakefile +14 -4
  4. data/bin/spec +7 -7
  5. data/bin/test2spec +13 -8
  6. data/lib/spec/api/helper/diff.rb +53 -0
  7. data/lib/spec/api/helper/instance_helper.rb +11 -11
  8. data/lib/spec/api/helper/instance_negator.rb +11 -11
  9. data/lib/spec/api/helper/kind_helper.rb +11 -11
  10. data/lib/spec/api/helper/kind_negator.rb +11 -11
  11. data/lib/spec/api/helper/respond_helper.rb +11 -11
  12. data/lib/spec/api/helper/respond_negator.rb +11 -11
  13. data/lib/spec/api/helper/should_base.rb +6 -6
  14. data/lib/spec/api/helper/should_helper.rb +35 -35
  15. data/lib/spec/api/helper/should_negator.rb +20 -20
  16. data/lib/spec/rake/spectask.rb +15 -6
  17. data/lib/spec/runner.rb +1 -0
  18. data/lib/spec/runner/backtrace_tweaker.rb +2 -0
  19. data/lib/spec/runner/base_text_formatter.rb +3 -1
  20. data/lib/spec/runner/html_formatter.rb +153 -0
  21. data/lib/spec/runner/option_parser.rb +9 -2
  22. data/lib/spec/runner/progress_bar_formatter.rb +4 -0
  23. data/lib/spec/runner/rdoc_formatter.rb +3 -0
  24. data/lib/spec/runner/reporter.rb +5 -5
  25. data/lib/spec/runner/specdoc_formatter.rb +3 -0
  26. data/lib/spec/test_to_spec/sexp_transformer.rb +1 -0
  27. data/lib/spec/test_to_spec/translation_test_runner.rb +10 -2
  28. data/lib/spec/version.rb +1 -1
  29. data/test/spec/api/helper/arbitrary_predicate_test.rb +49 -73
  30. data/test/spec/api/helper/diff_test.rb +60 -0
  31. data/test/spec/api/helper/equality_test.rb +14 -0
  32. data/test/spec/api/helper/should_have_test.rb +0 -29
  33. data/test/spec/api/helper/typing_test.rb +87 -87
  34. data/test/spec/api/sugar_test.rb +0 -6
  35. data/test/spec/runner/backtrace_tweaker_test.rb +8 -2
  36. data/test/spec/runner/html_formatter_test.rb +47 -0
  37. data/test/spec/runner/option_parser_test.rb +0 -5
  38. data/test/test_classes.rb +73 -0
  39. data/test/test_helper.rb +3 -0
  40. metadata +8 -49
  41. data/doc/README +0 -3
  42. data/doc/config.yaml +0 -2
  43. data/doc/plugin/syntax.rb +0 -60
  44. data/doc/plugin/version.rb +0 -19
  45. data/doc/src/core_team.page +0 -31
  46. data/doc/src/default.css +0 -199
  47. data/doc/src/default.template +0 -31
  48. data/doc/src/documentation/index.page +0 -188
  49. data/doc/src/documentation/meta.info +0 -22
  50. data/doc/src/documentation/mocks.page +0 -287
  51. data/doc/src/documentation/underscores.page +0 -21
  52. data/doc/src/examples.page +0 -9
  53. data/doc/src/images/David_and_Aslak.jpg +0 -0
  54. data/doc/src/images/Whats_That_Dude.jpg +0 -0
  55. data/doc/src/images/ducks1.png +0 -0
  56. data/doc/src/images/ul.gif +0 -0
  57. data/doc/src/index.page +0 -74
  58. data/doc/src/meta.info +0 -33
  59. data/doc/src/tools/index.page +0 -49
  60. data/doc/src/tools/meta.info +0 -18
  61. data/doc/src/tools/rails.page +0 -132
  62. data/doc/src/tools/rake.page +0 -21
  63. data/doc/src/tools/rcov.page +0 -28
  64. data/doc/src/tools/spec.page +0 -129
  65. data/doc/src/tools/test2spec.page +0 -103
  66. data/doc/src/tutorials/index.page +0 -52
  67. data/doc/src/tutorials/meta.info +0 -36
  68. data/doc/src/tutorials/notes.txt +0 -263
  69. data/doc/src/tutorials/stack.rb +0 -11
  70. data/doc/src/tutorials/stack_01.page +0 -226
  71. data/doc/src/tutorials/stack_02.page +0 -182
  72. data/doc/src/tutorials/stack_03.page +0 -283
  73. data/doc/src/tutorials/stack_04.page +0 -164
  74. data/doc/src/tutorials/stack_04.page.orig +0 -123
  75. data/doc/src/tutorials/stack_05.page +0 -90
  76. data/doc/src/tutorials/stack_05.page.orig +0 -124
  77. data/doc/src/tutorials/stack_06.page +0 -359
  78. data/doc/src/tutorials/stack_06.page.orig +0 -359
  79. data/doc/src/tutorials/stack_spec.rb +0 -25
  80. data/doc/src/ul.gif +0 -0
@@ -1,11 +0,0 @@
1
- class Stack
2
- def empty?
3
- @item.nil?
4
- end
5
- def push item
6
- @item = item
7
- end
8
- def top
9
- @item
10
- end
11
- end
@@ -1,226 +0,0 @@
1
- h2. A Simple Stack - The First Specification
2
-
3
- h3. Where do we start?
4
-
5
- We want to start off with the simplest thing that we can specify, just as we would in TDD. Remember that in spite of some important (if subtle) distinctions, BDD <em>is</em> TDD at its core.
6
-
7
- As discussed in the <a href="index.html">Overview</a>, a common first specification is that a new stack should be empty, and we typically verify this by checking that its size is 0. This simplicity is what we're looking for, but we want to avoid the "size" question. Well, let's think about how a client might use a stack:
8
-
9
- <ruby>
10
- #example usage
11
- stack.pop unless stack.empty?
12
- </ruby>
13
-
14
- So let's start with "A new stack should be empty".
15
-
16
- h3. Create a spec file
17
-
18
- Start by creating a file called stack_spec.rb in /projects/ruby/stack/. You can use any filename and directory you wish, but the following will assume these names and locations.
19
-
20
- h3. Add a context
21
-
22
- Add the following to stack_spec.rb
23
-
24
- <ruby>
25
- context "A new stack" do
26
- end
27
- </ruby>
28
-
29
- A context represents an object (or set of objects) in a known state. This is the same concept as a fixture in xUnit. For each known state from which we wish to specify behaviour, we'll add a new context.
30
-
31
- To see what damage we've done so far, open a command shell, cd to /projects/ruby/stack/, and enter the following:
32
-
33
- <pre>
34
- $ spec stack_spec.rb
35
- </pre>
36
-
37
- You should see output similar to this
38
-
39
- <pre>
40
- Finished in 6.9e-05 seconds
41
-
42
- 1 context, 0 specifications, 0 failures
43
- </pre>
44
-
45
- The <code>spec</code> command is installed when you install rSpec. It requires (using the ruby <code>require</code> method) any file(s) (or all of the files in a directory) that you specify on the command line. The <code>context</code> method accepts a name ("An empty stack") and a block (do ... end) and processes everything inside the block. Since there's nothing in this block to process, we discover that rSpec processed 1 context, but 0 specifications.
46
-
47
- You may wonder why bother with the name? Try adding the <code>-f s</code> option to the command
48
-
49
- <pre>
50
- $ spec stack_spec.rb -f s
51
-
52
- A new stack
53
-
54
- Finished in 6.9e-05 seconds
55
-
56
- 1 context, 0 specifications, 0 failures
57
- </pre>
58
-
59
- The option <code>-f s</code> is a shortcut for <code>--format specdoc</code>, which tells rSpec to print out the names of all the contexts and specifications as they are run. As we progress, you'll see how choosing these names carefully not only documents things well inside the spec files, but also in generated output.
60
-
61
- h3. Add a specification
62
-
63
- The spec that we are starting with is "A new stack should be empty". So far we have the context, "A new stack", but we need the specification, "should be empty" :
64
-
65
- <ruby>
66
- context "A new stack" do
67
- specify "should be empty" do
68
- end
69
- end
70
- </ruby>
71
-
72
- <pre>
73
- $ spec stack_spec.rb -f s
74
-
75
- A new stack
76
- - should be empty
77
-
78
- Finished in 0.000188 seconds
79
-
80
- 1 context, 1 specification, 0 failures
81
- </pre>
82
-
83
- As you can see, this reads like a specification. This is just like the output you get from running jUnit tests through agiledox. Agiledox was an important part of the inception of BDD, so we built it right into rspec. Of course, we haven't actually written any code in the specification, so we need to add some. Just as we do in TDD, we're going to add one little bit at a time - just enough to produce a failed expectation - followed by just enough code to meet the expectation.
84
-
85
- Let's start by creating the new stack.
86
-
87
- <ruby>
88
- context "A new stack" do
89
- setup do
90
- @stack = Stack.new
91
- end
92
- specify "should be empty" do
93
- end
94
- end
95
- </ruby>
96
-
97
- Introducing a setup here may seem a bit premature to some, but we know what the context is here: it's a new stack. We want to express that context in the setup method to clearly define it as the starting state for each of the specifications within this context.
98
-
99
- <pre>
100
- $ spec stack_spec.rb -f s
101
-
102
- A new stack
103
- - should be empty (FAILED - 1)
104
-
105
- 1)
106
- NameError in 'A new stack should be empty'
107
- uninitialized constant Stack
108
- ./stack_spec.rb:3:in `setup'
109
-
110
- Finished in 0.00031 seconds
111
-
112
- 1 context, 1 specification, 1 failure
113
- </pre>
114
-
115
- This tells us that there is a NameError, that it can't find the name Stack, and that the problem is in the setup block of this context. To resolve this, create a new file named stack.rb and add the following:
116
-
117
- <ruby>
118
- class Stack
119
- end
120
- </ruby>
121
-
122
- Then require that file in stack_spec.rb:
123
-
124
- <ruby>
125
- require 'stack'
126
-
127
- context "A new stack" do
128
- ...
129
- </ruby>
130
-
131
- and run the specs.
132
-
133
- <pre>
134
- $ spec stack_spec.rb -f s
135
-
136
- A new stack
137
- - should be empty
138
-
139
- Finished in 0.000229 seconds
140
-
141
- 1 context, 1 specification, 0 failures
142
- </pre>
143
-
144
- We're getting closer, but we still need more to exercise this specification.
145
-
146
- <ruby>
147
- context "A new stack" do
148
- setup do
149
- @stack = Stack.new
150
- end
151
- specify "should be empty" do
152
- @stack.should_be_empty
153
- end
154
- end
155
- </ruby>
156
-
157
- <pre>
158
- $ spec stack_spec.rb -f s
159
-
160
- A new stack
161
- - should be empty (FAILED - 1)
162
-
163
- 1)
164
- NoMethodError in 'A new stack should be empty'
165
- undefined method `empty?' for #<Stack:0x36e6fc>
166
- ./stack_spec.rb:8:in `should be empty'
167
-
168
- Finished in 0.000361 seconds
169
-
170
- 1 context, 1 specification, 1 failure
171
- </pre>
172
-
173
- In this case, rspec interprets the message <code>should_be_empty</code>, and sends <code>empty?</code> to <code>stack</code>. This will work for any predicate (ruby methods that end with a "?" and return boolean).
174
-
175
- You can think of <code>NameError</code> as the equivalent of a compilation failure in java or C#. <code>Stack</code> doesn't respond to the <code>empty?</code> message ... yet.
176
-
177
- <ruby>
178
- class Stack
179
- def empty?
180
- end
181
- end
182
- </ruby>
183
-
184
- <pre>
185
- $ spec stack_spec.rb -f s
186
-
187
- A new stack
188
- - should be empty (FAILED - 1)
189
-
190
- 1)
191
- ExpectationNotMetError in 'A new stack should be empty'
192
- Stack #<Stack:0x36e60c> should be empty
193
- ./stack_spec.rb:8:in `should be empty'
194
-
195
- Finished in 0.000389 seconds
196
-
197
- 1 context, 1 specification, 1 failure
198
- </pre>
199
-
200
- ... and NOW we get a failing expectation. "Stack #&lt;Stack:0x36e60c&gt; should be empty" is the detail of this <code>ExpectationNotMetError</code>. The expectation is that <code>empty?</code> should return <code>true</code>, but it does not. Let's make it so ...
201
-
202
- <ruby>
203
- class Stack
204
- def empty?
205
- true
206
- end
207
- end
208
- </ruby>
209
-
210
- <pre>
211
- spec stack_spec.rb -f s
212
-
213
- A new stack
214
- - should be empty
215
-
216
- Finished in 0.000256 seconds
217
-
218
- 1 context, 1 specification, 0 failures
219
- </pre>
220
-
221
- And thus we have completed our first specification: "A new stack should be empty"
222
-
223
- If you've never had any experience, returning <code>true</code> from <code>empty?</code> may seem a bit strange. Even if you have, you may not feel that the cycle is complete yet. "Test-Code-Refactor", right? Or rather "Spec-Code-Refactor". At this point, we should refactor to eliminate duplication, and you might argue that there is duplication between the spec expecting true and the method returning true. The problem right now is that we have no specs with expectations of the stack being anything other than empty. Any conditional logic we might implement here would be adding new behaviour. Refactoring is defined as changing structure without changing behaviour. And so, as much as we'd like to change <code>true</code> to something more useful, we need to take that urge and recognize that, in this case, we have a deficiency in our specifications - not in the code.
224
-
225
- <a href="stack_02.html">Next</a>
226
-
@@ -1,182 +0,0 @@
1
- h2. A Simple Stack
2
-
3
- h3. Choosing the next Specification
4
-
5
- We left our code in a state in which it could not be refactored because adding conditional logic would be adding new behaviour at this point (which is not refactoring). We wanted to refactor because we had a hard-coded return value from a method that is begging for some conditional logic. So let's choose a specification to focus on next that will help us to address that. We want a specification that will result in a non-empty stack.
6
-
7
- Since an "empty stack" seems more interesting from a behavioural perspective than a "new stack", let's start talking about the behaviour of an <em>empty</em> stack.
8
-
9
- <ruby>
10
- context "An empty stack" do
11
- specify "should not be empty after 'push'" do
12
- end
13
- end
14
- </ruby>
15
-
16
- <pre>
17
- $ spec stack_spec.rb -f s
18
-
19
- A new stack
20
- - should be empty
21
-
22
- An empty stack
23
- - should not be empty after 'push'
24
-
25
- Finished in 0.000391 seconds
26
-
27
- 2 contexts, 2 specifications, 0 failures
28
- </pre>
29
-
30
- See how that's reading like a specification document? OK, now let's fill in the specification. First we add the setup for our context.
31
-
32
- <ruby>
33
- context "An empty stack" do
34
- setup do
35
- @stack = Stack.new
36
- end
37
- specify "should not be empty after 'push'" do
38
- end
39
- end
40
- </ruby>
41
-
42
- <pre>
43
- $ spec stack_spec.rb -f s
44
-
45
- A new stack
46
- - should be empty
47
-
48
- An empty stack
49
- - should not be empty after 'push'
50
-
51
- Finished in 0.000444 seconds
52
-
53
- 2 contexts, 2 specifications, 0 failures
54
- </pre>
55
-
56
- No change in the result. Now we'll push something on to the stack.
57
-
58
- <ruby>
59
- context "An empty stack" do
60
- setup do
61
- @stack = Stack.new
62
- end
63
- specify "should not be empty after 'push'" do
64
- @stack.push 37
65
- end
66
- end
67
- </ruby>
68
-
69
- <pre>
70
- $ spec stack_spec.rb -f s
71
-
72
- A new stack
73
- - should be empty
74
-
75
- An empty stack
76
- - should not be empty after 'push' (FAILED - 1)
77
-
78
- 1)
79
- NoMethodError in 'An empty stack should not be empty after 'push''
80
- undefined method `push' for #<Stack:0x36d0e0>
81
- ./stack_spec.rb:17:in `should not be empty after 'push''
82
-
83
- Finished in 0.000548 seconds
84
-
85
- 2 contexts, 2 specifications, 1 failure
86
- </pre>
87
-
88
- The <code>NoMethodError</code> tells us we need to add a push method to the stack.
89
-
90
- <ruby>
91
- class Stack
92
- def empty?
93
- true
94
- end
95
- def push item
96
- end
97
- end
98
- </ruby>
99
-
100
- <pre>
101
- $ spec stack_spec.rb -f s
102
-
103
- A new stack
104
- - should be empty
105
-
106
- An empty stack
107
- - should not be empty after 'push'
108
-
109
- Finished in 0.000427 seconds
110
-
111
- 2 contexts, 2 specifications, 0 failures
112
- </pre>
113
-
114
- The idea is to add a little bit of spec, just enough to get some kind of failure, then just enough code to get the code to meet the expectations expressed in the spec. In this case, the NameError was like a compilation failure in java or C#.
115
-
116
- Next we set our expectation:
117
-
118
- <ruby>
119
- context "An empty stack" do
120
- setup do
121
- @stack = Stack.new
122
- end
123
- specify "should not be empty after 'push'" do
124
- @stack.push 37
125
- @stack.should_not_be_empty
126
- end
127
- end
128
- </ruby>
129
-
130
- <pre>
131
- $ spec stack_spec.rb -f s
132
-
133
- A new stack
134
- - should be empty
135
-
136
- An empty stack
137
- - should not be empty after 'push' (FAILED - 1)
138
-
139
- 1)
140
- ExpectationNotMetError in 'An empty stack should not be empty after 'push''
141
- Stack #<Stack:0x36cf50> should not be empty
142
- ./stack_spec.rb:18:in `should not be empty after 'push''
143
-
144
- Finished in 0.000604 seconds
145
-
146
- 2 contexts, 2 specifications, 1 failure
147
- </pre>
148
-
149
- The <code>ExpectationNotMetError</code> tells us we have something to implement. We want to do the simplest thing that we can do to meet our existing expectations. At this point we don't know anything about collections or even specific values, so we can just manage whether or not it is empty.
150
-
151
- <ruby>
152
- class Stack
153
- def initialize
154
- @empty = true
155
- end
156
- def empty?
157
- @empty
158
- end
159
- def push item
160
- @empty = false
161
- end
162
- end
163
- </ruby>
164
-
165
- <pre>
166
- $ spec stack_spec.rb -f s
167
-
168
- A new stack
169
- - should be empty
170
-
171
- An empty stack
172
- - should not be empty after 'push'
173
-
174
- Finished in 0.000443 seconds
175
-
176
- 2 contexts, 2 specifications, 0 failures
177
- </pre>
178
-
179
- Again, this may seem a little odd, but we haven't specified anything yet about what happens to things that get pushed on to the stack. That's right around the corner though...
180
-
181
- <a href="stack_01.html">Previous</a> |
182
- <a href="stack_03.html">Next</a>
@@ -1,283 +0,0 @@
1
- h2. A Simple Stack - eliminating duplication
2
-
3
- h3. What to specify next?
4
-
5
- Picking the next thing to specify is always a challenge (just as picking the next thing to test is in TDD). Ideally, you want to specify the simplest thing that you can imagine implementing. Of course, thinking about implementation seems to fly in the face of a core tenet of TDD and BDD: focus on interface - focus on behaviour. So you have a couple of opposing forces and notions guiding this decision. The bottom line is that it's not that important which one you pick next. The important thing is that as soon as you recognize that you've headed down the wrong path (one which requires a lot of implementation to meet the newest specification), roll back immediately and pick a different "next step".
6
-
7
- For our problem, there seem to be (at least) two logical potential next steps. We know that pushing on to an empty stack results in the stack no longer being empty. So one logical next step might be to specify how an empty stack behaves when sending it a different message. Another might be to send push to a non-empty stack. But what I'd really like to know is what happened to the item we just pushed onto the stack!
8
-
9
- To specify that, we have to move diagonally a bit. We need to specify the stack's response to a new message starting in a new state - a new context. We're going to start with a stack with one item already pushed onto it and specify what happens when you send it 'top'. Why top and not pop? In this case, top is simpler than pop - top just returns the top item, while pop also removes it from the stack.
10
-
11
- h3. Send top to a stack with one item
12
-
13
- Start by adding a new context and spec in stack_spec.rb.
14
-
15
- <ruby>
16
- context "A stack with one item" do
17
- specify "should return top when you send it 'top'" do
18
- end
19
- end
20
- </ruby>
21
-
22
- <pre>
23
- $ spec stack_spec.rb -f s
24
-
25
- A new stack
26
- - should be empty
27
-
28
- An empty stack
29
- - should not be empty after 'push'
30
-
31
- A stack with one item
32
- - should return top when you send it 'top'
33
-
34
- Finished in 0.000693 seconds
35
-
36
- 3 contexts, 4 specifications, 0 failures
37
- </pre>
38
-
39
- Add the setup...
40
-
41
- <ruby>
42
- context "A stack with one item" do
43
- setup do
44
- @stack = Stack.new
45
- @stack.push "one item"
46
- end
47
-
48
- specify "should return top when you send it 'top'" do
49
- end
50
- end
51
- </ruby>
52
-
53
- <pre>
54
- $ spec stack_spec.rb -f s
55
-
56
- A new stack
57
- - should be empty
58
-
59
- An empty stack
60
- - should not be empty after 'push'
61
-
62
- A stack with one item
63
- - should return top when you send it 'top'
64
-
65
- Finished in 0.000733 seconds
66
-
67
- 3 contexts, 4 specifications, 0 failures
68
- </pre>
69
-
70
- No change in the output. Add the expectation...
71
-
72
- <ruby>
73
- context "A stack with one item" do
74
- setup do
75
- @stack = Stack.new
76
- @stack.push "one item"
77
- end
78
-
79
- specify "should return top when you send it 'top'" do
80
- @stack.top.should_equal "one item"
81
- end
82
- end
83
- </ruby>
84
-
85
- <pre>
86
- $ spec stack_spec.rb -f s
87
-
88
- A new stack
89
- - should be empty
90
-
91
- An empty stack
92
- - should not be empty after 'push'
93
-
94
- A stack with one item
95
- - should return top when you send it 'top' (FAILED - 1)
96
-
97
- 1)
98
- NoMethodError in 'A stack with one item should return top when you send it 'top''
99
- undefined method `top' for #<Stack:0x36bd44 @empty=false>
100
- ./stack_spec.rb:35:in `should return top when you send it 'top''
101
-
102
- Finished in 0.000863 seconds
103
-
104
- 3 contexts, 4 specifications, 1 failure
105
- </pre>
106
-
107
- The <code>NoMethodError</code> tells us to add the 'top' method.
108
-
109
- <ruby>
110
- class Stack
111
- ...
112
- def top
113
- end
114
- end
115
- </ruby>
116
-
117
- <pre>
118
- $ spec stack_spec.rb -f s
119
-
120
- A new stack
121
- - should be empty
122
-
123
- An empty stack
124
- - should not be empty after 'push'
125
-
126
- A stack with one item
127
- - should return top when you send it 'top' (FAILED - 1)
128
-
129
- 1)
130
- ExpectationNotMetError in 'A stack with one item should return top when you send it 'top''
131
- nil should equal "one item"
132
- ./stack_spec.rb:35:in `should return top when you send it 'top''
133
-
134
- Finished in 0.000867 seconds
135
-
136
- 3 contexts, 4 specifications, 1 failure
137
- </pre>
138
-
139
- The <code>ExpectationNotMetError</code> tells us to implement something. What's the simplest thing we can add to meet all of the current expectations?
140
-
141
- <ruby>
142
- class Stack
143
- ...
144
- def top
145
- "one item"
146
- end
147
- end
148
- </ruby>
149
-
150
- <pre>
151
- $ spec stack_spec.rb -f s
152
-
153
- A new stack
154
- - should be empty
155
-
156
- An empty stack
157
- - should not be empty after 'push'
158
-
159
- A stack with one item
160
- - should return top when you send it 'top'
161
-
162
- Finished in 0.000744 seconds
163
-
164
- 3 contexts, 4 specifications, 0 failures
165
- </pre>
166
-
167
- Again we have duplication between the specs and the code ("one item") and we want to get rid of it. This time, however, we have enough specs and entry points that there is actually something to refactor to.
168
-
169
- If you're not familiar with refactoring, check out <a href="http://www.refactoring.com/">http://www.refactoring.com/</a>. We'll do some now, but we won't be examining the steps too deeply. The basic idea is that we want to change structure/implementation without affecting behaviour. Running the specs and watching them pass between each step proves that the behaviour is in tact.
170
-
171
- First, we save the item we add and return that from <code>top</code> ...
172
-
173
- <ruby>
174
- class Stack
175
- def initialize
176
- @empty = true
177
- end
178
- def empty?
179
- @empty
180
- end
181
- def push item
182
- @empty = false
183
- @item = item
184
- end
185
- def top
186
- @item
187
- end
188
- end
189
- </ruby>
190
-
191
- <pre>
192
- $ spec stack_spec.rb -f s
193
-
194
- A new stack
195
- - should be empty
196
-
197
- An empty stack
198
- - should not be empty after 'push'
199
-
200
- A stack with one item
201
- - should return top when you send it 'top'
202
-
203
- Finished in 0.000846 seconds
204
-
205
- 3 contexts, 4 specifications, 0 failures
206
- </pre>
207
-
208
- Now let's use the item to determine "emptiness"...
209
-
210
- <ruby>
211
- class Stack
212
- def initialize
213
- @empty = true
214
- end
215
- def empty?
216
- @item.nil?
217
- end
218
- def push item
219
- @empty = false
220
- @item = item
221
- end
222
- def top
223
- @item
224
- end
225
- end
226
- </ruby>
227
-
228
- <pre>
229
- $ spec stack_spec.rb -f s
230
-
231
- A new stack
232
- - should be empty
233
-
234
- An empty stack
235
- - should not be empty after 'push'
236
-
237
- A stack with one item
238
- - should return top when you send it 'top'
239
-
240
- Finished in 0.000764 seconds
241
-
242
- 3 contexts, 4 specifications, 0 failures
243
- </pre>
244
-
245
- Now we can eliminate <code>@empty</code> (which means we can eliminate <code>initialize</code> as well).
246
-
247
- <ruby>
248
- class Stack
249
- def empty?
250
- @item.nil?
251
- end
252
- def push item
253
- @item = item
254
- end
255
- def top
256
- @item
257
- end
258
- end
259
- </ruby>
260
-
261
- <pre>
262
- $ spec stack_spec.rb -f s
263
-
264
- A new stack
265
- - should be empty
266
-
267
- An empty stack
268
- - should not be empty after 'push'
269
-
270
- A stack with one item
271
- - should return top when you send it 'top'
272
-
273
- Finished in 0.000737 seconds
274
-
275
- 3 contexts, 4 specifications, 0 failures
276
- </pre>
277
-
278
- So this time we were able to refactor, and in doing so not only reduce the duplication but also reduce the size of the stack class. Sweet.
279
-
280
- To be continued...
281
-
282
- <a href="stack_02.html">Previous</a> |
283
- <a href="stack_04.html">Next</a>