scmd 3.0.0 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +65 -0
- data/lib/scmd.rb +40 -2
- data/lib/scmd/command.rb +4 -4
- data/lib/scmd/command_spy.rb +121 -0
- data/lib/scmd/stored_commands.rb +78 -0
- data/lib/scmd/version.rb +1 -1
- data/test/helper.rb +2 -0
- data/test/support/factory.rb +6 -0
- data/test/unit/command_spy_tests.rb +228 -0
- data/test/unit/command_tests.rb +3 -3
- data/test/unit/scmd_tests.rb +85 -2
- data/test/unit/stored_commands_tests.rb +146 -0
- metadata +21 -37
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
data.tar.gz: 41ab93becdd3b11aa43cf2b7465bb06740176732
|
4
|
+
metadata.gz: d8df11392ad93610a721cdfb7c85aa4a2bc3b0a2
|
5
|
+
SHA512:
|
6
|
+
data.tar.gz: c069015a2af2701ac855f12384c2941b39ede49b7e89b9157a83be6214b83034106405a1ad0c52fc016007b65a4d3ced67cb118008a6d7c0fa5cbf56fa3eb0ed
|
7
|
+
metadata.gz: cce48d3004f825e93f42b5e1a397ed5c7dbaff2a4fddcfce0e8acba3586b56286ba9a3dd7952136b73aacdb2eb51cd9ebf3435d35719dfc2cc0384a87193fec6
|
data/README.md
CHANGED
@@ -121,6 +121,71 @@ reader.gets # => "test\n"
|
|
121
121
|
|
122
122
|
For all the possible options see [posix-spawn](https://github.com/rtomayko/posix-spawn#status).
|
123
123
|
|
124
|
+
## Testing
|
125
|
+
|
126
|
+
Scmd comes with some testing utilities built in. Specifically this includes a command spy and a "test mode" API on the main `Scmd` namespace.
|
127
|
+
|
128
|
+
### Command Spy
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
require 'scmd/command_spy'
|
132
|
+
spy = Scmd::CommandSpy.new(cmd_str)
|
133
|
+
spy.exitstatus = 1
|
134
|
+
spy.stdout = 'some test output'
|
135
|
+
Assert.stub(Scmd, :new).with(cmd_str){ spy }
|
136
|
+
|
137
|
+
cmd = Scmd.new(cmd_str) # => spy
|
138
|
+
cmd.run('some input')
|
139
|
+
|
140
|
+
cmd.run_called? # => true
|
141
|
+
cmd.run_calls.size # => 1
|
142
|
+
cmd.run_calls.first.input # => 'some input'
|
143
|
+
```
|
144
|
+
|
145
|
+
The spy is useful for stubbing out system commands that you don't want to call or aren't safe to call in the test suite. It responds to the same API that commands do but doesn't run any system commands.
|
146
|
+
|
147
|
+
### "Test Mode" API
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
Scmd.add_command(cmd_str){ |cmd| cmd.stdout = 'some output' } # => raises NoMethodError
|
151
|
+
|
152
|
+
ENV['SCMD_TEST_MODE'] = '1'
|
153
|
+
Scmd.add_command(cmd_str){ |cmd| cmd.stdout = 'some output' }
|
154
|
+
Scmd.add_command(cmd_str).with({:env => { :SOME_ENV_VAR => '1' }}) do |cmd|
|
155
|
+
cmd.stdout = 'some other output'
|
156
|
+
end
|
157
|
+
Scmd.commands.empty? # => false
|
158
|
+
|
159
|
+
cmd = Scmd.new(cmd_str)
|
160
|
+
cmd.class # => Scmd::CommandSpy
|
161
|
+
cmd.stdout # => 'some output'
|
162
|
+
cmd.run('some input')
|
163
|
+
Scmd.calls.size # => 1
|
164
|
+
Scmd.calls.last.class # => Scmd::Call
|
165
|
+
Scmd.calls.last.cmd_str # => cmd_str
|
166
|
+
Scmd.calls.last.input # => 'some input'
|
167
|
+
Scmd.calls.last.cmd.class # => Scmd::CommandSpy
|
168
|
+
|
169
|
+
cmd = Scmd.new(cmd_str, {:env => { 'SOME_ENV_VAR' => '1' }})
|
170
|
+
cmd.class # => Scmd::CommandSpy
|
171
|
+
cmd.stdout # => 'some other output'
|
172
|
+
cmd.run('some input')
|
173
|
+
Scmd.calls.size # => 2
|
174
|
+
Scmd.calls.last.class # => Scmd::Call
|
175
|
+
Scmd.calls.last.cmd_str # => cmd_str
|
176
|
+
Scmd.calls.last.input # => 'some input'
|
177
|
+
Scmd.calls.last.cmd.class # => Scmd::CommandSpy
|
178
|
+
Scmd.calls.last.cmd.env # => { 'SOME_ENV_VAR' => '1' }
|
179
|
+
|
180
|
+
Scmd.reset
|
181
|
+
Scmd.commands.empty? # => true
|
182
|
+
Scmd.calls.empty? # => true
|
183
|
+
```
|
184
|
+
|
185
|
+
Use these singleton methods on the `Scmd` namespace to add specific command spies in specific contexts and to track command calls (runs, starts). Use `reset` to reset the state of things.
|
186
|
+
|
187
|
+
**Note:** these methods are only available when test mode is enabled (when the `SCMD_TEST_MODE` env var has a non-falsey value). Otherwise these methods will raise `NoMethodError`.
|
188
|
+
|
124
189
|
## Installation
|
125
190
|
|
126
191
|
Add this line to your application's Gemfile:
|
data/lib/scmd.rb
CHANGED
@@ -3,8 +3,46 @@ require 'scmd/command'
|
|
3
3
|
|
4
4
|
module Scmd
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
# Scmd can be run in "test mode". This means that command spies will be used
|
7
|
+
# in place of "live" commands, each time a command is run or started will be
|
8
|
+
# logged in a collection and option-specific spies can be added and used to
|
9
|
+
# "stub" spies with specific attributes in specific contexts.
|
10
|
+
|
11
|
+
def self.new(*args)
|
12
|
+
if !ENV['SCMD_TEST_MODE']
|
13
|
+
Command.new(*args)
|
14
|
+
else
|
15
|
+
self.commands.get(*args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.commands
|
20
|
+
raise NoMethodError if !ENV['SCMD_TEST_MODE']
|
21
|
+
@commands ||= begin
|
22
|
+
require 'scmd/stored_commands'
|
23
|
+
StoredCommands.new
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.calls
|
28
|
+
raise NoMethodError if !ENV['SCMD_TEST_MODE']
|
29
|
+
@calls ||= []
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.reset
|
33
|
+
raise NoMethodError if !ENV['SCMD_TEST_MODE']
|
34
|
+
self.calls.clear
|
35
|
+
self.commands.remove_all
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.add_command(cmd_str, &block)
|
39
|
+
self.commands.add(cmd_str, &block)
|
40
|
+
end
|
41
|
+
|
42
|
+
class Call < Struct.new(:cmd_str, :input, :cmd)
|
43
|
+
def initialize(cmd_spy, input)
|
44
|
+
super(cmd_spy.cmd_str, input, cmd_spy)
|
45
|
+
end
|
8
46
|
end
|
9
47
|
|
10
48
|
TimeoutError = Class.new(::RuntimeError)
|
data/lib/scmd/command.rb
CHANGED
@@ -88,10 +88,10 @@ module Scmd
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
|
-
def kill(
|
91
|
+
def kill(signal = nil)
|
92
92
|
return if !running?
|
93
93
|
|
94
|
-
send_kill(
|
94
|
+
send_kill(signal)
|
95
95
|
wait # indefinitely until cmd is killed
|
96
96
|
end
|
97
97
|
|
@@ -148,8 +148,8 @@ module Scmd
|
|
148
148
|
send_signal 'TERM'
|
149
149
|
end
|
150
150
|
|
151
|
-
def send_kill(
|
152
|
-
send_signal(
|
151
|
+
def send_kill(signal = nil)
|
152
|
+
send_signal(signal || 'KILL')
|
153
153
|
end
|
154
154
|
|
155
155
|
def send_signal(sig)
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'scmd'
|
2
|
+
|
3
|
+
module Scmd
|
4
|
+
|
5
|
+
class CommandSpy
|
6
|
+
|
7
|
+
attr_reader :cmd_str, :env, :options
|
8
|
+
attr_reader :run_calls, :run_bang_calls, :start_calls
|
9
|
+
attr_reader :wait_calls, :stop_calls, :kill_calls
|
10
|
+
attr_accessor :pid, :exitstatus, :stdout, :stderr
|
11
|
+
|
12
|
+
def initialize(cmd_str, opts = nil)
|
13
|
+
opts ||= {}
|
14
|
+
@cmd_str = cmd_str
|
15
|
+
@env = opts[:env]
|
16
|
+
@options = opts[:options]
|
17
|
+
|
18
|
+
@run_calls, @run_bang_calls, @start_calls = [], [], []
|
19
|
+
@wait_calls, @stop_calls, @kill_calls = [], [], []
|
20
|
+
|
21
|
+
@running = false
|
22
|
+
|
23
|
+
@stdout, @stderr, @pid, @exitstatus = '', '', 1, 0
|
24
|
+
end
|
25
|
+
|
26
|
+
def run(input = nil)
|
27
|
+
@run_calls.push(InputCall.new(input))
|
28
|
+
Scmd.calls.push(Scmd::Call.new(self, input))
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def run_called?
|
33
|
+
!@run_calls.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
def run!(input = nil)
|
37
|
+
@run_bang_calls.push(InputCall.new(input))
|
38
|
+
Scmd.calls.push(Scmd::Call.new(self, input))
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def run_bang_called?
|
43
|
+
!@run_bang_calls.empty?
|
44
|
+
end
|
45
|
+
|
46
|
+
def start(input = nil)
|
47
|
+
@start_calls.push(InputCall.new(input))
|
48
|
+
Scmd.calls.push(Scmd::Call.new(self, input))
|
49
|
+
@running = true
|
50
|
+
end
|
51
|
+
|
52
|
+
def start_called?
|
53
|
+
!@start_calls.empty?
|
54
|
+
end
|
55
|
+
|
56
|
+
def wait(timeout = nil)
|
57
|
+
@wait_calls.push(TimeoutCall.new(timeout))
|
58
|
+
@running = false
|
59
|
+
end
|
60
|
+
|
61
|
+
def wait_called?
|
62
|
+
!@wait_calls.empty?
|
63
|
+
end
|
64
|
+
|
65
|
+
def stop(timeout = nil)
|
66
|
+
@stop_calls.push(TimeoutCall.new(timeout))
|
67
|
+
@running = false
|
68
|
+
end
|
69
|
+
|
70
|
+
def stop_called?
|
71
|
+
!@stop_calls.empty?
|
72
|
+
end
|
73
|
+
|
74
|
+
def kill(signal = nil)
|
75
|
+
@kill_calls.push(SignalCall.new(signal))
|
76
|
+
@running = false
|
77
|
+
end
|
78
|
+
|
79
|
+
def kill_called?
|
80
|
+
!@kill_calls.empty?
|
81
|
+
end
|
82
|
+
|
83
|
+
def running?
|
84
|
+
!!@running
|
85
|
+
end
|
86
|
+
|
87
|
+
def success?
|
88
|
+
@exitstatus == 0
|
89
|
+
end
|
90
|
+
|
91
|
+
def to_s
|
92
|
+
@cmd_str.to_s
|
93
|
+
end
|
94
|
+
|
95
|
+
def ==(other_spy)
|
96
|
+
if other_spy.kind_of?(CommandSpy)
|
97
|
+
self.cmd_str == other_spy.cmd_str &&
|
98
|
+
self.env == other_spy.env &&
|
99
|
+
self.options == other_spy.options &&
|
100
|
+
self.run_calls == other_spy.run_calls &&
|
101
|
+
self.run_bang_calls == other_spy.run_bang_calls &&
|
102
|
+
self.start_calls == other_spy.start_calls &&
|
103
|
+
self.wait_calls == other_spy.wait_calls &&
|
104
|
+
self.stop_calls == other_spy.stop_calls &&
|
105
|
+
self.kill_calls == other_spy.kill_calls &&
|
106
|
+
self.pid == other_spy.pid &&
|
107
|
+
self.exitstatus == other_spy.exitstatus &&
|
108
|
+
self.stdout == other_spy.stdout &&
|
109
|
+
self.stderr == other_spy.stderr
|
110
|
+
else
|
111
|
+
super
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
InputCall = Struct.new(:input)
|
116
|
+
TimeoutCall = Struct.new(:timeout)
|
117
|
+
SignalCall = Struct.new(:signal)
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'scmd/command_spy'
|
2
|
+
|
3
|
+
module Scmd
|
4
|
+
|
5
|
+
class StoredCommands
|
6
|
+
|
7
|
+
attr_reader :hash
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@hash = Hash.new{ |h, k| h[k] = Stub.new(k) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def add(cmd_str, &block)
|
14
|
+
@hash[cmd_str].tap{ |s| s.set_default_proc(&block) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def get(cmd_str, opts = nil)
|
18
|
+
@hash[cmd_str].call(opts)
|
19
|
+
end
|
20
|
+
|
21
|
+
def remove(cmd_str)
|
22
|
+
@hash.delete(cmd_str)
|
23
|
+
end
|
24
|
+
|
25
|
+
def remove_all
|
26
|
+
@hash.clear
|
27
|
+
end
|
28
|
+
|
29
|
+
def empty?
|
30
|
+
@hash.empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
def ==(other_stored_commands)
|
34
|
+
if other_stored_commands.kind_of?(StoredCommands)
|
35
|
+
self.hash == other_stored_commands.hash
|
36
|
+
else
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Stub
|
42
|
+
|
43
|
+
attr_reader :cmd_str, :hash
|
44
|
+
|
45
|
+
def initialize(cmd_str)
|
46
|
+
@cmd_str = cmd_str
|
47
|
+
@default_proc = proc{ |cmd_spy| } # no-op
|
48
|
+
@hash = {}
|
49
|
+
end
|
50
|
+
|
51
|
+
def set_default_proc(&block)
|
52
|
+
@default_proc = block if block
|
53
|
+
end
|
54
|
+
|
55
|
+
def with(opts, &block)
|
56
|
+
@hash[opts] = block
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
def call(opts)
|
61
|
+
block = @hash[opts] || @default_proc
|
62
|
+
CommandSpy.new(@cmd_str, opts).tap(&block)
|
63
|
+
end
|
64
|
+
|
65
|
+
def ==(other_stub)
|
66
|
+
if other_stub.kind_of?(Stub)
|
67
|
+
self.cmd_str == other_stub.cmd_str &&
|
68
|
+
self.hash == other_stub.hash
|
69
|
+
else
|
70
|
+
super
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
data/lib/scmd/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -0,0 +1,228 @@
|
|
1
|
+
require "assert"
|
2
|
+
require 'scmd/command_spy'
|
3
|
+
|
4
|
+
class Scmd::CommandSpy
|
5
|
+
|
6
|
+
class UnitTests < Assert::Context
|
7
|
+
desc "Scmd::CommandSpy"
|
8
|
+
setup do
|
9
|
+
@spy_class = Scmd::CommandSpy
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
class InitTests < UnitTests
|
15
|
+
setup do
|
16
|
+
@orig_scmd_test_mode = ENV['SCMD_TEST_MODE']
|
17
|
+
ENV['SCMD_TEST_MODE'] = '1'
|
18
|
+
Scmd.reset
|
19
|
+
|
20
|
+
@cmd_str = Factory.string
|
21
|
+
@spy = @spy_class.new(@cmd_str)
|
22
|
+
end
|
23
|
+
teardown do
|
24
|
+
Scmd.reset
|
25
|
+
ENV['SCMD_TEST_MODE'] = @orig_scmd_test_mode
|
26
|
+
end
|
27
|
+
subject{ @spy }
|
28
|
+
|
29
|
+
should have_readers :cmd_str, :env, :options
|
30
|
+
should have_readers :run_calls, :run_bang_calls, :start_calls
|
31
|
+
should have_readers :wait_calls, :stop_calls, :kill_calls
|
32
|
+
should have_accessors :pid, :exitstatus, :stdout, :stderr
|
33
|
+
should have_imeths :run, :run_called?, :run!, :run_bang_called?
|
34
|
+
should have_imeths :start, :start_called?
|
35
|
+
should have_imeths :wait, :wait_called?, :stop, :stop_called?
|
36
|
+
should have_imeths :kill, :kill_called?
|
37
|
+
should have_imeths :running?, :success?
|
38
|
+
|
39
|
+
should "know and return its cmd string" do
|
40
|
+
assert_equal @cmd_str, subject.cmd_str
|
41
|
+
assert_equal @cmd_str, subject.to_s
|
42
|
+
end
|
43
|
+
|
44
|
+
should "default its attrs" do
|
45
|
+
assert_nil subject.env
|
46
|
+
assert_nil subject.options
|
47
|
+
|
48
|
+
assert_equal [], subject.run_calls
|
49
|
+
assert_equal [], subject.run_bang_calls
|
50
|
+
assert_equal [], subject.start_calls
|
51
|
+
assert_equal [], subject.wait_calls
|
52
|
+
assert_equal [], subject.stop_calls
|
53
|
+
assert_equal [], subject.kill_calls
|
54
|
+
|
55
|
+
assert_equal 1, subject.pid
|
56
|
+
assert_equal 0, subject.exitstatus
|
57
|
+
assert_equal '', subject.stdout
|
58
|
+
assert_equal '', subject.stderr
|
59
|
+
end
|
60
|
+
|
61
|
+
should "allow specifying env and options" do
|
62
|
+
opts = { Factory.string => Factory.string }
|
63
|
+
cmd = Scmd::Command.new(Factory.string, {
|
64
|
+
:env => { :SCMD_TEST_VAR => 1 },
|
65
|
+
:options => opts
|
66
|
+
})
|
67
|
+
exp = { 'SCMD_TEST_VAR' => '1' }
|
68
|
+
assert_equal exp, cmd.env
|
69
|
+
assert_equal opts, cmd.options
|
70
|
+
end
|
71
|
+
|
72
|
+
should "know whether it is running or not" do
|
73
|
+
assert_false subject.running?
|
74
|
+
|
75
|
+
subject.run
|
76
|
+
assert_false subject.running?
|
77
|
+
subject.run!
|
78
|
+
assert_false subject.running?
|
79
|
+
|
80
|
+
subject.start
|
81
|
+
assert_true subject.running?
|
82
|
+
subject.stop
|
83
|
+
assert_false subject.running?
|
84
|
+
|
85
|
+
subject.start
|
86
|
+
subject.wait
|
87
|
+
assert_false subject.running?
|
88
|
+
|
89
|
+
subject.start
|
90
|
+
subject.kill
|
91
|
+
assert_false subject.running?
|
92
|
+
end
|
93
|
+
|
94
|
+
should "know if it was successful" do
|
95
|
+
assert_true subject.success?
|
96
|
+
|
97
|
+
subject.exitstatus = 1
|
98
|
+
assert_false subject.success?
|
99
|
+
|
100
|
+
subject.exitstatus = 0
|
101
|
+
assert_true subject.success?
|
102
|
+
|
103
|
+
subject.exitstatus = Factory.string
|
104
|
+
assert_false subject.success?
|
105
|
+
end
|
106
|
+
|
107
|
+
should "track its run calls" do
|
108
|
+
input = Factory.string
|
109
|
+
subject.run(input)
|
110
|
+
|
111
|
+
assert_equal 1, subject.run_calls.size
|
112
|
+
assert_kind_of InputCall, subject.run_calls.first
|
113
|
+
assert_equal input, subject.run_calls.first.input
|
114
|
+
|
115
|
+
assert_equal 1, Scmd.calls.size
|
116
|
+
assert_kind_of Scmd::Call, Scmd.calls.first
|
117
|
+
assert_equal @cmd_str, Scmd.calls.first.cmd_str
|
118
|
+
assert_equal input, Scmd.calls.first.input
|
119
|
+
assert_equal subject, Scmd.calls.first.cmd
|
120
|
+
|
121
|
+
subject.run(Factory.string)
|
122
|
+
assert_equal 2, subject.run_calls.size
|
123
|
+
assert_equal 2, Scmd.calls.size
|
124
|
+
end
|
125
|
+
|
126
|
+
should "track its run! calls" do
|
127
|
+
input = Factory.string
|
128
|
+
subject.run!(input)
|
129
|
+
|
130
|
+
assert_equal 1, subject.run_bang_calls.size
|
131
|
+
assert_kind_of InputCall, subject.run_bang_calls.first
|
132
|
+
assert_equal input, subject.run_bang_calls.first.input
|
133
|
+
|
134
|
+
assert_equal 1, Scmd.calls.size
|
135
|
+
assert_kind_of Scmd::Call, Scmd.calls.first
|
136
|
+
assert_equal @cmd_str, Scmd.calls.first.cmd_str
|
137
|
+
assert_equal input, Scmd.calls.first.input
|
138
|
+
assert_equal subject, Scmd.calls.first.cmd
|
139
|
+
|
140
|
+
subject.run!(Factory.string)
|
141
|
+
assert_equal 2, subject.run_bang_calls.size
|
142
|
+
assert_equal 2, Scmd.calls.size
|
143
|
+
end
|
144
|
+
|
145
|
+
should "track its start calls" do
|
146
|
+
input = Factory.string
|
147
|
+
subject.start(input)
|
148
|
+
|
149
|
+
assert_equal 1, subject.start_calls.size
|
150
|
+
assert_kind_of InputCall, subject.start_calls.first
|
151
|
+
assert_equal input, subject.start_calls.first.input
|
152
|
+
|
153
|
+
assert_equal 1, Scmd.calls.size
|
154
|
+
assert_kind_of Scmd::Call, Scmd.calls.first
|
155
|
+
assert_equal @cmd_str, Scmd.calls.first.cmd_str
|
156
|
+
assert_equal input, Scmd.calls.first.input
|
157
|
+
assert_equal subject, Scmd.calls.first.cmd
|
158
|
+
|
159
|
+
subject.start(Factory.string)
|
160
|
+
assert_equal 2, subject.start_calls.size
|
161
|
+
assert_equal 2, Scmd.calls.size
|
162
|
+
end
|
163
|
+
|
164
|
+
should "track its wait calls" do
|
165
|
+
timeout = Factory.string
|
166
|
+
subject.wait(timeout)
|
167
|
+
|
168
|
+
assert_equal 1, subject.wait_calls.size
|
169
|
+
assert_kind_of TimeoutCall, subject.wait_calls.first
|
170
|
+
assert_equal timeout, subject.wait_calls.first.timeout
|
171
|
+
|
172
|
+
subject.wait(Factory.string)
|
173
|
+
assert_equal 2, subject.wait_calls.size
|
174
|
+
end
|
175
|
+
|
176
|
+
should "track its stop calls" do
|
177
|
+
timeout = Factory.string
|
178
|
+
subject.stop(timeout)
|
179
|
+
|
180
|
+
assert_equal 1, subject.stop_calls.size
|
181
|
+
assert_kind_of TimeoutCall, subject.stop_calls.first
|
182
|
+
assert_equal timeout, subject.stop_calls.first.timeout
|
183
|
+
|
184
|
+
subject.stop(Factory.string)
|
185
|
+
assert_equal 2, subject.stop_calls.size
|
186
|
+
end
|
187
|
+
|
188
|
+
should "track its kill calls" do
|
189
|
+
signal = Factory.string
|
190
|
+
subject.kill(signal)
|
191
|
+
|
192
|
+
assert_equal 1, subject.kill_calls.size
|
193
|
+
assert_kind_of SignalCall, subject.kill_calls.first
|
194
|
+
assert_equal signal, subject.kill_calls.first.signal
|
195
|
+
|
196
|
+
subject.kill(Factory.string)
|
197
|
+
assert_equal 2, subject.kill_calls.size
|
198
|
+
end
|
199
|
+
|
200
|
+
should "know if it is equal to another cmd spy" do
|
201
|
+
spy1 = @spy_class.new(@cmd_str)
|
202
|
+
spy2 = @spy_class.new(@cmd_str)
|
203
|
+
|
204
|
+
assert_equal spy1, spy2
|
205
|
+
|
206
|
+
a = [
|
207
|
+
:cmd_str,
|
208
|
+
:env,
|
209
|
+
:options,
|
210
|
+
:run_calls,
|
211
|
+
:run_bang_calls,
|
212
|
+
:start_calls,
|
213
|
+
:wait_calls,
|
214
|
+
:stop_calls,
|
215
|
+
:kill_calls,
|
216
|
+
:pid,
|
217
|
+
:exitstatus,
|
218
|
+
:stdout,
|
219
|
+
:stderr
|
220
|
+
].choice
|
221
|
+
Assert.stub(spy2, a){ Factory.string }
|
222
|
+
|
223
|
+
assert_not_equal spy1, spy2
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
data/test/unit/command_tests.rb
CHANGED
@@ -8,7 +8,7 @@ class Scmd::Command
|
|
8
8
|
setup do
|
9
9
|
@cmd = Scmd::Command.new("echo hi")
|
10
10
|
end
|
11
|
-
subject
|
11
|
+
subject{ @cmd }
|
12
12
|
|
13
13
|
should have_readers :cmd_str, :env, :options
|
14
14
|
should have_readers :pid, :exitstatus, :stdout, :stderr
|
@@ -29,8 +29,8 @@ class Scmd::Command
|
|
29
29
|
cmd = Scmd::Command.new("echo $SCMD_TEST_VAR", {
|
30
30
|
:env => { :SCMD_TEST_VAR => 1 }
|
31
31
|
})
|
32
|
-
|
33
|
-
assert_equal
|
32
|
+
exp = { 'SCMD_TEST_VAR' => '1' }
|
33
|
+
assert_equal exp, cmd.env
|
34
34
|
end
|
35
35
|
|
36
36
|
should "default its options to an empty hash" do
|
data/test/unit/scmd_tests.rb
CHANGED
@@ -2,6 +2,8 @@ require "assert"
|
|
2
2
|
require 'scmd'
|
3
3
|
|
4
4
|
require 'scmd/command'
|
5
|
+
require 'scmd/command_spy'
|
6
|
+
require 'scmd/stored_commands'
|
5
7
|
|
6
8
|
module Scmd
|
7
9
|
|
@@ -9,10 +11,91 @@ module Scmd
|
|
9
11
|
desc "Scmd"
|
10
12
|
subject{ Scmd }
|
11
13
|
|
12
|
-
should
|
14
|
+
should have_imeths :new, :commands, :calls, :reset, :add_command
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
class NonTestModeTests < UnitTests
|
19
|
+
desc "when NOT in test mode"
|
13
20
|
|
14
21
|
should "build a `Command` with the `new` method" do
|
15
|
-
|
22
|
+
assert_instance_of Scmd::Command, subject.new('echo hi')
|
23
|
+
end
|
24
|
+
|
25
|
+
should "raise no method error on the test mode API methods" do
|
26
|
+
[:commands, :calls, :reset].each do |meth|
|
27
|
+
assert_raises(NoMethodError) do
|
28
|
+
subject.send(meth)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
assert_raises(NoMethodError) do
|
32
|
+
subject.add_command(Factory.string)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
class TestModeTests < UnitTests
|
39
|
+
desc "when in test mode"
|
40
|
+
setup do
|
41
|
+
@orig_scmd_test_mode = ENV['SCMD_TEST_MODE']
|
42
|
+
ENV['SCMD_TEST_MODE'] = '1'
|
43
|
+
Scmd.reset
|
44
|
+
end
|
45
|
+
teardown do
|
46
|
+
Scmd.reset
|
47
|
+
ENV['SCMD_TEST_MODE'] = @orig_scmd_test_mode
|
48
|
+
end
|
49
|
+
|
50
|
+
should "get a command spy from the commands collection with the new` method" do
|
51
|
+
assert_equal Scmd::CommandSpy.new('echo hi'), subject.new('echo hi')
|
52
|
+
end
|
53
|
+
|
54
|
+
should "know its test mode API attrs" do
|
55
|
+
assert_equal StoredCommands.new, subject.commands
|
56
|
+
assert_equal [], subject.calls
|
57
|
+
end
|
58
|
+
|
59
|
+
should "clear/remove the test mode API attrs on `reset`" do
|
60
|
+
cmd_str = Factory.string
|
61
|
+
subject.commands.add(cmd_str)
|
62
|
+
subject.calls.push(cmd_str)
|
63
|
+
assert_not_empty subject.commands
|
64
|
+
assert_not_empty subject.calls
|
65
|
+
|
66
|
+
subject.reset
|
67
|
+
assert_empty subject.commands
|
68
|
+
assert_empty subject.calls
|
69
|
+
end
|
70
|
+
|
71
|
+
should "add stored commands using `add_command`" do
|
72
|
+
cmd_str = Factory.string
|
73
|
+
output = Factory.text
|
74
|
+
assert_not_equal output, subject.new(cmd_str).stdout
|
75
|
+
|
76
|
+
subject.add_command(cmd_str){ |cmd| cmd.stdout = output }
|
77
|
+
assert_equal output, subject.new(cmd_str).stdout
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
class CallTests < UnitTests
|
83
|
+
desc "Call"
|
84
|
+
setup do
|
85
|
+
@cmd_str = Factory.string
|
86
|
+
@input = Factory.text
|
87
|
+
@cmd = CommandSpy.new(@cmd_str)
|
88
|
+
|
89
|
+
@call = Call.new(@cmd, @input)
|
90
|
+
end
|
91
|
+
subject{ @call }
|
92
|
+
|
93
|
+
should have_accessors :cmd_str, :input, :cmd
|
94
|
+
|
95
|
+
should "know its attrs" do
|
96
|
+
assert_equal @cmd_str, subject.cmd_str
|
97
|
+
assert_equal @input, subject.input
|
98
|
+
assert_equal @cmd, subject.cmd
|
16
99
|
end
|
17
100
|
|
18
101
|
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'scmd/stored_commands'
|
3
|
+
|
4
|
+
require 'scmd/command_spy'
|
5
|
+
|
6
|
+
class Scmd::StoredCommands
|
7
|
+
|
8
|
+
class UnitTests < Assert::Context
|
9
|
+
desc "Scmd::StoredCommands"
|
10
|
+
setup do
|
11
|
+
@cmd_str = Factory.string
|
12
|
+
@opts = { Factory.string => Factory.string }
|
13
|
+
@output = Factory.text
|
14
|
+
|
15
|
+
@commands = Scmd::StoredCommands.new
|
16
|
+
end
|
17
|
+
subject{ @commands }
|
18
|
+
|
19
|
+
should have_imeths :add, :get, :remove, :remove_all, :empty?
|
20
|
+
|
21
|
+
should "allow adding and getting commands when yielded a command" do
|
22
|
+
yielded = nil
|
23
|
+
subject.add(@cmd_str) do |cmd|
|
24
|
+
yielded = cmd
|
25
|
+
cmd.stdout = @output
|
26
|
+
end
|
27
|
+
cmd_spy = subject.get(@cmd_str, {})
|
28
|
+
|
29
|
+
assert_instance_of Scmd::CommandSpy, yielded
|
30
|
+
assert_equal yielded, cmd_spy
|
31
|
+
assert_equal @output, cmd_spy.stdout
|
32
|
+
end
|
33
|
+
|
34
|
+
should "return a stub when adding a command" do
|
35
|
+
stub = subject.add(@cmd_str)
|
36
|
+
assert_instance_of Scmd::StoredCommands::Stub, stub
|
37
|
+
|
38
|
+
stub.with(@opts){ |cmd| cmd.stdout = @output }
|
39
|
+
cmd = subject.get(@cmd_str, @opts)
|
40
|
+
assert_equal @output, cmd.stdout
|
41
|
+
|
42
|
+
cmd = subject.get(@cmd_str, {})
|
43
|
+
assert_not_equal @output, cmd.stdout
|
44
|
+
end
|
45
|
+
|
46
|
+
should "return a unaltered cmd spy for a cmd str that isn't configured" do
|
47
|
+
cmd_spy = Scmd::CommandSpy.new(@cmd_str)
|
48
|
+
cmd = subject.get(@cmd_str)
|
49
|
+
|
50
|
+
assert_equal cmd_spy, cmd
|
51
|
+
end
|
52
|
+
|
53
|
+
should "not call a cmd block until it is retrieved" do
|
54
|
+
called = false
|
55
|
+
subject.add(@cmd_str){ called = true }
|
56
|
+
assert_false called
|
57
|
+
subject.get(@cmd_str)
|
58
|
+
assert_true called
|
59
|
+
end
|
60
|
+
|
61
|
+
should "allow removing a stub" do
|
62
|
+
subject.add(@cmd_str){ |cmd| cmd.stdout = @output }
|
63
|
+
cmd = subject.get(@cmd_str)
|
64
|
+
assert_equal @output, cmd.stdout
|
65
|
+
|
66
|
+
subject.remove(@cmd_str)
|
67
|
+
cmd = subject.get(@cmd_str)
|
68
|
+
assert_not_equal @output, cmd.stdout
|
69
|
+
end
|
70
|
+
|
71
|
+
should "allow removing all commands" do
|
72
|
+
subject.add(@cmd_str){ |cmd| cmd.stdout = @output }
|
73
|
+
other_cmd_str = Factory.string
|
74
|
+
subject.add(other_cmd_str){ |cmd| cmd.stdout = @output }
|
75
|
+
|
76
|
+
subject.remove_all
|
77
|
+
cmd = subject.get(@cmd_str)
|
78
|
+
assert_not_equal @output, cmd.stdout
|
79
|
+
cmd = subject.get(other_cmd_str)
|
80
|
+
assert_not_equal @output, cmd.stdout
|
81
|
+
end
|
82
|
+
|
83
|
+
should "know if it is empty or not" do
|
84
|
+
assert_empty subject
|
85
|
+
|
86
|
+
subject.add(@cmd_str)
|
87
|
+
assert_not_empty subject
|
88
|
+
|
89
|
+
subject.remove_all
|
90
|
+
assert_empty subject
|
91
|
+
end
|
92
|
+
|
93
|
+
should "know if it is equal to another stored commands or not" do
|
94
|
+
cmds1 = Scmd::StoredCommands.new
|
95
|
+
cmds2 = Scmd::StoredCommands.new
|
96
|
+
assert_equal cmds1, cmds2
|
97
|
+
|
98
|
+
cmds1.add(@cmd_str)
|
99
|
+
assert_not_equal cmds1, cmds2
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
class StubTests < UnitTests
|
105
|
+
desc "Stub"
|
106
|
+
setup do
|
107
|
+
@stub = Stub.new(@cmd_str)
|
108
|
+
end
|
109
|
+
subject{ @stub }
|
110
|
+
|
111
|
+
should have_readers :cmd_str, :hash
|
112
|
+
should have_imeths :set_default_proc, :with, :call
|
113
|
+
|
114
|
+
should "default its default command proc" do
|
115
|
+
cmd_spy = Scmd::CommandSpy.new(@cmd_str, @opts)
|
116
|
+
cmd = subject.call(@opts)
|
117
|
+
assert_equal cmd_spy, cmd
|
118
|
+
end
|
119
|
+
|
120
|
+
should "allow setting its default proc" do
|
121
|
+
subject.set_default_proc{ |cmd| cmd.stdout = @output }
|
122
|
+
cmd = subject.call(@opts)
|
123
|
+
assert_equal @output, cmd.stdout
|
124
|
+
end
|
125
|
+
|
126
|
+
should "allow setting commands for specific opts" do
|
127
|
+
cmd = subject.call(@opts)
|
128
|
+
assert_equal '', cmd.stdout
|
129
|
+
|
130
|
+
subject.with({}){ |cmd| cmd.stdout = @output }
|
131
|
+
cmd = subject.call({})
|
132
|
+
assert_equal @output, cmd.stdout
|
133
|
+
end
|
134
|
+
|
135
|
+
should "know if it is equal to another stub or not" do
|
136
|
+
stub1 = Stub.new(@cmd_str)
|
137
|
+
stub2 = Stub.new(@cmd_str)
|
138
|
+
assert_equal stub1, stub2
|
139
|
+
|
140
|
+
Assert.stub(stub1, [:cmd_str, :hash].choice){ Factory.string }
|
141
|
+
assert_not_equal stub1, stub2
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scmd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 3
|
8
|
-
- 0
|
9
|
-
- 0
|
10
|
-
version: 3.0.0
|
4
|
+
version: 3.0.1
|
11
5
|
platform: ruby
|
12
6
|
authors:
|
13
7
|
- Kelly Redding
|
@@ -16,38 +10,27 @@ autorequire:
|
|
16
10
|
bindir: bin
|
17
11
|
cert_chain: []
|
18
12
|
|
19
|
-
date: 2015-
|
13
|
+
date: 2015-12-22 00:00:00 Z
|
20
14
|
dependencies:
|
21
15
|
- !ruby/object:Gem::Dependency
|
22
|
-
|
23
|
-
none: false
|
16
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
24
17
|
requirements:
|
25
18
|
- - ~>
|
26
19
|
- !ruby/object:Gem::Version
|
27
|
-
hash: 29
|
28
|
-
segments:
|
29
|
-
- 2
|
30
|
-
- 15
|
31
20
|
version: "2.15"
|
32
21
|
type: :development
|
22
|
+
requirement: *id001
|
33
23
|
name: assert
|
34
|
-
version_requirements: *id001
|
35
24
|
prerelease: false
|
36
25
|
- !ruby/object:Gem::Dependency
|
37
|
-
|
38
|
-
none: false
|
26
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
39
27
|
requirements:
|
40
28
|
- - ~>
|
41
29
|
- !ruby/object:Gem::Version
|
42
|
-
hash: 5
|
43
|
-
segments:
|
44
|
-
- 0
|
45
|
-
- 3
|
46
|
-
- 11
|
47
30
|
version: 0.3.11
|
48
31
|
type: :runtime
|
32
|
+
requirement: *id002
|
49
33
|
name: posix-spawn
|
50
|
-
version_requirements: *id002
|
51
34
|
prerelease: false
|
52
35
|
description: Build and run system commands.
|
53
36
|
email:
|
@@ -69,54 +52,55 @@ files:
|
|
69
52
|
- bench/runner.rb
|
70
53
|
- lib/scmd.rb
|
71
54
|
- lib/scmd/command.rb
|
55
|
+
- lib/scmd/command_spy.rb
|
56
|
+
- lib/scmd/stored_commands.rb
|
72
57
|
- lib/scmd/version.rb
|
73
58
|
- log/.gitkeep
|
74
59
|
- scmd.gemspec
|
75
60
|
- script/bench.rb
|
76
61
|
- test/helper.rb
|
77
62
|
- test/support/bigger-than-64k.txt
|
63
|
+
- test/support/factory.rb
|
78
64
|
- test/support/smaller-than-64k.txt
|
79
65
|
- test/system/command_tests.rb
|
66
|
+
- test/unit/command_spy_tests.rb
|
80
67
|
- test/unit/command_tests.rb
|
81
68
|
- test/unit/scmd_tests.rb
|
69
|
+
- test/unit/stored_commands_tests.rb
|
82
70
|
- tmp/.gitkeep
|
83
71
|
homepage: http://github.com/redding/scmd
|
84
72
|
licenses:
|
85
73
|
- MIT
|
74
|
+
metadata: {}
|
75
|
+
|
86
76
|
post_install_message:
|
87
77
|
rdoc_options: []
|
88
78
|
|
89
79
|
require_paths:
|
90
80
|
- lib
|
91
81
|
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
-
none: false
|
93
82
|
requirements:
|
94
|
-
-
|
83
|
+
- &id003
|
84
|
+
- ">="
|
95
85
|
- !ruby/object:Gem::Version
|
96
|
-
hash: 3
|
97
|
-
segments:
|
98
|
-
- 0
|
99
86
|
version: "0"
|
100
87
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
-
none: false
|
102
88
|
requirements:
|
103
|
-
-
|
104
|
-
- !ruby/object:Gem::Version
|
105
|
-
hash: 3
|
106
|
-
segments:
|
107
|
-
- 0
|
108
|
-
version: "0"
|
89
|
+
- *id003
|
109
90
|
requirements: []
|
110
91
|
|
111
92
|
rubyforge_project:
|
112
|
-
rubygems_version:
|
93
|
+
rubygems_version: 2.5.1
|
113
94
|
signing_key:
|
114
|
-
specification_version:
|
95
|
+
specification_version: 4
|
115
96
|
summary: Build and run system commands.
|
116
97
|
test_files:
|
117
98
|
- test/helper.rb
|
118
99
|
- test/support/bigger-than-64k.txt
|
100
|
+
- test/support/factory.rb
|
119
101
|
- test/support/smaller-than-64k.txt
|
120
102
|
- test/system/command_tests.rb
|
103
|
+
- test/unit/command_spy_tests.rb
|
121
104
|
- test/unit/command_tests.rb
|
122
105
|
- test/unit/scmd_tests.rb
|
106
|
+
- test/unit/stored_commands_tests.rb
|