rspec-shell-expectations 0.0.1 → 1.0.0.pre.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.travis.yml +0 -1
- data/Gemfile +1 -0
- data/README.md +63 -15
- data/Rakefile +7 -1
- data/bin/stub +40 -0
- data/features/README.md +15 -0
- data/features/developer/assert_calls.feature +15 -0
- data/features/developer/assert_stdin.feature +13 -0
- data/features/developer/change_exitstatus.feature +36 -0
- data/features/developer/provide-env-vars.feature +20 -0
- data/features/developer/step_definitions/general_steps.rb +85 -0
- data/features/developer/stub_commands.feature +21 -0
- data/features/developer/stub_output.feature +37 -0
- data/features/developer/support/simulated_env.rb +9 -0
- data/features/developer/support/tempfiles.rb +9 -0
- data/features/developer/support/workfolder.rb +14 -0
- data/lib/rspec/shell/expectations/call_configuration.rb +40 -0
- data/lib/rspec/shell/expectations/call_log.rb +41 -0
- data/lib/rspec/shell/expectations/stubbed_call.rb +34 -0
- data/lib/rspec/shell/expectations/stubbed_command.rb +44 -0
- data/lib/rspec/shell/expectations/stubbed_env.rb +6 -4
- data/lib/rspec/shell/expectations/version.rb +1 -1
- data/lib/rspec/shell/expectations.rb +4 -0
- data/spec/assert_called_spec.rb +43 -0
- data/spec/assert_stdin_spec.rb +43 -0
- data/spec/change_exitstatus_spec.rb +57 -0
- data/spec/provide_env_vars_spec.rb +31 -0
- data/spec/replace_shell_commands_spec.rb +19 -4
- data/spec/stub_output_spec.rb +69 -0
- metadata +41 -6
- data/spec/fixtures/simple_script.sh +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89ba258c34cca0bd7077422b028d0d157c7d5d9c
|
4
|
+
data.tar.gz: 022db2cab38856e5e1314dcc72ba6f32e0906a0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad5581cba13751757c9275a3efb8b285c3a94b4f49a54bba02955839d8f9ac0b17a70638260b60c07d680593b7dbfe259e6a51f47d5dd37b53c9fd985e4def5e
|
7
|
+
data.tar.gz: d6b1f96a40508db1f34f0b21db09a872cf4c95aa232e497ddb411bf3e5dbf5e5ec0c35e1ce5f5198f785ee1195f9758680bdce15d177e494c9f82e5be41eda66
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Rspec::Shell::Expectations
|
2
2
|
[](https://travis-ci.org/matthijsgroen/rspec-shell-expectations)
|
3
|
+
[](http://badge.fury.io/rb/rspec-shell-expectations)
|
3
4
|
|
4
5
|
Run your shell script in a mocked environment to test its behaviour
|
5
6
|
using RSpec.
|
@@ -27,16 +28,17 @@ see specs in `spec/` folder:
|
|
27
28
|
### Running script through stubbed env:
|
28
29
|
|
29
30
|
```ruby
|
30
|
-
require 'English'
|
31
|
-
|
32
31
|
describe 'my shell script' do
|
33
32
|
include Rspec::Shell::Expectations
|
34
33
|
|
35
34
|
let(:stubbed_env) { create_stubbed_env }
|
36
35
|
|
37
36
|
it 'runs the script' do
|
38
|
-
stubbed_env.execute
|
39
|
-
|
37
|
+
stdout, stderr, status = stubbed_env.execute(
|
38
|
+
'my-shell-script.sh',
|
39
|
+
{ 'SOME_OPTIONAL' => 'env vars' }
|
40
|
+
)
|
41
|
+
expect(status.exitstatus).to eq 0
|
40
42
|
end
|
41
43
|
end
|
42
44
|
```
|
@@ -44,23 +46,69 @@ see specs in `spec/` folder:
|
|
44
46
|
### Stubbing commands:
|
45
47
|
|
46
48
|
```ruby
|
47
|
-
|
49
|
+
let(:stubbed_env) { create_stubbed_env }
|
50
|
+
before do
|
51
|
+
stubbed_env.stub_command('rake')
|
52
|
+
end
|
53
|
+
```
|
48
54
|
|
49
|
-
|
50
|
-
include Rspec::Shell::Expectations
|
55
|
+
### Changing exitstatus:
|
51
56
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
57
|
+
```ruby
|
58
|
+
let(:stubbed_env) { create_stubbed_env }
|
59
|
+
before do
|
60
|
+
stubbed_env.stub_command('rake').returns_exitstatus(5)
|
61
|
+
stubbed_env.stub_command('rake').with_args('spec').returns_exitstatus(3)
|
62
|
+
end
|
63
|
+
```
|
56
64
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
65
|
+
### Stubbing output:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
let(:stubbed_env) { create_stubbed_env }
|
69
|
+
let(:rake_stub) { stubbed_env.stub_command 'rake' }
|
70
|
+
before do
|
71
|
+
rake_stub.outputs('informative message', to: :stdout)
|
72
|
+
.outputs('error message', to: :stderr)
|
73
|
+
.outputs('log contents', to: 'logfile.log')
|
61
74
|
end
|
62
75
|
```
|
63
76
|
|
77
|
+
### Verifying called:
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
let(:stubbed_env) { create_stubbed_env }
|
81
|
+
let(:rake_stub) { stubbed_env.stub_command 'rake' }
|
82
|
+
it 'verifies called' do
|
83
|
+
stubbed_env.execute_script 'script.sh'
|
84
|
+
|
85
|
+
expect(rake_stub).to be_called
|
86
|
+
expect(rake_stub.with_args('spec')).to be_called
|
87
|
+
expect(rake_stub.with_args('features')).not_to be_called
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
91
|
+
### Verifying stdin:
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
let(:stubbed_env) { create_stubbed_env }
|
95
|
+
let(:cat_stub) { stubbed_env.stub_command 'cat' }
|
96
|
+
let(:mail_stub) { stubbed_env.stub_command 'mail' }
|
97
|
+
it 'verifies stdin' do
|
98
|
+
stubbed_env.execute_script 'script.sh'
|
99
|
+
expect(cat_stub.stdin).to eql 'hello'
|
100
|
+
expect(mail_stub.with_args('-s', 'hello').stdin).to eql 'world'
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
## More examples
|
105
|
+
|
106
|
+
see the *features* folder
|
107
|
+
|
108
|
+
## Supported ruby versions
|
109
|
+
|
110
|
+
Ruby 2+, no JRuby, due to issues with `Open3.capture3`
|
111
|
+
|
64
112
|
## Contributing
|
65
113
|
|
66
114
|
1. Fork it ( https://github.com/matthijsgroen/rspec-shell-expectations/fork )
|
data/Rakefile
CHANGED
@@ -8,4 +8,10 @@ end
|
|
8
8
|
require 'rubocop/rake_task'
|
9
9
|
RuboCop::RakeTask.new
|
10
10
|
|
11
|
-
|
11
|
+
require 'cucumber'
|
12
|
+
require 'cucumber/rake/task'
|
13
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
14
|
+
t.cucumber_opts = 'features --strict --format progress'
|
15
|
+
end
|
16
|
+
|
17
|
+
task default: [:rubocop, :features, :spec]
|
data/bin/stub
CHANGED
@@ -1 +1,41 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
require 'pathname'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
command = File.basename(__FILE__)
|
6
|
+
folder = File.dirname(__FILE__)
|
7
|
+
|
8
|
+
call_logs = Pathname.new(folder).join("#{command}_calls.yml")
|
9
|
+
call_logs.open('a') do |f|
|
10
|
+
f.puts '- args:'
|
11
|
+
ARGV.each { |arg| f.puts " - #{arg}" }
|
12
|
+
f.puts " stdin: #{$stdin.read}" unless STDIN.tty?
|
13
|
+
end
|
14
|
+
|
15
|
+
call_configurations = Pathname.new(folder).join("#{command}_stub.yml")
|
16
|
+
if call_configurations.exist?
|
17
|
+
config = YAML.load call_configurations.read
|
18
|
+
|
19
|
+
matching_calls = []
|
20
|
+
config.each do |call_config|
|
21
|
+
next unless (call_config[:args] - ARGV).empty?
|
22
|
+
matching_calls << {
|
23
|
+
config: call_config,
|
24
|
+
specific: call_config[:args].length
|
25
|
+
}
|
26
|
+
end
|
27
|
+
exit 0 if matching_calls.empty?
|
28
|
+
|
29
|
+
call_config = matching_calls.sort do |a, b|
|
30
|
+
b[:specific] <=> a[:specific]
|
31
|
+
end.first[:config]
|
32
|
+
(call_config[:outputs] || []).each do |data|
|
33
|
+
$stdout.print data[:content] if data[:target] == :stdout
|
34
|
+
$stderr.print data[:content] if data[:target] == :stderr
|
35
|
+
next unless data[:target].is_a? String
|
36
|
+
Pathname.new(data[:target]).open('w') do |f|
|
37
|
+
f.print data[:content]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
exit call_config[:statuscode] || 0
|
41
|
+
end
|
data/features/README.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Features of this application
|
2
|
+
|
3
|
+
The features of this applications are added in the form of userstories:
|
4
|
+
|
5
|
+
```gerkhin
|
6
|
+
In order to <value>
|
7
|
+
As a <role>
|
8
|
+
I want <thing>
|
9
|
+
```
|
10
|
+
|
11
|
+
These features are also in this directory structure this way:
|
12
|
+
|
13
|
+
```
|
14
|
+
features/<role>/<thing>.feature
|
15
|
+
```
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Feature:
|
2
|
+
In order to make sure the script reaches a certain point
|
3
|
+
As a developer
|
4
|
+
I want to assert a command call
|
5
|
+
|
6
|
+
Scenario: Assert command call
|
7
|
+
Given I have the shell script
|
8
|
+
"""
|
9
|
+
command_call
|
10
|
+
"""
|
11
|
+
And I have stubbed "command_call"
|
12
|
+
And I have stubbed "other_call"
|
13
|
+
When I run this script in a simulated environment
|
14
|
+
Then the command "command_call" is called
|
15
|
+
And the command "other_call" is not called
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Feature:
|
2
|
+
In order to check the input of a command
|
3
|
+
As a developer
|
4
|
+
I want to check the standard-in stream
|
5
|
+
|
6
|
+
Scenario: Assert standard-in
|
7
|
+
Given I have the shell script
|
8
|
+
"""
|
9
|
+
echo "text to stdin" | command_call
|
10
|
+
"""
|
11
|
+
And I have stubbed "command_call"
|
12
|
+
When I run this script in a simulated environment
|
13
|
+
Then the command "command_call" has received "text to stdin" from standard-in
|
@@ -0,0 +1,36 @@
|
|
1
|
+
Feature:
|
2
|
+
In order to manipulate code paths in scripts
|
3
|
+
As a developer
|
4
|
+
I want to change the exitstatus of a command
|
5
|
+
|
6
|
+
Scenario: Change exitstatus code unconditional
|
7
|
+
Given I have the shell script
|
8
|
+
"""
|
9
|
+
#!/bin/bash
|
10
|
+
command_with_status
|
11
|
+
"""
|
12
|
+
And I have stubbed "command_with_status"
|
13
|
+
And the stubbed command returns exitstatus 5
|
14
|
+
When I run this script in a simulated environment
|
15
|
+
Then the exitstatus will be 5
|
16
|
+
|
17
|
+
Scenario: Change exitstatus code when argument matches
|
18
|
+
Given I have the shell script
|
19
|
+
"""
|
20
|
+
#!/bin/bash
|
21
|
+
command_with_status --flag
|
22
|
+
if [ $? -neq 4 ]; then
|
23
|
+
exit 3
|
24
|
+
fi
|
25
|
+
command_with_status --foo
|
26
|
+
"""
|
27
|
+
And I have stubbed "command_with_status" with args:
|
28
|
+
| args |
|
29
|
+
| --flag |
|
30
|
+
And the stubbed command returns exitstatus 4
|
31
|
+
And I have stubbed "command_with_status" with args:
|
32
|
+
| args |
|
33
|
+
| --foo |
|
34
|
+
And the stubbed command returns exitstatus 5
|
35
|
+
When I run this script in a simulated environment
|
36
|
+
Then the exitstatus will be 5
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Feature:
|
2
|
+
In order to simulate an environment better
|
3
|
+
As a developer
|
4
|
+
I want to provide environment variables with execution
|
5
|
+
|
6
|
+
Scenario: Provide environment variables
|
7
|
+
Given I have the shell script
|
8
|
+
"""
|
9
|
+
echo $MESSAGE | command_call
|
10
|
+
other_command $CREDENTIAL
|
11
|
+
"""
|
12
|
+
And I have stubbed "command_call"
|
13
|
+
And I have stubbed "other_command"
|
14
|
+
When I run this script in a simulated environment with env:
|
15
|
+
| name | value |
|
16
|
+
| MESSAGE | message contents |
|
17
|
+
| CREDENTIAL | supa-sekret |
|
18
|
+
Then the command "command_call" has received "message contents" from standard-in
|
19
|
+
And the command "other_command" is called with "supa-sekret"
|
20
|
+
|
@@ -0,0 +1,85 @@
|
|
1
|
+
Given(/^I have the shell script$/) do |script_contents|
|
2
|
+
@script = workfolder.join('script.sh')
|
3
|
+
@script.open('w') do |w|
|
4
|
+
w.puts script_contents
|
5
|
+
end
|
6
|
+
@script.chmod 0777
|
7
|
+
end
|
8
|
+
|
9
|
+
Given(/^I have stubbed "(.*?)"$/) do |command|
|
10
|
+
@stubbed_command = simulated_environment.stub_command command
|
11
|
+
end
|
12
|
+
|
13
|
+
Given(/^I have stubbed "(.*?)" with args:$/) do |command, table|
|
14
|
+
# table is a Cucumber::Ast::Table
|
15
|
+
args = table.hashes.map { |d| d['args'] }
|
16
|
+
@stubbed_command = simulated_environment.stub_command(command)
|
17
|
+
.with_args(*args)
|
18
|
+
end
|
19
|
+
|
20
|
+
sc = /^the stubbed command/
|
21
|
+
Given(/#{sc} returns exitstatus (\d+)$/) do |statuscode|
|
22
|
+
@stubbed_command.returns_exitstatus(statuscode.to_i)
|
23
|
+
end
|
24
|
+
|
25
|
+
Given(/#{sc} outputs "(.*?)" to standard\-out$/) do |output|
|
26
|
+
@stubbed_command.outputs(output, to: :stdout)
|
27
|
+
end
|
28
|
+
|
29
|
+
Given(/#{sc} outputs "(.*?)" to standard\-error$/) do |output|
|
30
|
+
@stubbed_command.outputs(output, to: :stderr)
|
31
|
+
end
|
32
|
+
|
33
|
+
Given(/#{sc} outputs "(.*?)" to "(.*?)"$/) do |output, target|
|
34
|
+
@stubbed_command.outputs(output, to: target)
|
35
|
+
files_to_delete.push Pathname.new(target)
|
36
|
+
end
|
37
|
+
|
38
|
+
When(/^I run this script in a simulated environment$/) do
|
39
|
+
@stdout, @stderr, @status = simulated_environment.execute "#{@script} 2>&1"
|
40
|
+
end
|
41
|
+
|
42
|
+
When(/^I run this script in a simulated environment with env:$/) do |table|
|
43
|
+
env = Hash[table.hashes.map do |hash|
|
44
|
+
[hash[:name], hash[:value]]
|
45
|
+
end]
|
46
|
+
|
47
|
+
@stdout, @stderr, @status = simulated_environment.execute(
|
48
|
+
@script,
|
49
|
+
env
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
Then(/^the exitstatus will not be (\d+)$/) do |statuscode|
|
54
|
+
expect(@status.exitstatus).not_to eql statuscode.to_i
|
55
|
+
end
|
56
|
+
|
57
|
+
Then(/^the exitstatus will be (\d+)$/) do |statuscode|
|
58
|
+
expect(@status.exitstatus).to eql statuscode.to_i
|
59
|
+
end
|
60
|
+
|
61
|
+
c = /^(the command ".*")/
|
62
|
+
Transform(/^the command "(.*)"/) do |command|
|
63
|
+
simulated_environment.stub_command command
|
64
|
+
end
|
65
|
+
|
66
|
+
Then(/#{c} is called$/) do |command|
|
67
|
+
expect(command).to be_called
|
68
|
+
end
|
69
|
+
|
70
|
+
Then(/#{c} is called with "(.*?)"$/) do |command, argument|
|
71
|
+
expect(command.with_args(argument)).to be_called
|
72
|
+
end
|
73
|
+
|
74
|
+
Then(/#{c} is not called$/) do |command|
|
75
|
+
expect(command).not_to be_called
|
76
|
+
end
|
77
|
+
|
78
|
+
Then(/#{c} has received "(.*?)" from standard\-in$/) do |command, contents|
|
79
|
+
expect(command.stdin).to eql contents
|
80
|
+
end
|
81
|
+
|
82
|
+
Then(/^the file "(.*?)" contains "(.*?)"$/) do |filename, contents|
|
83
|
+
files_to_delete.push Pathname.new(filename)
|
84
|
+
expect(Pathname.new(filename).read).to eql contents
|
85
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Feature:
|
2
|
+
In order to run scripts without triggering real commands
|
3
|
+
As a developer
|
4
|
+
I want to stub commands
|
5
|
+
|
6
|
+
Scenario: Run a script without stub
|
7
|
+
Given I have the shell script
|
8
|
+
"""
|
9
|
+
command_that_does_not_exist
|
10
|
+
"""
|
11
|
+
When I run this script in a simulated environment
|
12
|
+
Then the exitstatus will not be 0
|
13
|
+
|
14
|
+
Scenario: Run a script with stub
|
15
|
+
Given I have the shell script
|
16
|
+
"""
|
17
|
+
command_that_does_not_exist
|
18
|
+
"""
|
19
|
+
And I have stubbed "command_that_does_not_exist"
|
20
|
+
When I run this script in a simulated environment
|
21
|
+
Then the exitstatus will be 0
|
@@ -0,0 +1,37 @@
|
|
1
|
+
Feature:
|
2
|
+
In order to simulate command behaviour
|
3
|
+
As a developer
|
4
|
+
I want to stub the output of a command
|
5
|
+
|
6
|
+
Scenario: Stub standard-out
|
7
|
+
Given I have the shell script
|
8
|
+
"""
|
9
|
+
command_call 1> file.txt
|
10
|
+
"""
|
11
|
+
And I have stubbed "command_call"
|
12
|
+
And the stubbed command outputs "hello there" to standard-out
|
13
|
+
When I run this script in a simulated environment
|
14
|
+
Then the file "file.txt" contains "hello there"
|
15
|
+
|
16
|
+
Scenario: Stub standard-error
|
17
|
+
Given I have the shell script
|
18
|
+
"""
|
19
|
+
command_call 2> file.txt
|
20
|
+
"""
|
21
|
+
And I have stubbed "command_call"
|
22
|
+
And the stubbed command outputs "hello there" to standard-error
|
23
|
+
When I run this script in a simulated environment
|
24
|
+
Then the file "file.txt" contains "hello there"
|
25
|
+
|
26
|
+
Scenario: Stub to file
|
27
|
+
Given I have the shell script
|
28
|
+
"""
|
29
|
+
command_call
|
30
|
+
"""
|
31
|
+
And I have stubbed "command_call"
|
32
|
+
And the stubbed command outputs "hello there" to "file.txt"
|
33
|
+
And the stubbed command outputs "there" to "other_file.txt"
|
34
|
+
When I run this script in a simulated environment
|
35
|
+
Then the file "file.txt" contains "hello there"
|
36
|
+
And the file "other_file.txt" contains "there"
|
37
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Rspec
|
4
|
+
module Shell
|
5
|
+
module Expectations
|
6
|
+
# Configuration of a stubbed command
|
7
|
+
class CallConfiguration
|
8
|
+
def initialize(config_path)
|
9
|
+
@config_path = config_path
|
10
|
+
@configuration = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def set_exitcode(statuscode, args = [])
|
14
|
+
@configuration[args] ||= {}
|
15
|
+
@configuration[args][:statuscode] = statuscode
|
16
|
+
end
|
17
|
+
|
18
|
+
def set_output(content, target, args = [])
|
19
|
+
@configuration[args] ||= {}
|
20
|
+
@configuration[args][:outputs] ||= []
|
21
|
+
@configuration[args][:outputs] << { target: target, content: content }
|
22
|
+
end
|
23
|
+
|
24
|
+
def write
|
25
|
+
structure = []
|
26
|
+
@configuration.each do |args, results|
|
27
|
+
call = {
|
28
|
+
args: args
|
29
|
+
}.merge results
|
30
|
+
structure << call
|
31
|
+
end
|
32
|
+
|
33
|
+
@config_path.open('w') do |f|
|
34
|
+
f.puts structure.to_yaml
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Shell
|
3
|
+
module Expectations
|
4
|
+
# Log of calls to a command
|
5
|
+
class CallLog
|
6
|
+
def initialize(call_log_path)
|
7
|
+
@call_log_path = call_log_path
|
8
|
+
end
|
9
|
+
|
10
|
+
def exist?
|
11
|
+
@call_log_path.exist?
|
12
|
+
end
|
13
|
+
|
14
|
+
def called_with_args?(*args)
|
15
|
+
return true if find_call(*args)
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
def stdin_for_args(*args)
|
20
|
+
call = find_call(*args)
|
21
|
+
return call['stdin'] if call
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def find_call(*args)
|
28
|
+
call_log.each do |call|
|
29
|
+
call_args = call['args'] || []
|
30
|
+
return call if (args - call_args).empty?
|
31
|
+
end
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def call_log
|
36
|
+
YAML.load_file @call_log_path
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Shell
|
3
|
+
module Expectations
|
4
|
+
# A specific call with arguments on a StubbedCommand
|
5
|
+
class StubbedCall
|
6
|
+
def initialize(config, call_log, args)
|
7
|
+
@config, @call_log, @args = config, call_log, args
|
8
|
+
end
|
9
|
+
|
10
|
+
def returns_exitstatus(statuscode)
|
11
|
+
@config.set_exitcode(statuscode, @args)
|
12
|
+
@config.write
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def outputs(content, to: :stdout)
|
17
|
+
@config.set_output(content, to, @args)
|
18
|
+
@config.write
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def stdin
|
23
|
+
return nil unless @call_log.exist?
|
24
|
+
@call_log.stdin_for_args(*@args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def called?
|
28
|
+
return false unless @call_log.exist?
|
29
|
+
@call_log.called_with_args?(*@args)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Shell
|
3
|
+
module Expectations
|
4
|
+
# Command that produces specific output
|
5
|
+
# and monitors input
|
6
|
+
class StubbedCommand
|
7
|
+
def initialize(command, dir)
|
8
|
+
@dir, @command = dir, command
|
9
|
+
FileUtils.cp('bin/stub', File.join(dir, command))
|
10
|
+
@call_configuration = CallConfiguration.new(
|
11
|
+
Pathname.new(dir).join("#{command}_stub.yml")
|
12
|
+
)
|
13
|
+
@call_log = CallLog.new(
|
14
|
+
Pathname.new(dir).join("#{command}_calls.yml")
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def with_args(*args)
|
19
|
+
StubbedCall.new(@call_configuration, @call_log, args)
|
20
|
+
end
|
21
|
+
|
22
|
+
def called?
|
23
|
+
with_args.called?
|
24
|
+
end
|
25
|
+
|
26
|
+
def called_with_args?(*args)
|
27
|
+
with_args.called_with_args?(*args)
|
28
|
+
end
|
29
|
+
|
30
|
+
def returns_exitstatus(statuscode)
|
31
|
+
with_args.returns_exitstatus(statuscode)
|
32
|
+
end
|
33
|
+
|
34
|
+
def stdin
|
35
|
+
with_args.stdin
|
36
|
+
end
|
37
|
+
|
38
|
+
def outputs(contents, to: :stdout)
|
39
|
+
with_args.outputs(contents, to: to)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'tmpdir'
|
2
|
+
require 'English'
|
3
|
+
require 'open3'
|
2
4
|
|
3
5
|
module Rspec
|
4
6
|
module Shell
|
@@ -17,16 +19,16 @@ module Rspec
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def stub_command(command)
|
20
|
-
|
22
|
+
StubbedCommand.new command, @dir
|
21
23
|
end
|
22
24
|
|
23
|
-
def execute(command)
|
24
|
-
|
25
|
+
def execute(command, env_vars = {})
|
26
|
+
Open3.capture3(env_vars, "#{env} #{command}")
|
25
27
|
end
|
26
28
|
|
27
29
|
private
|
28
30
|
|
29
|
-
def
|
31
|
+
def env
|
30
32
|
"PATH=#{@dir}:$PATH"
|
31
33
|
end
|
32
34
|
end
|
@@ -1,2 +1,6 @@
|
|
1
1
|
require 'rspec/shell/expectations/version'
|
2
|
+
require 'rspec/shell/expectations/stubbed_command'
|
3
|
+
require 'rspec/shell/expectations/stubbed_call'
|
4
|
+
require 'rspec/shell/expectations/call_configuration'
|
5
|
+
require 'rspec/shell/expectations/call_log'
|
2
6
|
require 'rspec/shell/expectations/stubbed_env'
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'rspec/shell/expectations'
|
3
|
+
|
4
|
+
describe 'Assert called' do
|
5
|
+
include Rspec::Shell::Expectations
|
6
|
+
let(:stubbed_env) { create_stubbed_env }
|
7
|
+
let!(:command1_stub) { stubbed_env.stub_command('command1') }
|
8
|
+
|
9
|
+
let(:script) do
|
10
|
+
<<-SCRIPT
|
11
|
+
command1 "foo bar"
|
12
|
+
SCRIPT
|
13
|
+
end
|
14
|
+
let(:script_path) { Pathname.new '/tmp/test_script.sh' }
|
15
|
+
|
16
|
+
before do
|
17
|
+
script_path.open('w') { |f| f.puts script }
|
18
|
+
script_path.chmod 0777
|
19
|
+
end
|
20
|
+
|
21
|
+
after do
|
22
|
+
script_path.delete
|
23
|
+
end
|
24
|
+
|
25
|
+
subject do
|
26
|
+
stubbed_env.execute script_path.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'assert called' do
|
30
|
+
it 'returns called status' do
|
31
|
+
subject
|
32
|
+
expect(command1_stub).to be_called
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'assert with args' do
|
36
|
+
it 'returns called status' do
|
37
|
+
subject
|
38
|
+
expect(command1_stub.with_args('foo bar')).to be_called
|
39
|
+
expect(command1_stub.with_args('foo')).not_to be_called
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'rspec/shell/expectations'
|
3
|
+
|
4
|
+
describe 'Assert stdin' do
|
5
|
+
include Rspec::Shell::Expectations
|
6
|
+
let(:stubbed_env) { create_stubbed_env }
|
7
|
+
let!(:command1_stub) { stubbed_env.stub_command('command1') }
|
8
|
+
|
9
|
+
let(:script) do
|
10
|
+
<<-SCRIPT
|
11
|
+
echo "foo bar" | command1
|
12
|
+
echo "baz" | command1 'hello'
|
13
|
+
SCRIPT
|
14
|
+
end
|
15
|
+
let(:script_path) { Pathname.new '/tmp/test_script.sh' }
|
16
|
+
|
17
|
+
before do
|
18
|
+
script_path.open('w') { |f| f.puts script }
|
19
|
+
script_path.chmod 0777
|
20
|
+
end
|
21
|
+
|
22
|
+
after do
|
23
|
+
script_path.delete
|
24
|
+
end
|
25
|
+
|
26
|
+
subject do
|
27
|
+
stubbed_env.execute script_path.to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#stdin' do
|
31
|
+
it 'returns the stdin' do
|
32
|
+
subject
|
33
|
+
expect(command1_stub.stdin).to eql 'foo bar'
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'with arguments' do
|
37
|
+
it 'returns the stdin' do
|
38
|
+
subject
|
39
|
+
expect(command1_stub.with_args('hello').stdin).to eql 'baz'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'rspec/shell/expectations'
|
3
|
+
|
4
|
+
describe 'Change exitstatus' do
|
5
|
+
include Rspec::Shell::Expectations
|
6
|
+
let(:stubbed_env) { create_stubbed_env }
|
7
|
+
let!(:command1_stub) { stubbed_env.stub_command('command1') }
|
8
|
+
let(:script) do
|
9
|
+
<<-SCRIPT
|
10
|
+
command1 "foo bar"
|
11
|
+
SCRIPT
|
12
|
+
end
|
13
|
+
let(:script_path) { Pathname.new '/tmp/test_script.sh' }
|
14
|
+
|
15
|
+
before do
|
16
|
+
script_path.open('w') { |f| f.puts script }
|
17
|
+
script_path.chmod 0777
|
18
|
+
end
|
19
|
+
|
20
|
+
after do
|
21
|
+
script_path.delete
|
22
|
+
end
|
23
|
+
|
24
|
+
subject do
|
25
|
+
stubbed_env.execute script_path.to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'default exitstatus' do
|
29
|
+
it 'is 0' do
|
30
|
+
_o, _e, s = subject
|
31
|
+
expect(s.exitstatus).to eq 0
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'changing exitstatus' do
|
36
|
+
before do
|
37
|
+
command1_stub.returns_exitstatus(4)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns the stubbed exitstatus' do
|
41
|
+
_o, _e, s = subject
|
42
|
+
expect(s.exitstatus).to eq 4
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'with specific args only' do
|
46
|
+
before do
|
47
|
+
command1_stub.with_args('foo bar').returns_exitstatus(2)
|
48
|
+
command1_stub.with_args('bar').returns_exitstatus(6)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'returns the stubbed exitstatus' do
|
52
|
+
_o, _e, s = subject
|
53
|
+
expect(s.exitstatus).to eq 2
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'rspec/shell/expectations'
|
3
|
+
|
4
|
+
describe 'Provide environment vars' do
|
5
|
+
include Rspec::Shell::Expectations
|
6
|
+
let(:script) do
|
7
|
+
<<-SCRIPT
|
8
|
+
echo $SOME_ENV_VAR
|
9
|
+
SCRIPT
|
10
|
+
end
|
11
|
+
let(:script_path) { Pathname.new '/tmp/test_script.sh' }
|
12
|
+
|
13
|
+
before do
|
14
|
+
script_path.open('w') { |f| f.puts script }
|
15
|
+
script_path.chmod 0777
|
16
|
+
end
|
17
|
+
|
18
|
+
after do
|
19
|
+
script_path.delete
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:stubbed_env) { create_stubbed_env }
|
23
|
+
|
24
|
+
it 'exits with an error' do
|
25
|
+
o, _e, _s = stubbed_env.execute(
|
26
|
+
script_path,
|
27
|
+
'SOME_ENV_VAR' => 'SekretCredential'
|
28
|
+
)
|
29
|
+
expect(o).to eql "SekretCredential\n"
|
30
|
+
end
|
31
|
+
end
|
@@ -3,10 +3,25 @@ require 'rspec/shell/expectations'
|
|
3
3
|
|
4
4
|
describe 'Replace shell commands' do
|
5
5
|
include Rspec::Shell::Expectations
|
6
|
+
let(:script) do
|
7
|
+
<<-SCRIPT
|
8
|
+
command1 "foo bar"
|
9
|
+
SCRIPT
|
10
|
+
end
|
11
|
+
let(:script_path) { Pathname.new '/tmp/test_script.sh' }
|
12
|
+
|
13
|
+
before do
|
14
|
+
script_path.open('w') { |f| f.puts script }
|
15
|
+
script_path.chmod 0777
|
16
|
+
end
|
17
|
+
|
18
|
+
after do
|
19
|
+
script_path.delete
|
20
|
+
end
|
6
21
|
|
7
22
|
describe 'running a file with non-existing commands' do
|
8
23
|
it 'exits with an error' do
|
9
|
-
|
24
|
+
`#{script_path} 2>&1`
|
10
25
|
expect($CHILD_STATUS.exitstatus).not_to eq 0
|
11
26
|
end
|
12
27
|
|
@@ -14,7 +29,7 @@ describe 'Replace shell commands' do
|
|
14
29
|
let(:stubbed_env) { create_stubbed_env }
|
15
30
|
|
16
31
|
it 'exits with an error' do
|
17
|
-
stubbed_env.execute
|
32
|
+
stubbed_env.execute "#{script_path} 2>&1"
|
18
33
|
expect($CHILD_STATUS.exitstatus).not_to eq 0
|
19
34
|
end
|
20
35
|
|
@@ -24,8 +39,8 @@ describe 'Replace shell commands' do
|
|
24
39
|
end
|
25
40
|
|
26
41
|
it 'exits with status code 0' do
|
27
|
-
stubbed_env.execute
|
28
|
-
expect(
|
42
|
+
_o, _e, s = stubbed_env.execute "#{script_path} 2>&1"
|
43
|
+
expect(s.exitstatus).to eq 0
|
29
44
|
end
|
30
45
|
end
|
31
46
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'rspec/shell/expectations'
|
3
|
+
|
4
|
+
describe 'Stub command output' do
|
5
|
+
include Rspec::Shell::Expectations
|
6
|
+
let(:stubbed_env) { create_stubbed_env }
|
7
|
+
let!(:command1_stub) { stubbed_env.stub_command('command1') }
|
8
|
+
|
9
|
+
let(:script) do
|
10
|
+
<<-SCRIPT
|
11
|
+
command1
|
12
|
+
SCRIPT
|
13
|
+
end
|
14
|
+
let(:script_path) { Pathname.new '/tmp/test_script.sh' }
|
15
|
+
|
16
|
+
before do
|
17
|
+
script_path.open('w') { |f| f.puts script }
|
18
|
+
script_path.chmod 0777
|
19
|
+
end
|
20
|
+
|
21
|
+
after do
|
22
|
+
script_path.delete
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'stubbing standard-out' do
|
26
|
+
subject do
|
27
|
+
stubbed_env.execute "#{script_path} 2>/dev/null"
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'changes standard-out' do
|
31
|
+
command1_stub.outputs('hello', to: :stdout)
|
32
|
+
o, e, _s = subject
|
33
|
+
expect(o).to eql 'hello'
|
34
|
+
expect(e).to be_empty
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'stubbing standard-err' do
|
39
|
+
subject do
|
40
|
+
stubbed_env.execute "#{script_path} 1>/dev/null"
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'changes standard-out' do
|
44
|
+
command1_stub.outputs('world', to: :stderr)
|
45
|
+
o, e, _s = subject
|
46
|
+
expect(e).to eql 'world'
|
47
|
+
expect(o).to be_empty
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'stubbing contents to file' do
|
52
|
+
subject do
|
53
|
+
stubbed_env.execute "#{script_path}"
|
54
|
+
end
|
55
|
+
let(:filename) { 'test-log.nice' }
|
56
|
+
after do
|
57
|
+
f = Pathname.new(filename)
|
58
|
+
f.delete if f.exist?
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'write data to a file' do
|
62
|
+
command1_stub.outputs('world', to: filename)
|
63
|
+
o, e, _s = subject
|
64
|
+
expect(e).to be_empty
|
65
|
+
expect(o).to be_empty
|
66
|
+
expect(Pathname.new(filename).read).to eql 'world'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-shell-expectations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 1.0.0.pre.beta
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthijs Groen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -49,6 +49,7 @@ extensions: []
|
|
49
49
|
extra_rdoc_files: []
|
50
50
|
files:
|
51
51
|
- ".gitignore"
|
52
|
+
- ".rspec"
|
52
53
|
- ".ruby-version"
|
53
54
|
- ".travis.yml"
|
54
55
|
- Gemfile
|
@@ -56,12 +57,31 @@ files:
|
|
56
57
|
- README.md
|
57
58
|
- Rakefile
|
58
59
|
- bin/stub
|
60
|
+
- features/README.md
|
61
|
+
- features/developer/assert_calls.feature
|
62
|
+
- features/developer/assert_stdin.feature
|
63
|
+
- features/developer/change_exitstatus.feature
|
64
|
+
- features/developer/provide-env-vars.feature
|
65
|
+
- features/developer/step_definitions/general_steps.rb
|
66
|
+
- features/developer/stub_commands.feature
|
67
|
+
- features/developer/stub_output.feature
|
68
|
+
- features/developer/support/simulated_env.rb
|
69
|
+
- features/developer/support/tempfiles.rb
|
70
|
+
- features/developer/support/workfolder.rb
|
59
71
|
- lib/rspec/shell/expectations.rb
|
72
|
+
- lib/rspec/shell/expectations/call_configuration.rb
|
73
|
+
- lib/rspec/shell/expectations/call_log.rb
|
74
|
+
- lib/rspec/shell/expectations/stubbed_call.rb
|
75
|
+
- lib/rspec/shell/expectations/stubbed_command.rb
|
60
76
|
- lib/rspec/shell/expectations/stubbed_env.rb
|
61
77
|
- lib/rspec/shell/expectations/version.rb
|
62
78
|
- rspec-shell-expectations.gemspec
|
63
|
-
- spec/
|
79
|
+
- spec/assert_called_spec.rb
|
80
|
+
- spec/assert_stdin_spec.rb
|
81
|
+
- spec/change_exitstatus_spec.rb
|
82
|
+
- spec/provide_env_vars_spec.rb
|
64
83
|
- spec/replace_shell_commands_spec.rb
|
84
|
+
- spec/stub_output_spec.rb
|
65
85
|
homepage: ''
|
66
86
|
licenses:
|
67
87
|
- MIT
|
@@ -77,9 +97,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
77
97
|
version: '0'
|
78
98
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
99
|
requirements:
|
80
|
-
- - "
|
100
|
+
- - ">"
|
81
101
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
102
|
+
version: 1.3.1
|
83
103
|
requirements: []
|
84
104
|
rubyforge_project:
|
85
105
|
rubygems_version: 2.2.2
|
@@ -87,5 +107,20 @@ signing_key:
|
|
87
107
|
specification_version: 4
|
88
108
|
summary: Fake execution environments to TDD shell scripts
|
89
109
|
test_files:
|
90
|
-
-
|
110
|
+
- features/README.md
|
111
|
+
- features/developer/assert_calls.feature
|
112
|
+
- features/developer/assert_stdin.feature
|
113
|
+
- features/developer/change_exitstatus.feature
|
114
|
+
- features/developer/provide-env-vars.feature
|
115
|
+
- features/developer/step_definitions/general_steps.rb
|
116
|
+
- features/developer/stub_commands.feature
|
117
|
+
- features/developer/stub_output.feature
|
118
|
+
- features/developer/support/simulated_env.rb
|
119
|
+
- features/developer/support/tempfiles.rb
|
120
|
+
- features/developer/support/workfolder.rb
|
121
|
+
- spec/assert_called_spec.rb
|
122
|
+
- spec/assert_stdin_spec.rb
|
123
|
+
- spec/change_exitstatus_spec.rb
|
124
|
+
- spec/provide_env_vars_spec.rb
|
91
125
|
- spec/replace_shell_commands_spec.rb
|
126
|
+
- spec/stub_output_spec.rb
|
@@ -1 +0,0 @@
|
|
1
|
-
command1
|