rspec-system 1.7.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -6,3 +6,4 @@ doc/
6
6
  vendor/
7
7
  .bundle
8
8
  spec/reports/
9
+ .rspec_system/
data/CHANGELOG.md CHANGED
@@ -1,11 +1,50 @@
1
- 1.7.1
1
+ 2.0.0
2
2
  =====
3
3
 
4
- This fixes the nokogiri 1.6.0 issue, whereby that version no longer supports Ruby 1.8.7 any more. Instead we have pinned nokogiri to 1.5.x.
4
+ This major release adds some syntactical sugar, providing the user with the ability to use helpers in subjects.
5
5
 
6
- #### Detailed Changes
6
+ So for example, where before you could use `shell` as a helper:
7
+
8
+ describe 'shell tests' do
9
+ it 'test 1' do
10
+ shell('cat /etc/hosts') do |r|
11
+ r.stdout.should =~ /localhost/
12
+ r.stderr.should be_empty
13
+ r.exit_code.should be_zero
14
+ end
15
+ end
16
+ end
17
+
18
+ Now you can use it as the subject of a `describe` or `context`:
19
+
20
+ describe 'shell tests' do
21
+ context shell 'cat /etc/hosts' do
22
+ its(:stdout) { should =~ /localhost/ }
23
+ its(:stderr) { should be_empty }
24
+ its(:exit_code) { should be_zero }
25
+ end
26
+ end
27
+
28
+ The helper `rcp` has also been modified to benefit from this change:
29
+
30
+ describe 'rcp tests' do
31
+ context rcp :dp => '/tmp/foo', :sp => '/tmp/foo' do
32
+ its(:success) { should be_true }
33
+ end
34
+ end
35
+
36
+ The fact that you can use the helpers in both places should provide the user with greater flexibility to create more succinct tests, while still providing simple sequences of commands in a single test when needed as before.
37
+
38
+ This facility is also available to other plugins by providing a new `RSpecSystem::Helper` object that can be extended to provide a new helper with all the syntactic sugar features as the core methods `shell` and `rcp`.
39
+
40
+ As part of this release, we have also removed some prior deprecations:
41
+
42
+ * The system_* methods no longer work: system_run, system_rcp and system_node
43
+ * system_setup_block no longer works.
44
+
45
+ Before upgrading, we suggest you upgrade to 1.7.0, paying heed to any deprecation warnings before upgrading to 2.0.0.
7
46
 
8
- * Fix nokogiri for 1.8.7 (Ken Barber)
47
+ #### Detail Changes
9
48
 
10
49
  -------------------------------
11
50
 
data/README.md CHANGED
@@ -46,21 +46,25 @@ An example file would look like this:
46
46
  require 'spec_helper_system'
47
47
 
48
48
  describe 'basics' do
49
+ # Here we use the 'shell' helper as a subject
50
+ context shell 'cat /etc/hosts' do
51
+ its(:stdout) { should =~ /localhost/ }
52
+ its(:stderr) { should be_empty }
53
+ its(:exit_code) { should be_zero }
54
+ end
55
+
49
56
  it 'should cat /etc/resolv.conf' do
57
+ # Here we run the shell command as a helper
50
58
  shell 'cat /etc/hosts' do |r|
51
59
  r.stdout.should =~ /localhost/
52
- r.exit_code.should be_zero
53
60
  r.stderr.should be_empty
61
+ r.exit_code.should be_zero
54
62
  end
55
63
  end
56
64
  end
57
65
 
58
66
  Also consult the examples in the `examples` directory in the source of this library for more details.
59
67
 
60
- For your reference, here are the list of custom rspec configuration items that can be overriden in your `spec_helper_system.rb` file:
61
-
62
- * *system_tmp* - For some of our activity, we require a temporary file area. By default we just a random temporary path, so you normally do not need to set this.
63
-
64
68
  Currently to get the nice formatting rspec-system specific formatter its recommended to use the Rake task, so add the following to your `Rakefile`:
65
69
 
66
70
  require 'rspec-system/rake_task'
data/lib/rspec-system.rb CHANGED
@@ -5,7 +5,9 @@ module RSpecSystem; end
5
5
 
6
6
  require 'rspec-system/util'
7
7
  require 'rspec-system/log'
8
+ require 'rspec-system/helper'
8
9
  require 'rspec-system/helpers'
10
+ require 'rspec-system/internal_helpers'
9
11
  require 'rspec-system/node_set'
10
12
  require 'rspec-system/prefab'
11
13
  require 'rspec-system/node'
