rspec-bash 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -0
  3. data/Gemfile +1 -0
  4. data/README.md +23 -0
  5. data/Rakefile +15 -4
  6. data/bin/bash_stub.sh +92 -0
  7. data/bin/bash_wrapper.sh.erb +12 -0
  8. data/bin/ruby_stub.rb +33 -0
  9. data/lib/rspec/bash.rb +5 -4
  10. data/lib/rspec/bash/command.rb +5 -0
  11. data/lib/rspec/bash/command/call_configuration.rb +76 -0
  12. data/lib/rspec/bash/command/call_configuration_manager.rb +24 -0
  13. data/lib/rspec/bash/command/call_log.rb +48 -0
  14. data/lib/rspec/bash/command/call_log_manager.rb +38 -0
  15. data/lib/rspec/bash/command/stubbed_command.rb +64 -0
  16. data/lib/rspec/bash/server.rb +3 -0
  17. data/lib/rspec/bash/server/bash_stub_marshaller.rb +19 -0
  18. data/lib/rspec/bash/server/ruby_stub_marshaller.rb +13 -0
  19. data/lib/rspec/bash/server/stub_server.rb +47 -0
  20. data/lib/rspec/bash/stubbed_env.rb +75 -54
  21. data/lib/rspec/bash/util/call_conf_argument_list_matcher.rb +5 -5
  22. data/lib/rspec/bash/util/call_log_argument_list_matcher.rb +1 -1
  23. data/lib/rspec/bash/wrapper.rb +4 -0
  24. data/lib/rspec/bash/wrapper/bash_stub_script.rb +15 -0
  25. data/lib/rspec/bash/wrapper/bash_wrapper.rb +54 -0
  26. data/lib/rspec/bash/wrapper/ruby_stub_script.rb +15 -0
  27. data/lib/rspec/bash/wrapper/stub_function.rb +36 -0
  28. data/rspec-bash.gemspec +2 -1
  29. data/spec/classes/command/call_configuration_manager_spec.rb +68 -0
  30. data/spec/classes/{call_configuration_spec.rb → command/call_configuration_spec.rb} +51 -114
  31. data/spec/classes/command/call_log_manager_spec.rb +83 -0
  32. data/spec/classes/{call_log_spec.rb → command/call_log_spec.rb} +23 -82
  33. data/spec/classes/command/stubbed_command_spec.rb +118 -0
  34. data/spec/classes/server/bash_stub_marshaller_spec.rb +38 -0
  35. data/spec/classes/server/ruby_stub_marshaller_spec.rb +31 -0
  36. data/spec/classes/server/stub_server_spec.rb +121 -0
  37. data/spec/classes/stubbed_env_spec.rb +141 -280
  38. data/spec/classes/util/call_conf_argument_list_matcher_spec.rb +17 -17
  39. data/spec/classes/util/call_log_argument_list_matcher_spec.rb +24 -18
  40. data/spec/classes/wrapper/bash_wrapper_spec.rb +37 -0
  41. data/spec/classes/wrapper/ruby_stub_script_spec.rb +204 -0
  42. data/spec/helper/string_file_io.rb +1 -1
  43. data/spec/integration/call_log/called_with_args_spec.rb +8 -4
  44. data/spec/integration/call_log/called_with_no_args_spec.rb +1 -1
  45. data/spec/integration/call_log/stdin_spec.rb +10 -4
  46. data/spec/integration/edge_cases_spec.rb +34 -0
  47. data/spec/integration/matchers/be_called_with_arguments_spec.rb +12 -13
  48. data/spec/integration/matchers/be_called_with_no_arguments_spec.rb +6 -7
  49. data/spec/integration/stubbed_command/outputs_spec.rb +111 -91
  50. data/spec/integration/stubbed_command/returns_exitstatus_spec.rb +46 -37
  51. data/spec/integration/stubbed_env/execute_with_env_vars_spec.rb +3 -4
  52. data/spec/integration/stubbed_env/execute_with_path_spec.rb +6 -7
  53. data/spec/integration/stubbed_env/execute_with_stub_wrapper_spec.rb +4 -12
  54. data/spec/integration/stubbed_env/override_spec.rb +354 -0
  55. data/spec/integration/wrapper/bash_stub_script_spec.rb +383 -0
  56. data/spec/integration/wrapper/bash_wrapper_spec.rb +48 -0
  57. data/spec/scripts/function_library.sh +9 -1
  58. data/spec/spec_helper.rb +2 -0
  59. metadata +65 -21
  60. data/bin/function_override.sh.erb +0 -7
  61. data/bin/function_override_wrapper.sh.erb +0 -19
  62. data/bin/stub.rb.erb +0 -56
  63. data/lib/rspec/bash/call_configuration.rb +0 -62
  64. data/lib/rspec/bash/call_log.rb +0 -71
  65. data/lib/rspec/bash/stubbed_command.rb +0 -88
  66. data/spec/classes/stub_spec.rb +0 -510
  67. data/spec/classes/stubbed_command_spec.rb +0 -134
  68. data/spec/integration/assert_called_spec.rb +0 -0
