rspec-shell-expectations 0.0.1 → 1.0.0.pre.beta
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://travis-ci.org/matthijsgroen/rspec-shell-expectations.png?branch=master)](https://travis-ci.org/matthijsgroen/rspec-shell-expectations)
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/rspec-shell-expectations.svg)](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
|