@@ -0,0 +1,160 @@
1
+ require 'rspec-system'
2
+ require 'rspec-system/result'
3
+ require 'rspec-system/internal_helpers'
4
+
5
+ module RSpecSystem
6
+ # This class represents an abstract 'helper' object.
7
+ #
8
+ # It provides some DSL and convenience helpers to create rspec-system
9
+ # compatible helper objects so others can create their own helper methods
10
+ # with the same syntactical sugar.
11
+ #
12
+ # Start by sub-classing this feature and providing your own #execute
13
+ # method, name & properties declaration. See other sub-classes for examples
14
+ # on proper usage.
15
+ #
16
+ # @abstract Subclass and override methods to create a helper object
17
+ class Helper
18
+ include RSpecSystem::InternalHelpers
19
+
20
+ # Cache of previous result data
21
+ # @api private
22
+ attr_reader :rd
23
+
24
+ # Options when called
25
+ attr_reader :opts
26
+
27
+ class << self
28
+ attr_accessor :name_value
29
+
30
+ # DSL method for setting the helper name
31
+ #
32
+ # @param name [String] unique helper method name
33
+ def name(name)
34
+ @name_value = name
35
+ end
36
+
37
+ # Accepts a list of properties to automatically create
38
+ #
39
+ # @param props [Array <Symbol>] an array of property methods to create
40
+ def properties(*props)
41
+ props.each do |prop|
42
+ define_method(prop) { result_data.send(prop) }
43
+ end
44
+ end
45
+ end
46
+
47
+ # Setup the helper object.
48
+ #
49
+ # Here we establish laziness detection, provide the default :node setting
50
+ # and handle been called as a block automatically for the consumer. This is
51
+ # the main setup for the magic that is behind these helper objects.
52
+ #
53
+ # This initialize method is usually not overridden for simple cases, but can
54
+ # be overridden for the purposes of munging options and providing defaults.
55
+ #
56
+ # @abstract Override, but make sure you call super(opts, clr, &block)
57
+ def initialize(opts, clr, &block)
58
+ dn = default_node
59
+
60
+ # This is a test for the context of how this command was called
61
+ #
62
+ # If clr is Class or Object then it could be called as a subject, and it
63
+ # should lazy execute its action.
64
+ lazy = nil
65
+ if [Class, Object].include?(clr.class) # presumes being used as a subject
66
+ lazy = true
67
+ elsif clr.is_a? RSpec::Core::ExampleGroup # anything inside an 'it'
68
+ lazy = false
69
+ else
70
+ # We presume everything else wants results immediately
71
+ lazy = false
72
+ end
73
+
74
+ opts = {
75
+ :node => opts[:n] || dn,
76
+ :n => opts[:node] || dn,
77
+ :lazy => lazy,
78
+ }.merge(opts)
79
+
80
+ @opts = opts
81
+ r = result_data unless opts[:lazy]
82
+
83
+ # If called as a block, yield the result as a block
84
+ if block_given?
85
+ yield(self)
86
+ end
87
+ end
88
+
89
+ # This method is executed to retrieve the data for this helper. It is always
90
+ # overridden by sub-classes.
91
+ #
92
+ # Here we perform the actual step to retrieve the helper data, returning
93
+ # the result as a basic hash which gets stored for later retrieval via the
94
+ # helper object.
95
+ #
96
+ # @return [Hash <Symbol, Any>] return a hash of results, with symbolic keys
97
+ # @abstract Always override this method with your own execution routine.
98
+ def execute
99
+ raise "The #execute method has not be overridden in this class"
100
+ end
101
+
102
+ # Internal method to return any result data from resource execution time
103
+ #
104
+ # If there are no previous results, it will execute the resource action
105
+ # and return those result. The action only runs once, so subsequent
106
+ # requests return the last result.
107
+ #
108
+ # @return [RSpecSystem::Result] result object
109
+ # @api private
110
+ def result_data
111
+ return rd unless rd.nil?
112
+ @rd = RSpecSystem::Result.new(execute)
113
+ end
114
+
115
+ # Refresh the data, re-running the action associated with this helper.
116
+ #
117
+ # @return [void]
118
+ def refresh
119
+ @rd = nil
120
+ result_data
121
+ nil
122
+ end
123
+
124
+ # Allow run as an alias to refresh
125
+ alias_method :run, :refresh
126
+
127
+ # This allows the data to be treated as a hash
128
+ #
129
+ # @param key [Symbol] key of value to retrieve
130
+ def [](key)
131
+ result_data[key]
132
+ end
133
+
134
+ # Retrieve the data from this helper object as a hash
135
+ #
136
+ # @return [Hash] result data as a hash
137
+ def to_hash
138
+ result_data.to_hash
139
+ end
140
+
141
+ # Return the helper name of this helper object
142
+ #
143
+ # @return [String] name of helper
144
+ def name
145
+ self.class.name_value
146
+ end
147
+
148
+ # String representation of helper
149
+ #
150
+ # @return [String] helper_name(args) formatted string
151
+ def to_s
152
+ name + "(" + opts.inspect + ")"
153
+ end
154
+
155
+ # Return default node
156
+ def default_node
157
+ rspec_system_node_set.default_node
158
+ end
159
+ end
160
+ end
@@ -1,4 +1,6 @@
1
1
  require 'rspec-system/result'
2
+ require 'rspec-system/helpers/shell'
3
+ require 'rspec-system/helpers/rcp'
2
4
 
3
5
  # This module contains the main rspec helpers that are to be used within
4
6
  # rspec-system tests. These are the meat-and-potatoes of your system tests,
@@ -56,22 +58,6 @@ module RSpecSystem::Helpers
56
58
  # @!group Actions
57
59
 
58
60
  # @!macro shell_method