@@ -0,0 +1,36 @@
1
+ module Rspec
2
+ module Bash
3
+ class StubFunction
4
+ def initialize(port, stub_script_class)
5
+ @port = port
6
+ @stub_script_class = stub_script_class
7
+ end
8
+
9
+ def header(name)
10
+ "function #{name} {"
11
+ end
12
+
13
+ def footer(name)
14
+ "}\nreadonly -f #{name} &> /dev/null"
15
+ end
16
+
17
+ def body(name)
18
+ "#{stub_path} #{name} #{@port} \"${@}\""
19
+ end
20
+
21
+ def script(name)
22
+ <<-multiline_string
23
+ #{header(name)}
24
+ #{body(name)}
25
+ #{footer(name)}
26
+ multiline_string
27
+ end
28
+
29
+ private
30
+
31
+ def stub_path
32
+ @stub_script_class.path
33
+ end
34
+ end
35
+ end
36
+ end
data/rspec-bash.gemspec CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'rspec-bash'
7
- spec.version = '0.1.1'
7
+ spec.version = '0.2.0'
8
8
  spec.authors = ['Ben Brewer', 'Mike Urban', 'Matthijs Groen']
9
9
  spec.email = ['ben@benbrewer.me', 'mike.david.urban@gmail.com']
10
10
  spec.summary = 'Test Bash with RSpec'
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ['lib']
21
21
 
22
+ spec.add_runtime_dependency 'sparsify', '~> 1.1'
22
23
  spec.add_development_dependency 'bundler', '~> 1.6'
23
24
  spec.add_development_dependency 'rake', '~> 10.0'
24
25
  end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+ include Rspec::Bash
