rspec-given 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,167 @@
1
+ # rspec-given
2
+
3
+ rspec-given is an RSpec 2 extension to allow Given/When/Then notation
4
+ in RSpec specifications. It is a natural extension of the
5
+ experimental work done on the Given framework. It turns out that 90%
6
+ of the Given framework can be trivially implemented on top of RSpec.
7
+
8
+ # Why Given/When/Then
9
+
10
+ RSpec has done a great job of making specifications more readable for
11
+ humans. However, I really like the given / when / then nature of
12
+ Cucumber stories and would like to follow the same structure in my
13
+ unit tests. rspec-given allows a simple given/when/then structure
14
+ RSpec specifications.
15
+
16
+ ## Status
17
+
18
+ rspec-given is quite usable at the moment, although is is lacking
19
+ several features.
20
+
21
+ * Invariants are not supported yet.
22
+ * Then assertions without _should_ are not supported yet.
23
+
24
+ ## Example Zero
25
+
26
+ Here's the spec that I've been playing with. Its gone through
27
+ mulitple revisions and several prototype implementations. And this is
28
+ probably not the final form.
29
+
30
+ With all that in mind, here's a specification in my imaginary
31
+ framework:
32
+
33
+ <pre>
34
+ require 'spec_helper'
35
+ require 'stack'
36
+
37
+ describe Stack do
38
+ # NOTE: Invariants are not yet supported in rspec-given
39
+ # Invariant { stack.depth >= 0 }
40
+ # Invariant { stack.empty? == (stack.depth == 0) }
41
+
42
+ Given(:an_empty_stack) { Stack.new }
43
+
44
+ Given(:a_stack_with_one_item) do
45
+ Stack.new.tap do |s|
46
+ s.push(:an_item)
47
+ end
48
+ end
49
+
50
+ Given(:a_stack_with_several_items) do
51
+ Stack.new.tap do |s|
52
+ s.push(:second_item)
53
+ s.push(:top_item)
54
+ end
55
+ end
56
+
57
+ context "an empty stack" do
58
+ Given(:stack) { an_empty_stack }
59
+
60
+ Then { stack.depth.should == 0 }
61
+
62
+ context "Pushing onto an empty stack" do
63
+ When { stack.push(:an_item) }
64
+
65
+ Then { stack.depth.should == 1 }
66
+ Then { stack.top.should == :an_item }
67
+ end
68
+ end
69
+
70
+ context "a stack with one item do" do
71
+ Given(:stack) { a_stack_with_one_item }
72
+
73
+ context "popping an item empties the stack" do
74
+ When(:pop_result) { stack.pop }
75
+
76
+ Then { pop_result.should == :an_item }
77
+ Then { stack.should be_empty }
78
+ end
79
+ end
80
+
81
+ context "a stack with several items" do
82
+ Given(:stack) { a_stack_with_several_items }
83
+ Given!(:original_depth) { stack.depth }
84
+
85
+ context "pushing a new item adds a new top" do
86
+ When { stack.push(:new_item) }
87
+
88
+ Then { stack.top.should == :new_item }
89
+ Then { stack.depth.should == original_depth + 1 }
90
+ end
91
+
92
+ context "popping an item removes the top item" do
93
+ When(:pop_result) { stack.pop }
94
+
95
+ Then { pop_result.should == :top_item }
96
+ Then { stack.top.should == :second_item }
97
+ Then { stack.depth.should == original_depth - 1 }
98
+ end
99
+ end
100
+ end
101
+ </pre>
102
+
103
+ Let's talk about the individual sections.
104
+
105
+ ### Given
106
+
107
+ The _Given_ section specifies a starting point, a set of preconditions
108
+ that must be true before the code under test is allowed to be run. In
109
+ standard test frameworks the preconditions are established with a
110
+ combination of setup methods (or :before actions in RSpec) and code in
111
+ the test.
112
+
113
+ In the example code above, we see three starting points of interest.
114
+ One is an empty, just freshly created stack. The next is a stack with
115
+ exactly one item. The final starting point is a stack with several
116
+ items.
117
+
118
+ A precondition in the form "Given(:var) {...}" creates an accessor
119
+ method named "var". The accessor is lazily initialized by the code
120
+ block. If you want a non-lazy given, use "Given!(:var) {...}".
121
+
122
+ A precondition in the form "Given {...}" just executes the code block
123
+ for side effects. Since there is no accessor, the code block is
124
+ executed immediately (i.e. no lazy evaluation).
125
+
126
+ The preconditions are run in order of definition. Nested contexts
127
+ will inherit the preconditions from the enclosing context, with out
128
+ preconditions running before inner preconditions.
129
+
130
+ ### When
131
+
132
+ The _When_ block specifies the code to be tested ... oops, excuse me
133
+ ... specified. After the preconditions in the given section are met,
134
+ the when code block is run.
135
+
136
+ There should only be one _When_ block for a given context.
137
+
138
+ ### Then
139
+
140
+ The _Then_ sections are the postconditions of the specification. These
141
+ then conditions must be true after the code under test (the _When_
142
+ block) is run.
143
+
144
+ The code in the _Then_ block should be a single boolean condition that
145
+ devaluates to true if the code in the _When_ block is correct. If the
146
+ _Then_ block evaluates to false, then that is recorded as a failure.
147
+
148
+ ### Invariant
149
+
150
+ The _Invariant_ block is a new idea that doesn't have an analog in
151
+ RSpec or Test::Unit. The invariant allows you specify things that
152
+ must always be true. In the stack example, <tt>empty?</tt> is defined
153
+ in term of <tt>size</tt>. Whenever <tt>size</tt> is 0,
154
+ <tt>empty?</tt> should be true. Whenever <tt>size</tt> is non-zero,
155
+ <tt>empty?</tt> should be false.
156
+
157
+ You can conceptually think of an _Invariant_ block as a _Then_ block
158
+ that automatically gets added to every _When_ within its scope.
159
+
160
+ Invariants nested within a context only apply to the _When_ blocks in
161
+ that context.
162
+
163
+ Invariants that reference a _Given_ precondition accessor must only be
164
+ used in contexts that define that accessor.
165
+
166
+ NOTE: Invariants are not yet implemented in the current version of
167
+ rspec-given.
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/ruby -wKU
2
+
3
+ require 'rake/clean'
4
+
5
+ CLOBBER.include("*.gemspec", "html")
6
+
7
+
8
+ # README Formatting --------------------------------------------------
9
+
10
+ require 'bluecloth'
11
+
12
+
13
+ task :default => :examples
14
+
15
+ # Running examples ---------------------------------------------------
16
+
17
+ desc "Run the examples"
18
+ task :examples do
19
+ sh "rspec examples"
20
+ end
21
+
22
+ # Formatting the README ----------------------------------------------
23
+
24
+ directory 'html'
25
+
26
+ desc "Display the README file"
27
+ task :readme => "html/README.html" do
28
+ sh "open html/README.html"
29
+ end
30
+
31
+ desc "format the README file"
32
+ task "html/README.html" => ['html', 'README.md'] do
33
+ open("README.md") do |source|
34
+ open('html/README.html', 'w') do |out|
35
+ out.write(BlueCloth.new(source.read).to_html)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,2 @@
1
+ require 'rspec/given'
2
+ $LOAD_PATH << './examples/stack'
@@ -0,0 +1,25 @@
1
+ class Stack
2
+ def initialize
3
+ @items = []
4
+ end
5
+
6
+ def depth
7
+ @items.size
8
+ end
9
+
10
+ def empty?
11
+ @items.empty?
12
+ end
13
+
14
+ def top
15
+ @items.last
16
+ end
17
+
18
+ def push(item)
19
+ @items << item
20
+ end
21
+
22
+ def pop
23
+ @items.pop
24
+ end
25
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+ require 'stack'
3
+
4
+ describe Stack do
5
+ # NOTE: Invariants are not yet supported in rspec-given
6
+ # Invariant { stack.depth >= 0 }
7
+ # Invariant { stack.empty? == (stack.depth == 0) }
8
+
9
+ Given(:an_empty_stack) { Stack.new }
10
+
11
+ Given(:a_stack_with_one_item) do
12
+ Stack.new.tap do |s|
13
+ s.push(:an_item)
14
+ end
15
+ end
16
+
17
+ Given(:a_stack_with_several_items) do
18
+ Stack.new.tap do |s|
19
+ s.push(:second_item)
20
+ s.push(:top_item)
21
+ end
22
+ end
23
+
24
+ context "an empty stack" do
25
+ Given(:stack) { an_empty_stack }
26
+
27
+ Then { stack.depth.should == 0 }
28
+
29
+ context "Pushing onto an empty stack" do
30
+ When { stack.push(:an_item) }
31
+
32
+ Then { stack.depth.should == 1 }
33
+ Then { stack.top.should == :an_item }
34
+ end
35
+ end
36
+
37
+ context "a stack with one item do" do
38
+ Given(:stack) { a_stack_with_one_item }
39
+
40
+ context "popping an item empties the stack" do
41
+ When(:pop_result) { stack.pop }
42
+
43
+ Then { pop_result.should == :an_item }
44
+ Then { stack.should be_empty }
45
+ end
46
+ end
47
+
48
+ context "a stack with several items" do
49
+ Given(:stack) { a_stack_with_several_items }
50
+ Given!(:original_depth) { stack.depth }
51
+
52
+ context "pushing a new item adds a new top" do
53
+ When { stack.push(:new_item) }
54
+
55
+ Then { stack.top.should == :new_item }
56
+ Then { stack.depth.should == original_depth + 1 }
57
+ end
58
+
59
+ context "popping an item removes the top item" do
60
+ When(:pop_result) { stack.pop }
61
+
62
+ Then { pop_result.should == :top_item }
63
+ Then { stack.top.should == :second_item }
64
+ Then { stack.depth.should == original_depth - 1 }
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,3 @@
1
+ require 'rspec/given/version'
2
+ require 'rspec/given/extensions'
3
+
@@ -0,0 +1,38 @@
1
+ require 'rspec/core/let'
2
+
3
+ module RSpec
4
+ module Core
5
+ class ExampleGroup
6
+ alias_example_to :Then
7
+ end
8
+ end
9
+ end
10
+
11
+ module RSpec
12
+ module Core
13
+ module Let
14
+ module ClassMethods
15
+
16
+ def Given(*args,&block)
17
+ if args.first.is_a?(Symbol)
18
+ let(args.first, &block)
19
+ else
20
+ before(&block)
21
+ end
22
+ end
23
+
24
+ def Given!(var, &block)
25
+ let!(var, &block)
26
+ end
27
+
28
+ def When(*args, &block)
29
+ if args.first.is_a?(Symbol)
30
+ let!(args.first, &block)
31
+ else
32
+ before(&block)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,9 @@
1
+ module RSpec
2
+ module Given
3
+ VERSION_MAJOR = 1
4
+ VERSION_MINOR = 0
5
+ VERSION_BUILD = 0
6
+ VERSION_NUMBERS = [VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD]
7
+ VERSION = VERSION_NUMBERS.join(".")
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec-given
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Jim Weirich
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-11-27 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: |
22
+ Given is an RSpec extension that allows explicit definition of the
23
+ pre and post-conditions for code under test.
24
+
25
+ email: jim.weirich@gmail.com
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - Rakefile
34
+ - README.md
35
+ - lib/rspec/given/extensions.rb
36
+ - lib/rspec/given/version.rb
37
+ - lib/rspec/given.rb
38
+ - examples/spec_helper.rb
39
+ - examples/stack/stack.rb
40
+ - examples/stack/stack_spec.rb
41
+ has_rdoc: true
42
+ homepage: http://github.com/jimweirich/rspec-given
43
+ licenses: []
44
+
45
+ post_install_message:
46
+ rdoc_options:
47
+ - --line-numbers
48
+ - --inline-source
49
+ - --main
50
+ - README.md
51
+ - --title
52
+ - RSpec Given Extensions
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ requirements: []
70
+
71
+ rubyforge_project: given
72
+ rubygems_version: 1.3.6
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Given/When/Then Specification Extensions for RSpec.
76
+ test_files: []
77
+