59
- # @api public
60
- # @overload $0(options)
61
- # @param options [Hash] options for command execution
62
- # @option options [String] :command command to execute. Mandatory.
63
- # @option options [String] :c alias for :command
64
- # @option options [RSpecSystem::Node] :node (defaults to what was defined
65
- # default in your YAML file, otherwise if there is only one node it uses
66
- # that) specifies node to execute command on.
67
- # @option options [RSpecSystem::Node] :n alias for :node
68
- # @overload $0(command)
69
- # @param command [String] command to execute
70
- # @yield [result] yields result when called as a block
71
- # @yieldparam result [RSpecSystem::Result] result of run containing
72
- # :exit_code, :stdout and :stderr
73
- # @return [RSpecSystem::Result] result of run containing :exit_code,
74
- # :stdout and :stderr
75
61
 
76
62
  # Runs a shell command on a test host.
77
63
  #
@@ -88,7 +74,20 @@ module RSpecSystem::Helpers
88
74
  # to worry about that.
89
75
  #
90
76
  # @api public
91
- # @macro shell_method
77
+ # @api public
78
+ # @overload $0(options)
79
+ # @param options [Hash] options for command execution
80
+ # @option options [String] :command command to execute. Mandatory.
81
+ # @option options [String] :c alias for :command
82
+ # @option options [RSpecSystem::Node] :node (defaults to what was defined
83
+ # default in your YAML file, otherwise if there is only one node it uses
84
+ # that) specifies node to execute command on.
85
+ # @option options [RSpecSystem::Node] :n alias for :node
86
+ # @overload $0(command)
87
+ # @param command [String] command to execute
88
+ # @yield [result] yields result when called as a block
89
+ # @yieldparam result [RSpecSystem::Helpers::Shell] result of run
90
+ # @return [RSpecSystem::Helpers::Shell] result of run
92
91
  # @example Using it as a helper
93
92
  # it 'test a command' do
94
93
  # shell 'cat /etc/hosts' do |r|
@@ -111,61 +110,15 @@ module RSpecSystem::Helpers
111
110
  # end
112
111
  # end
113
112
  def shell(options, &block)
114
- ns = rspec_system_node_set
115
- dn = ns.default_node
116
-
117
113
  # If options is a string, turn the string into a command in the normal
118
114
  # options hash.
119
115
  if options.is_a?(String)
120
116
  options = {:c => options}
121
117
  end
122
118
 
123
- # Defaults etc.
124
- options = {
125
- :node => options[:n] || dn,
126
- :n => options[:node] || dn,
127
- :c => options[:command],
128
- :command => options[:c],
129
- }.merge(options)
130
-
131
- if options[:c].nil?
132
- raise "Cannot use shell with no :command option"
133
- end
134
-
135
- result = RSpecSystem::Result.new(ns.run(options))
136
-
137
- if block_given?
138
- yield(result)
139
- else
140
- result
141
- end
142
- end
143
-
144
- # Legacy method for running a shell command.
145
- #
146
- # @deprecated Use {#shell} instead
147
- # @macro shell_method
148
- def system_run(options, &block)
149
- log.warn('system_run is deprecated, use shell instead')
150
-
151
- shell(options, &block)
119
+ RSpecSystem::Helpers::Shell.new(options, self, &block)
152
120
  end
153
121
 
154
- # @!macro rcp_method
155
- # @param options [Hash] options for command execution
156
- # @option options [String] :source_path source to copy files from (currently
157
- # only locally)
158
- # @option options [String] :sp alias for source_path
159
- # @option options [String] :destination_path destination for copy
160
- # @option options [String] :dp alias for dest_path
161
- # @option options [RSpecSystem::Node] :destination_node (default_node) destination node
162
- # to transfer files to. Optional.
163
- # @option options [RSpecSystem::Node] :d alias for destination_node
164
- # @option options [RSpecSystem::Node] :source_node ('') Reserved
165
- # for future use. Patches welcome.
166
- # @option options [RSpecSystem::Node] :s alias for source_node
167
- # @return [Bool] returns true if successful
168
-
169
122
  # Remotely copy files to a test host
170
123
  #
171
124
  # Just specify a source path, destination path, and optionally a destination
@@ -175,56 +128,41 @@ module RSpecSystem::Helpers
175
128
  # node provider, however this abstraction should mean you shouldn't need
176
129
  # to worry about that.
177
130
  #
178
- # @macro rcp_method
131
+ # @param options [Hash] options for command execution
132
+ # @option options [String] :source_path source to copy files from (currently
133
+ # only locally)
134
+ # @option options [String] :sp alias for source_path
135
+ # @option options [String] :destination_path destination for copy
136
+ # @option options [String] :dp alias for dest_path
137
+ # @option options [RSpecSystem::Node] :destination_node (default_node) destination node
138
+ # to transfer files to. Optional.
139
+ # @option options [RSpecSystem::Node] :d alias for destination_node
140
+ # @option options [RSpecSystem::Node] :source_node ('') Reserved
141
+ # for future use. Patches welcome.
142
+ # @option options [RSpecSystem::Node] :s alias for source_node
143
+ # @yield [result] yields result when called as a block
144
+ # @yieldparam result [RSpecSystem::Helpers::Rcp] result of rcp
145
+ # @return [RSpecSystem::Helpers::Rcp] result of rcp
179
146
  # @example Copying a path remotely
180
147
  # describe 'test running' do
181
148
  # it 'copy my files' do
182
149
  # rcp :sp => 'mydata', :dp => '/srv/data'.should be_true
183
150
  # end