3
+
4
+ describe 'CallConfigurationManager' do
5
+ subject { CallConfigurationManager.new }
6
+
7
+ context 'with a command call configuration' do
8
+ let(:first_command_call_conf) do
9
+ call_conf = double(CallConfiguration)
10
+ allow(CallConfiguration).to receive(:new)
11
+ .and_return(call_conf).once
12
+ call_conf
13
+ end
14
+ context '#set_exitcode' do
15
+ it 'passes the exit code along to the correct CallConfiguration' do
16
+ expect(first_command_call_conf).to receive(:set_exitcode)
17
+ .with(0, %w(first_argument second_argument)).once
18
+ expect(first_command_call_conf).to receive(:set_exitcode)
19
+ .with(1, %w(first_argument second_argument)).once
20
+
21
+ subject.set_exitcode('first_command', 0, %w(first_argument second_argument))
22
+ subject.set_exitcode('first_command', 1, %w(first_argument second_argument))
23
+ end
24
+ end
25
+ context '#add_output' do
26
+ it 'passes the output addition along to the correct CallConfiguration' do
27
+ expect(first_command_call_conf).to receive(:add_output)
28
+ .with('hello', :stdout, %w(first_argument second_argument)).once
29
+ expect(first_command_call_conf).to receive(:add_output)
30
+ .with('world', :stderr, %w(first_argument second_argument)).once
31
+
32
+ subject.add_output('first_command', 'hello', :stdout, %w(first_argument second_argument))
33
+ subject.add_output('first_command', 'world', :stderr, %w(first_argument second_argument))
34
+ end
35
+ end
36
+ context '#get_best_call_conf' do
37
+ it 'passes the query along to the correct CallConfiguration' do
38
+ allow(first_command_call_conf).to receive(:get_best_call_conf)
39
+ .with(%w(first_argument second_argument))
40
+ .and_return(
41
+ args: %w(first_argument second_argument),
42
+ exitcode: 0,
43
+ outputs: []
44
+ ).once
45
+ allow(first_command_call_conf).to receive(:get_best_call_conf)
46
+ .with(%w(first_argument other_argument))
47
+ .and_return(
48
+ args: %w(first_argument other_argument),
49
+ exitcode: 1,
50
+ outputs: []
51
+ ).once
52
+
53
+ expect(subject.get_best_call_conf('first_command', %w(first_argument second_argument)))
54
+ .to eql(
55
+ args: %w(first_argument second_argument),
56
+ exitcode: 0,
57
+ outputs: []
58
+ )
59
+ expect(subject.get_best_call_conf('first_command', %w(first_argument other_argument)))
60
+ .to eql(
61
+ args: %w(first_argument other_argument),
62
+ exitcode: 1,
63
+ outputs: []
64
+ )
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,20 +1,11 @@
1
1
  require 'spec_helper'
2
+ include Rspec::Bash
2
3
 
3
4
  describe 'CallConfiguration' do
4
- let(:stubbed_env) { create_stubbed_env }
5
- include Rspec::Bash
6
-
7
- let(:mock_conf_file) { StringFileIO.new }
8
- let(:mock_conf_pathname) { instance_double(Pathname) }
9
- before(:each) do
10
- allow(mock_conf_pathname).to receive(:open).with('r').and_yield(mock_conf_file)
11
- allow(mock_conf_pathname).to receive(:open).with('w').and_yield(mock_conf_file)
12
- end
5
+ subject { Rspec::Bash::CallConfiguration.new }
13
6
 
14
7
  context '#set_exitcode' do
15
8
  context 'with any setup' do
16
- subject { Rspec::Bash::CallConfiguration.new(mock_conf_pathname, 'command_name') }
17
-
18
9
  context 'with no existing configuration' do
19
10
  let(:expected_conf) do
20
11
  [
@@ -30,11 +21,6 @@ describe 'CallConfiguration' do
30
21
  subject.set_exitcode(1, %w(first_argument second_argument))
31
22
  expect(subject.call_configuration).to eql expected_conf
32
23
  end
33
-
34
- it 'writes that configuration to its conf file' do
35
- expect(mock_conf_file).to receive(:write).with(expected_conf.to_yaml)
36
- subject.set_exitcode(1, %w(first_argument second_argument))
37
- end
38
24
  end
39
25
  context 'with an existing, non-matching configuration' do
40
26
  let(:expected_conf) do
@@ -52,7 +38,7 @@ describe 'CallConfiguration' do
52
38
  }
53
39
  ]
54
40
  end
55
- before(:each) do
41
+ before do
56
42
  subject.call_configuration = [
57
43
  {
58
44
  args: %w(first_argument),
@@ -65,11 +51,6 @@ describe 'CallConfiguration' do
65
51
  subject.set_exitcode(1, %w(first_argument second_argument))
66
52
  expect(subject.call_configuration).to eql expected_conf
67
53
  end
68
-
69
- it 'writes that configuration to its conf file' do
70
- expect(mock_conf_file).to receive(:write).with(expected_conf.to_yaml)
71
- subject.set_exitcode(1, %w(first_argument second_argument))
72
- end
73
54
  end
74
55
  context 'with an existing, matching configuration' do
75
56
  let(:expected_conf) do
@@ -81,7 +62,7 @@ describe 'CallConfiguration' do
81
62
  }
82
63
  ]