184
151
  # end
185
- def rcp(options)
186
- ns = rspec_system_node_set
187
- options = {
188
- :source_path => options[:sp],
189
- :destination_path => options[:dp],
190
- :dp => options[:destination_path],
191
- :sp => options[:source_path],
192
- :destination_node => ns.default_node,
193
- :d => ns.default_node,
194
- :source_node => nil,
195
- :s => nil,
196
- }.merge(options)
197
-
198
- d = options[:d]
199
- sp = options[:sp]
200
- dp = options[:dp]
201
-
202
- log.info("rcp from #{sp} to #{d.name}:#{dp} executed")
203
- ns.rcp(options)
204
- end
205
-
206
- # Legacy method for copying a file to a test host
207
- #
208
- # @deprecated Use {#rcp} instead
209
- # @macro rcp_method
210
- def system_rcp(options)
211
- log.warn('system_rcp is deprecated, use rcp instead')
212
- rcp(options)
152
+ def rcp(options, &block)
153
+ RSpecSystem::Helpers::Rcp.new(options, self, &block)
213
154
  end
214
155
 
215
156
  # @!group Queries
216
157
 
217
- # @!macro node_method
218
- # @param options [Hash] search criteria
219
- # @option options [String] :name the canonical name of the node
220
- # @return [RSpecSystem::Node] node object
221
-
222
158
  # Returns a particular node object from the current nodeset given a set of
223
159
  # criteria.
224
160
  #
225
161
  # If no options are supplied, it tries to return the default node.
226
162
  #
227
- # @macro node_method
163
+ # @param options [Hash] search criteria
164
+ # @option options [String] :name the canonical name of the node
165
+ # @return [RSpecSystem::Node] node object
228
166
  def node(options = {})
229
167
  ns = rspec_system_node_set
230
168
  options = {
@@ -239,13 +177,4 @@ module RSpecSystem::Helpers
239
177
  return ns.nodes[name]
240
178
  end
241
179
  end
242
-
243
- # Legacy method for querying nodes
244
- #
245
- # @deprecated Use {#node} instead
246
- # @macro node_method
247
- def system_node(options = {})
248
- log.warn('system_node is deprecated, use node instead')
249
- node(options)
250
- end
251
180
  end
@@ -0,0 +1,37 @@
1
+ require 'rspec-system'
2
+
3
+ module RSpecSystem::Helpers
4
+ # Helper object behind RSpecSystem::Helpers#shell
5
+ class Rcp < RSpecSystem::Helper
6
+ name 'rcp'
7
+ properties :success
8
+
9
+ def initialize(opts, clr, &block)
10
+ ns = rspec_system_node_set
11
+ opts = {
12
+ :source_path => opts[:sp],
13
+ :destination_path => opts[:dp],
14
+ :dp => opts[:destination_path],
15
+ :sp => opts[:source_path],
16
+ :destination_node => ns.default_node,
17
+ :d => ns.default_node,
18
+ :source_node => nil,
19
+ :s => nil,
20
+ }.merge(opts)
21
+
22
+ super(opts, clr, &block)
23
+ end
24
+
25
+ # Gathers new results by executing the resource action
26
+ def execute
27
+ ns = rspec_system_node_set
28
+ d = opts[:d]
29
+ sp = opts[:sp]
30
+ dp = opts[:dp]
31
+
32
+ log.info("rcp from #{sp} to #{d.name}:#{dp} executed")
33
+ result = ns.rcp(opts)
34
+ { :success => result }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ require 'rspec-system'
2
+
3
+ module RSpecSystem::Helpers
4
+ # Helper object behind RSpecSystem::Helpers#shell
5
+ class Shell < RSpecSystem::Helper
6
+ name 'shell'
7
+ properties :stdout, :stderr, :exit_code
8
+
9
+ # Initializer for Shell object.
10
+ #
11
+ # This should be initialized via the helper method, not directly.
12
+ #
13
+ # @api private
14
+ # @param opts [Hash] options hash
15
+ # @param clr [Object] caller object
16
+ # @param block [Proc] code block
17
+ # @see RSpecSystem::Helpers#shell helper method
18
+ def initialize(opts, clr, &block)
19
+ # Defaults
20
+ opts = {
21
+ :c => opts[:command],
22
+ :command => opts[:c],
23
+ }.merge(opts)
24
+
25
+ if opts[:c].nil?
26
+ raise "Cannot use shell with no :command or :c option"
27
+ end
28
+
29
+ super(opts, clr, &block)
30
+ end
31
+
32
+ # Gathers new results by executing the resource action
33
+ def execute
34
+ rspec_system_node_set.run(opts)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,98 @@
1
+ require 'rspec-system'
2
+
3
+ # This is a helper module that exposes some internal helpers used by the main
4
+ # public ones, also the startup and teardown routines.
5
+ #
6
+ # @api private
7
+ module RSpecSystem::InternalHelpers
8
+ # Return the path to the nodeset file
9
+ #
10
+ # @return [Pathname]
11
+ def nodeset
12
+ Pathname.new(File.join(File.basename(__FILE__), '..', '.nodeset.yml'))
13
+ end
14
+
15
+ # Return the path to the custom prefabs file
16
+ #
17
+ # @return [Pathname]
18
+ def custom_prefabs_path
19
+ Pathname.new(File.expand_path(File.join(File.basename(__FILE__), '..', '.prefabs.yml')))
20
+ end
21
+
22
+ # Return the path to the temporary directory
23
+ #
24
+ # @return [Pathname]
25
+ def rspec_system_tmp
26
+ path = ENV["RSPEC_SYSTEM_TMP"] || File.expand_path(File.join(File.basename(__FILE__), '..', '.rspec_system'))
27
+ FileUtils.mkdir_p(path)
28
+ Pathname.new(path)
29
+ end
30
+
31
+ # Return the nodeset configuration hash
32
+ #
33
+ # @return [Hash] nodeset configuration
34
+ def rspec_system_config
35
+ YAML.load_file('.nodeset.yml')
36
+ end
37
+
38
+ # Grab the type of virtual environment we wish to run these tests in
39
+ #
40
+ # @return [String] current virtual env type
41
+ def rspec_virtual_env
42
+ ENV["RSPEC_VIRTUAL_ENV"] || 'vagrant'
43
+ end
44
+
45
+ # Defines if a set will be destroyed before and after tests
46
+ #
47
+ # @return [Boolean]
48
+ def rspec_destroy
49
+ return false if ENV["RSPEC_DESTROY"] =~ /(no|false)/
50
+ return true
51
+ end
52
+
53
+ # Return the current nodeset object
54
+ #
55
+ # @return [RSpecSystem::NodeSet::Base] current nodeset object
56
+ def rspec_system_node_set
57
+ setname = ENV['RSPEC_SET'] || rspec_system_config['default_set']
58
+ config = rspec_system_config['sets'][setname]
59
+ options = {}
60
+ options[:destroy] = rspec_destroy
61
+ RSpecSystem::NodeSet.create(setname, config, rspec_virtual_env, custom_prefabs_path, options)
62
+ end
63
+
64
+ # Start all nodes
65
+ #
66
+ # @return [void]
67
+ def start_nodes
68
+ ns = rspec_system_node_set
69
+
70
+ puts "Starting nodes"
71
+ puts
72
+ puts "Setname is: " + ns.setname
73
+ puts "Configuration is: " + ns.config.pretty_inspect
74
+ puts "Virtual Environment type is: #{ns.env_type}"
75
+ puts "Default node is: #{ns.default_node.name}"
76
+ puts "Destroy node is: #{ns.destroy}"
77
+ puts
78
+
79
+ ns.setup
80
+
81
+ puts
82
+ puts "Finished starting nodes"
83
+ puts "================================================================="
84
+ nil
85
+ end
86
+
87
+ # Stop all nodes
88
+ #
89
+ # @return [void]
90
+ def stop_nodes
91
+ puts 'Stopping nodes'
92
+ puts
93
+ rspec_system_node_set.teardown
94
+ puts 'Finished stopping nodes'
95
+ puts "================================================================="
96
+ nil
97
+ end
98
+ end
@@ -1,6 +1,10 @@
1
+ require 'rspec-system'
2
+
1
3
  module RSpecSystem
2
4
  # This class represents a node in a nodeset
3
5
  class Node
6
+ include RSpecSystem::InternalHelpers
7
+
4
8
  # Static helper for generating a node direct from the hash returned by
5
9
  # the nodeset YAML file.
6
10
  #
@@ -77,5 +81,19 @@ module RSpecSystem
77
81
  def provider_specifics
78
82
  @provider_specifics
79
83
  end
84
+
85
+ # Return name when stringified
86
+ #
87
+ # @return [String] name of node
88
+ def to_s
89
+ name
90
+ end
91
+
92
+ # Return name when inspected
93
+ #
94
+ # @return [String] name of node
95
+ def inspect
96
+ name
97
+ end
80
98
  end
81
99
  end
@@ -48,7 +48,7 @@ module RSpecSystem
48
48
  # @param opts [Hash] options hash containing :n (node) and :c (command)
49
49
  # @return [Hash] a hash containing :stderr, :stdout and :exit_code
50
50
  # @abstract Override this method providing your own shell running code
51
- def run(options)
51
+ def run(opts)
52
52
  raise "Unimplemented method #run"
53
53
  end
54
54
 
@@ -60,7 +60,7 @@ module RSpecSystem
60
60
  # @option opts [String] :dp destination path
61
61
  # @return [Boolean] returns true if command succeeded, false otherwise
62
62
  # @abstract Override this method providing your own file transfer code
63
- def rcp(options)
63
+ def rcp(opts)
64
64
  raise "Unimplemented method #rcp"
65
65
  end
66
66
 
@@ -1,11 +1,21 @@
1
+ require 'rspec-system'
1
2
  require 'ostruct'
2
3
 
3
4
  module RSpecSystem
4
- # This class represents a result from a helper command
5
+ # This class represents raw results from a helper command
5
6
  class Result < OpenStruct
6
- # Returns the value of a member.
7
+ # Returns the value of a member, with hash syntax.
8
+ #
9
+ # @param name [String, Symbol] name of parameter to retrieve
7
10
  def [](name)
8
11
  @table[name.to_sym]
9
12
  end
13
+
14
+ # Return a hash
15
+ #
16
+ # @return [Hash] a hash representation of the results
17
+ def to_hash
18
+ @table
19
+ end
10
20
  end
11
21
  end
@@ -10,90 +10,17 @@ include RSpecSystem::Helpers
10
10
 
11
11
  RSpec.configure do |c|
12
12
  include RSpecSystem::Log
13
+ include RSpecSystem::InternalHelpers
13
14
  c.include RSpecSystem::Helpers
15
+ c.include RSpecSystem::InternalHelpers
16
+ c.extend RSpecSystem::Helpers
14
17
 
15
18
  # This provides a path to save vagrant files
16
19
  c.add_setting :system_tmp
17
- # Block to execute for environment setup
18
- c.add_setting :system_setup_block
19
20
  # Storage for ssh channels
20
21
  c.add_setting :ssh_channels, :default => {}
21
22
  c.add_setting :rspec_storage, :default => {}
22
23
 
23
- def nodeset
24
- Pathname.new(File.join(File.basename(__FILE__), '..', '.nodeset.yml'))
25
- end
26
-
27
- def custom_prefabs_path
28
- File.expand_path(File.join(File.basename(__FILE__), '..', '.prefabs.yml'))
29
- end
30
-
31
- def rspec_system_tmp
32
- path = ENV["RSPEC_SYSTEM_TMP"] || File.expand_path(File.join(File.basename(__FILE__), '..', '.rspec_system'))
33
- FileUtils.mkdir_p(path)
34
- path
35
- end
36
-
37
- def rspec_system_config
38
- YAML.load_file('.nodeset.yml')
39
- end
40
-
41
- # Grab the type of virtual environment we wish to run these tests in
42
- def rspec_virtual_env
43
- ENV["RSPEC_VIRTUAL_ENV"] || 'vagrant'
44
- end
45
-
46
- # Defines if a set will be destroyed before and after tests
47
- def rspec_destroy
48
- return false if ENV["RSPEC_DESTROY"] =~ /(no|false)/
49
- return true
50
- end
51
-
52
- def rspec_system_node_set
53
- setname = ENV['RSPEC_SET'] || rspec_system_config['default_set']
54
- config = rspec_system_config['sets'][setname]
55
- options = {}
56
- options[:destroy] = rspec_destroy
57
- RSpecSystem::NodeSet.create(setname, config, rspec_virtual_env, custom_prefabs_path, options)
58
- end
59
-
60
- def start_nodes
61
- ns = rspec_system_node_set
62
-
63
- puts "Starting nodes"
64
- puts
65
- puts "Setname is: " + ns.setname
66
- puts "Configuration is: " + ns.config.pretty_inspect
67
- puts "Virtual Environment type is: #{ns.env_type}"
68
- puts "Default node is: #{ns.default_node.name}"
69
- puts "Destroy node is: #{ns.destroy}"
70
- puts
71
-
72
- ns.setup
73
-
74
- puts
75
- puts "Finished starting nodes"
76
- puts "================================================================="
77
- end
78
-
79
- def stop_nodes
80
- puts 'Stopping nodes'
81
- puts
82
- rspec_system_node_set.teardown
83
- puts 'Finished stopping nodes'
84
- puts "================================================================="
85
- end
86
-
87
- def call_custom_setup_block
88
- # Run test specific setup routines
89
- if pr = RSpec.configuration.system_setup_block then
90
- log.info "Running custom setup block"
91
- log.warn "The system_setup_block methodology will be deprecated in the next major release, use before :suite instead"
92
- pr.call
93
- log.info "Finished running custom setup block"
94
- end
95
- end
96
-
97
24
  # Default the system_tmp dir to something random
98
25
  c.system_tmp = rspec_system_tmp
99
26
 
@@ -101,7 +28,6 @@ RSpec.configure do |c|
101
28
  # Before Suite exceptions get captured it seems
102
29
  begin
103
30
  start_nodes
104
- call_custom_setup_block
105
31
  rescue => ex
106
32
  puts ex.inspect + " in"
107
33
  puts ex.backtrace.join("\n ")
data/rspec-system.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
  Gem::Specification.new do |s|
3
3
  # Metadata
4
4
  s.name = "rspec-system"
5
- s.version = "1.7.1"
5
+ s.version = "2.0.0"
6
6
  s.authors = ["Ken Barber"]
7
7
  s.email = ["ken@bob.sh"]
8
8
  s.homepage = "https://github.com/puppetlabs/rspec-system"
@@ -1,10 +1,17 @@
1
1
  require 'rspec-system/spec_helper'
2
2
 
3
+ # A localized module for storing project specific helpers
3
4
  module LocalHelpers
5
+ # Return the project root
6
+ #
7
+ # @return [Pathname] root directory of project
4
8
  def proj_root
5
9
  Pathname.new(File.expand_path(File.join(File.dirname(__FILE__), '..')))
6
10
  end
7
11
 
12
+ # Return the fixture directory
13
+ #
14
+ # @return [Pathname] test fixture directory
8
15
  def fixture_root
9
16
  proj_root + 'spec' + 'fixtures'
10
17
  end
@@ -16,11 +23,4 @@ RSpec.configure do |c|
16
23
  c.before :suite do
17
24
  shell 'echo foobar > /tmp/setupblock'
18
25
  end
19
-
20
- # NOTE: this is deprecated, but we do this for legacy testing purposes
21
- # with the next major release we should remove this capability, and remove
22
- # the test. Do not use this in your own tests any more!
23
- c.system_setup_block = proc do
24
- shell 'echo foobar > /tmp/setupblockold'
25
- end
26
26
  end
@@ -1,29 +1,30 @@
1
1
  require 'spec_helper_system'
2
2
 
3
3
  describe "rcp:" do
4
- it 'check rcp works' do
4
+ it 'check rcp works with block matchers' do
5
5
  rcp(
6
6
  :sp => fixture_root + 'example_dir',
7
- :dp => '/tmp/example_destination'
8
- )
7
+ :dp => '/tmp/example_destination1'
8
+ ) do |r|
9
+ r.success.should be_true
10
+ end
9
11
 