83
64
  end
84
- before(:each) do
65
+ before do
85
66
  subject.call_configuration = [
86
67
  {
87
68
  args: %w(first_argument second_argument),
@@ -95,26 +76,11 @@ describe 'CallConfiguration' do
95
76
  subject.set_exitcode(1, %w(first_argument second_argument))
96
77
  expect(subject.call_configuration).to eql expected_conf
97
78
  end
98
-
99
- it 'writes that configuration to its conf file' do
100
- expect(mock_conf_file).to receive(:write).with(expected_conf.to_yaml)
101
- subject.set_exitcode(1, %w(first_argument second_argument))
102
- end
103
- end
104
- end
105
- context 'with no config_path' do
106
- subject { Rspec::Bash::CallConfiguration.new(nil, anything) }
107
- it 'raises an error' do
108
- expect do
109
- subject.set_exitcode(1, %w(first_argument second_argument))
110
- end.to raise_exception(NoMethodError)
111
79
  end
112
80
  end
113
81
  end
114
82
  context '#add_output' do
115
83
  context 'with any setup' do
116
- subject { Rspec::Bash::CallConfiguration.new(mock_conf_pathname, 'command_name') }
117
-
118
84
  context 'with no existing configuration' do
119
85
  let(:expected_conf) do
120
86
  [
@@ -134,11 +100,6 @@ describe 'CallConfiguration' do
134
100
  subject.add_output('new_content', :stderr, %w(first_argument second_argument))
135
101
  expect(subject.call_configuration).to eql expected_conf
136
102
  end
137
-
138
- it 'writes that configuration to its conf file' do
139
- expect(mock_conf_file).to receive(:write).with(expected_conf.to_yaml)
140
- subject.add_output('new_content', :stderr, %w(first_argument second_argument))
141
- end
142
103
  end
143
104
  context 'with an existing, non-matching configuration' do
144
105
  let(:expected_conf) do
@@ -165,7 +126,7 @@ describe 'CallConfiguration' do
165
126
  }
166
127
  ]
167
128
  end
168
- before(:each) do
129
+ before do
169
130
  subject.call_configuration = [
170
131
  {
171
132
  args: %w(first_argument),
@@ -183,11 +144,6 @@ describe 'CallConfiguration' do
183
144
  subject.add_output('new_content', :stderr, %w(first_argument second_argument))
184
145
  expect(subject.call_configuration).to eql expected_conf
185
146
  end
186
-
187
- it 'writes that configuration to its conf file' do
188
- expect(mock_conf_file).to receive(:write).with(expected_conf.to_yaml)
189
- subject.add_output('new_content', :stderr, %w(first_argument second_argument))
190
- end
191
147
  end
192
148
  context 'with an existing, matching configuration' do
193
149
  let(:expected_conf) do
@@ -208,7 +164,7 @@ describe 'CallConfiguration' do
208
164
  }
209
165
  ]
210
166
  end
211
- before(:each) do
167
+ before do
212
168
  subject.call_configuration = [
213
169
  {
214
170
  args: %w(first_argument second_argument),
@@ -226,82 +182,63 @@ describe 'CallConfiguration' do
226
182
  subject.add_output('new_content', :stderr, %w(first_argument second_argument))
227
183
  expect(subject.call_configuration).to eql expected_conf
228
184
  end
229
-
230
- it 'writes that configuration to its conf file' do
231
- expect(mock_conf_file).to receive(:write).with(expected_conf.to_yaml)
232
- subject.add_output('new_content', :stderr, %w(first_argument second_argument))
233
- end
234
- end
235
- end
236
- context 'with no config_path' do
237
- subject { Rspec::Bash::CallConfiguration.new(nil, anything) }
238
- it 'raises an error' do
239
- expect do
240
- subject.add_output('new_content', :stderr, %w(first_argument second_argument))
241
- end.to raise_exception(NoMethodError)
242
185
  end
243
186
  end
244
187
  end
245
- context '#call_configuration' do
246
- context 'when there is no config_path' do
247
- subject { Rspec::Bash::CallConfiguration.new(nil, anything) }
248
- it 'returns an empty array' do
249
- expect(subject.call_configuration).to eql []
250
- end
251
- end
252
- context 'when the conf file exists but is empty' do
253
- subject { Rspec::Bash::CallConfiguration.new(mock_conf_pathname, anything) }
254
- before(:each) do
255
- allow(mock_conf_file).to receive(:read).and_return('')
256
- end
257
- it 'returns an empty array' do
258
- expect(subject.call_configuration).to eql []
259
- end
260
- end
261
- context 'when the call log file open throws a file not found exception' do
262
- subject { Rspec::Bash::CallConfiguration.new(mock_conf_pathname, anything) }
263
- before(:each) do
264
- allow(mock_conf_pathname).to receive(:open).with('r').and_raise(Errno::ENOENT)
265
- end
266
- it 'returns an empty array' do
267
- expect(subject.call_configuration).to eql []
188
+ context '#get_best_call_conf' do
189
+ context 'with any setup' do
190
+ context 'with no existing configuration' do
191
+ it 'updates the status code conf for the arguments passed in' do
192
+ call_conf = subject.get_best_call_conf(%w(first_argument second_argument))
193
+ expect(call_conf).to eql({})
194
+ end
268
195
  end
269
- end
270
- context 'when setup is valid' do
271
- subject { Rspec::Bash::CallConfiguration.new(mock_conf_pathname, 'command_name') }
272
- let(:conf) do
273
- [{
274
- args: %w(first_argument second_argument),
275
- exitcode: 1,
276
- outputs: [
277
- {
278
- target: :stdout,
279
- content: 'old_content'
280
- },
196
+ context 'with an existing, non-matching configuration' do
197
+ before do
198
+ subject.call_configuration = [
281
199
  {
282
- target: :stderr,
283
- content: 'new_content'
200
+ args: %w(first_argument),
201
+ exitcode: 1,
202
+ outputs: []
284
203
  }
285
204
  ]
286
- }]
287
- end
288
- context 'and no configuration exists' do
289
- before(:each) do
290
- allow(mock_conf_file).to receive(:read).and_return(conf.to_yaml)
291
- allow(mock_conf_pathname).to receive(:open).with('r').and_yield(mock_conf_file)
292
205
  end
293
-
294
- it 'reads out what was in its configuration file' do
295
- expect(subject.call_configuration).to eql conf
206
+ it 'returns an empty hash indicating no match was found' do
207
+ call_conf = subject.get_best_call_conf(%w(first_argument second_argument))
208
+ expect(call_conf).to eql({})
296
209
  end
297
210
  end
298
- context 'and a configuration already exists' do
299
- before(:each) do
300
- subject.call_configuration = conf
211
+ context 'with an existing, matching configuration' do
212
+ let(:expected_conf) do
213
+ {
214
+ exitcode: 2,
215
+ outputs: [
216
+ target: 'first_argument-something-second_argument-another.txt',
217
+ content: 'dynamically generated file name contents'
218
+ ]
219
+ }
220
+ end
221
+ before do
222
+ subject.call_configuration = [
223
+ {
224
+ args: %w(first_argument second_argument),
225
+ exitcode: 2,
226
+ outputs: [
227
+ target: [
228
+ :arg1,
229
+ '-something-',
230
+ :arg2,
231
+ '-another.txt'
232
+ ],
233
+ content: 'dynamically generated file name contents'
234
+ ]
235
+ }
236
+ ]
301
237
  end
302
238
 
303
- it 'reads out what was in its configuration file' do
304
- expect(subject.call_configuration).to eql conf
239
+ it 'returns the matching hash with args removed and paths adjusted' do
240
+ call_conf = subject.get_best_call_conf(%w(first_argument second_argument))
241
+ expect(call_conf).to eql expected_conf
305
242
  end
306
243
  end
307
244
  end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+ include Rspec::Bash
3
+
4
+ describe 'CallLogManager' do
5
+ subject { CallLogManager.new }
6
+
7
+ context 'with a command call configuration' do
8
+ let(:first_command_call_log) do
9
+ call_log = double(CallLog)
10
+ allow(CallLog).to receive(:new)
11
+ .and_return(call_log).once
12
+ call_log
13
+ end
14
+
15
+ context '#add_log' do
16
+ it 'passes the logs to their respective calllogs' do
17
+ expect(first_command_call_log).to receive(:add_log)
18
+ .with('stdin', %w(first_argument second_argument)).twice
19
+
20
+ subject.add_log('first_command', 'stdin', %w(first_argument second_argument))
21
+ subject.add_log('first_command', 'stdin', %w(first_argument second_argument))
22
+ end
23
+ end
24
+
25
+ context '#stdin_for_args' do
26
+ it 'gets the respective stdin for an array of arguments' do
27
+ allow(first_command_call_log).to receive(:stdin_for_args)
28
+ .with(%w(first_argument second_argument))
29
+ .and_return('first_command stdin for [first_argument, second_argument]')
30
+ allow(first_command_call_log).to receive(:stdin_for_args)
31
+ .with(%w(third_argument fourth_argument))
32
+ .and_return('first_command stdin for [third_argument, fourth_argument]')
33
+
34
+ expect(subject.stdin_for_args('first_command', %w(first_argument second_argument)))
35
+ .to eql('first_command stdin for [first_argument, second_argument]')
36
+ expect(subject.stdin_for_args('first_command', %w(third_argument fourth_argument)))
37
+ .to eql('first_command stdin for [third_argument, fourth_argument]')
38
+ end
39
+ end
40
+
41
+ context '#call_count' do
42
+ it 'gets the respective call count for an array of arguments' do
43
+ allow(first_command_call_log).to receive(:call_count)
44
+ .with(%w(first_argument second_argument))
45
+ .and_return(2)
46
+ allow(first_command_call_log).to receive(:call_count)
47
+ .with(%w(third_argument fourth_argument))
48
+ .and_return(3)
49
+
50
+ expect(subject.call_count('first_command', %w(first_argument second_argument)))
51
+ .to eql(2)
52
+ expect(subject.call_count('first_command', %w(third_argument fourth_argument)))
53
+ .to eql(3)
54
+ end
55
+ end
56
+
57
+ context '#called_with_args?' do
58
+ it 'gets the respective call status for the arguments' do
59
+ allow(first_command_call_log).to receive(:called_with_args?)
60
+ .with(%w(first_argument second_argument))
61
+ .and_return(true)
62
+ allow(first_command_call_log).to receive(:called_with_args?)
63
+ .with(%w(third_argument fourth_argument))
64
+ .and_return(false)
65
+
66
+ expect(subject.called_with_args?('first_command', %w(first_argument second_argument)))
67
+ .to eql(true)
68
+ expect(subject.called_with_args?('first_command', %w(third_argument fourth_argument)))
69
+ .to eql(false)
70
+ end
71
+ end
72
+
73
+ context '#called_with_no_args?' do
74
+ it 'gets the respective call status for the arguments' do
75
+ allow(first_command_call_log).to receive(:called_with_no_args?)
76
+ .and_return(true)
77
+
78
+ expect(subject.called_with_no_args?('first_command'))
79
+ .to eql(true)
80
+ end
81
+ end
82
+ end
83
+ end