10
- shell 'cat /tmp/example_destination/example_file' do |r|
12
+ shell 'cat /tmp/example_destination1/example_file' do |r|
11
13
  r.exit_code.should be_zero
12
14
  r.stdout.should =~ /Test content 1234/
13
15
  end
14
16
  end
15
17
 
16
- context 'legacy tests' do
17
- it 'check system_rcp works' do
18
- system_rcp(
19
- :sp => fixture_root + 'example_dir',
20
- :dp => '/tmp/example_destination'
21
- )
18
+ it 'check rcp works outside a block' do
19
+ r = rcp(
20
+ :sp => fixture_root + 'example_dir',
21
+ :dp => '/tmp/example_destination2'
22
+ )
23
+ r.success.should be_true
22
24
 
23
- shell 'cat /tmp/example_destination/example_file' do |r|
24
- r.exit_code.should be_zero
25
- r.stdout.should =~ /Test content 1234/
26
- end
25
+ shell 'cat /tmp/example_destination2/example_file' do |r|
26
+ r.exit_code.should be_zero
27
+ r.stdout.should =~ /Test content 1234/
27
28
  end
28
29
  end
29
30
  end
@@ -14,6 +14,12 @@ describe "shell:" do
14
14
  end
15
15
  end
16
16
 
17
+ it 'ensure it can be used outside a block' do
18
+ shell 'echo foobar > /tmp/foobarbaz'
19
+ r = shell 'cat /tmp/foobarbaz'
20
+ r.stdout.should =~ /foobar/
21
+ end
22
+
17
23
  it "cat /etc/hosts - test results using hash method" do
18
24
  shell "cat /etc/hosts" do |r|
19
25
  r[:exit_code].should be_zero
@@ -74,6 +80,39 @@ describe "shell:" do
74
80
  r.exit_code.should be_zero
75
81
  end
76
82
 
83
+ describe 'use in subject' do
84
+ context shell 'cat /etc/hosts' do
85
+ its(:stdout) { should =~ /localhost/ }
86
+ its(:exit_code) { should be_zero }
87
+ its(:stderr) { should be_empty }
88
+ end
89
+ end
90
+
91
+ context 'should not be lazy in a before :each block' do
92
+ before :each do
93
+ shell('echo foobarbaz > /tmp/eachblock')
94
+ end
95
+ context shell 'cat /tmp/eachblock' do
96
+ its(:stdout) { should =~ /foobarbaz/ }
97
+ end
98
+ end
99
+
100
+ context 'should not be lazy in a before inside its own context' do
101
+ context shell 'cat /tmp/eachblock2' do
102
+ before :each do
103
+ shell('echo foobarbaz > /tmp/eachblock2')
104
+ end
105
+ its(:stdout) { should =~ /foobarbaz/ }
106
+ end
107
+ end
108
+
109
+ it 'should be able to make shell lazy' do
110
+ shell(:c => 'echo foobarbaz > /tmp/forcelazy', :lazy => true)
111
+ shell 'cat /tmp/forcelazy' do |r|
112
+ r.stdout.should be_empty
113
+ end
114
+ end
115
+
77
116
  context 'legacy tests' do
78
117
  it 'cat /etc/hosts - test results using hash method' do
79
118
  shell 'cat /etc/hosts' do |r|
@@ -81,18 +120,22 @@ describe "shell:" do
81
120
  r[:stdout].should =~ /localhost/
82
121
  end
83
122
  end
123
+ end
124
+ end
84
125
 
85
- it 'cat /etc/hosts - using system_run' do
86
- system_run 'cat /etc/hosts' do |r|
87
- r.exit_code.should be_zero
88
- r.stdout.should =~ /localhost/
89
- end
90
- end
126
+ # Test as a top-level subject
127
+ describe shell('cat /etc/hosts') do
128
+ its(:stdout) { should =~ /localhost/ }
129
+ its(:stderr) { should be_empty }
130
+ its(:exit_code) { should be_zero }
131
+ end
91
132
 
92
- it 'cat /tmp/setupblockold to ensure the system_setup_block still works' do
93
- shell 'cat /tmp/setupblockold' do |r|
94
- r.stdout.should =~ /foobar/
95
- end
96
- end
97
- end
133
+ # Test as an explicit subject, this is a bad example but put here for complete-
134
+ # ness. The problem is that the subject will get called each time, so its not
135
+ # recommended to use it ths way.
136
+ describe 'cat /etc/hosts' do
137
+ subject { shell('cat /etc/hosts') }
138
+ its(:stdout) { should =~ /localhost/ }
139
+ its(:stderr) { should be_empty }
140
+ its(:exit_code) { should be_zero }
98
141
  end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'RSpecSystem::Helper' do
4
+ let(:node) { mock() }
5
+
6
+ before :each do
7
+ # Always stub default_node
8
+ RSpecSystem::Helper.any_instance.stubs(:default_node).returns(node)
9
+ end
10
+
11
+ context '#initialize' do
12
+ it 'should be instantiatable' do
13
+ RSpecSystem::Helper.any_instance.expects(:result_data).returns({})
14
+ RSpecSystem::Helper.new({}, self)
15
+ end
16
+
17
+ it 'called as a block, should execute block and return itself' do
18
+ RSpecSystem::Helper.any_instance.expects(:result_data)
19
+ block_exec = nil
20
+ RSpecSystem::Helper.new({}, self) do |r|
21
+ r.class.should == RSpecSystem::Helper
22
+ block_exec = true
23
+ end
24
+ block_exec.should be_true
25
+ end
26
+ end
27
+
28
+ context '#refresh' do
29
+ it 'should only be called once even if data requested again' do
30
+ RSpecSystem::Helper.any_instance.expects(:execute).once.returns({:test => true})
31
+ r = RSpecSystem::Helper.new({}, self)
32
+ r[:test].should be_true
33
+ r[:test].should be_true
34
+ end
35
+
36
+ it 'should call execute again' do
37
+ RSpecSystem::Helper.any_instance.expects(:execute).once
38
+ r = RSpecSystem::Helper.new({}, self)
39
+ r.expects(:execute).once
40
+ r.refresh
41
+ end
42
+ end
43
+
44
+ context '#[]' do
45
+ it 'should retrieve result data as a hash element' do
46
+ rd = RSpecSystem::Result.new(:test => true)
47
+ RSpecSystem::Helper.any_instance.expects(:result_data).twice.returns(rd)
48
+ r = RSpecSystem::Helper.new({}, self)
49
+ r[:test].should be_true
50
+ end
51
+ end
52
+
53
+ context '#result_data' do
54
+ it 'no initial result data request if lazy' do
55
+ RSpecSystem::Helper.any_instance.expects(:result_data).never
56
+ RSpecSystem::Helper.new({:lazy => true}, self)
57
+ end
58
+
59
+ it 'when lazy, will call result_data on first data request' do
60
+ RSpecSystem::Helper.any_instance.expects(:result_data).never
61
+ r = RSpecSystem::Helper.new({:lazy => true}, self)
62
+ r.expects(:result_data).returns(RSpecSystem::Result.new(:test => true))
63
+ r[:test].should be_true
64
+ end
65
+ end
66
+
67
+ context '#to_hash' do
68
+ it 'should call result_data.to_hash' do
69
+ rd = mock()
70
+ rd.expects(:to_hash).once.returns({:test => true})
71
+ RSpecSystem::Helper.any_instance.stubs(:result_data).returns(rd)
72
+ r = RSpecSystem::Helper.new({}, self)
73
+ r.to_hash.should == {:test => true}
74
+ end
75
+ end
76
+ end
@@ -10,4 +10,12 @@ describe RSpecSystem::Result do
10
10
  result = subject.class.new(:foo => 'bar')
11
11
  result[:foo].should == 'bar'
12
12
  end
13
+
14
+ it 'should allow you to retreive the full hash' do
15
+ result = subject.class.new(:foo => 'bar', :baz => 'bam')
16
+ result.to_hash.should == {
17
+ :foo => 'bar',
18
+ :baz => 'bam',
19
+ }
20
+ end
13
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-system
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.1
4
+ version: 2.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-12 00:00:00.000000000 Z
12
+ date: 2013-06-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -150,7 +150,11 @@ files:
150
150
  - examples/spec/system/test3_spec.rb
151
151
  - lib/rspec-system.rb
152
152
  - lib/rspec-system/formatter.rb
153
+ - lib/rspec-system/helper.rb
153
154
  - lib/rspec-system/helpers.rb
155
+ - lib/rspec-system/helpers/rcp.rb
156
+ - lib/rspec-system/helpers/shell.rb
157
+ - lib/rspec-system/internal_helpers.rb
154
158
  - lib/rspec-system/log.rb
155
159
  - lib/rspec-system/node.rb
156
160
  - lib/rspec-system/node_set.rb
@@ -173,6 +177,7 @@ files:
173
177
  - spec/spec_helper_system.rb
174
178
  - spec/system/rcp_spec.rb
175
179
  - spec/system/shell_spec.rb
180
+ - spec/unit/helper_spec.rb
176
181
  - spec/unit/kwalify-schemas/nodeset_schema_spec.rb
177
182
  - spec/unit/kwalify-schemas/prefabs_schema_spec.rb
178
183
  - spec/unit/result_spec.rb
@@ -205,6 +210,7 @@ summary: System testing with rspec
205
210
  test_files:
206
211
  - spec/system/rcp_spec.rb
207
212
  - spec/system/shell_spec.rb
213
+ - spec/unit/helper_spec.rb
208
214
  - spec/unit/kwalify-schemas/nodeset_schema_spec.rb
209
215
  - spec/unit/kwalify-schemas/prefabs_schema_spec.rb
210
216
  - spec/unit/result_spec.rb