highline-test 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +84 -0
- data/Rakefile +9 -0
- data/highline-test.gemspec +29 -0
- data/lib/highline/test.rb +11 -0
- data/lib/highline/test/client.rb +90 -0
- data/lib/highline/test/driver.rb +26 -0
- data/lib/highline/test/partial_reader.rb +15 -0
- data/lib/highline/test/version.rb +5 -0
- data/spec/lib/highline/test/client_spec.rb +215 -0
- data/spec/lib/highline/test/driver_spec.rb +75 -0
- data/spec/lib/highline/test/partial_reader_spec.rb +42 -0
- data/spec/spec_helper.rb +12 -0
- metadata +162 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Joe Yates
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# Highline::Test
|
2
|
+
|
3
|
+
A micro framework to help you test your HighLine applications.
|
4
|
+
|
5
|
+
HighLine allows you to supply your own input and output streams (instead of the
|
6
|
+
default STDIN and STDOUT). This fact facilitates testing, allowing you to use
|
7
|
+
StringIO objects for input and output.
|
8
|
+
|
9
|
+
The problem with this approach is that it is hard to seperate the test, which pushes
|
10
|
+
data to the input stream, and the application which reads that data.
|
11
|
+
|
12
|
+
HighLine::Test resolves this problem by forking the test process.
|
13
|
+
One fork runs the tests, the other runs the application.
|
14
|
+
The two processes communicate via pipes.
|
15
|
+
|
16
|
+
HighLine::test can be used with any testing framework, e.g.
|
17
|
+
|
18
|
+
* RSpec
|
19
|
+
* Test::Unit
|
20
|
+
* Cucumber
|
21
|
+
|
22
|
+
## Installation
|
23
|
+
|
24
|
+
Add this line to your application's Gemfile:
|
25
|
+
|
26
|
+
gem 'highline-test'
|
27
|
+
|
28
|
+
And then execute:
|
29
|
+
|
30
|
+
$ bundle
|
31
|
+
|
32
|
+
Or install it yourself as:
|
33
|
+
|
34
|
+
$ gem install highline-test
|
35
|
+
|
36
|
+
## Usage
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
require 'highline/test'
|
40
|
+
|
41
|
+
before do
|
42
|
+
# Before running a test, create a HighLine::Test::Client
|
43
|
+
@client = HighLine::Test::Client.new
|
44
|
+
|
45
|
+
# The application itself is started in a block passed to the #run method
|
46
|
+
@client.run do |driver|
|
47
|
+
# This block is run in a child process
|
48
|
+
|
49
|
+
# The HighLine instance used by the application *must* be the one supplied by
|
50
|
+
# the client.
|
51
|
+
HighLine.stub(:new).and_return(@client.high_line)
|
52
|
+
|
53
|
+
# Do any other setup (e.g. stubbing) here
|
54
|
+
|
55
|
+
# Start the application under test
|
56
|
+
MyApp.new.run
|
57
|
+
|
58
|
+
# If this block ever completes, the child process will be killed by
|
59
|
+
# HighLine::Test
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
after do
|
64
|
+
# Ensure the child process is cleaned up
|
65
|
+
@client.cleanup
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'says Hello' do
|
69
|
+
# Send text input to the application
|
70
|
+
@client.type 'Fred'
|
71
|
+
|
72
|
+
# Test application output
|
73
|
+
expect(@client.output).to include('Hello Fred!')
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
## Contributing
|
78
|
+
|
79
|
+
1. Fork it
|
80
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
81
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
82
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
83
|
+
5. Create new Pull Request
|
84
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'highline/test/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'highline-test'
|
8
|
+
spec.version = Highline::Test::VERSION
|
9
|
+
spec.authors = ['Joe Yates']
|
10
|
+
spec.email = ['joe.g.yates@gmail.com']
|
11
|
+
spec.description = %q{Test HighLine applications}
|
12
|
+
spec.summary = %q{A micro framework that sets up tests for HighLine applications}
|
13
|
+
spec.homepage = ''
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(spec)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_dependency 'highline'
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
24
|
+
spec.add_development_dependency 'rake'
|
25
|
+
spec.add_development_dependency 'rspec'
|
26
|
+
spec.add_development_dependency 'bourne'
|
27
|
+
spec.add_development_dependency 'shoulda-matchers'
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module HighLine::Test
|
2
|
+
class Client
|
3
|
+
DEFAULT_POST_INPUT_DELAY = 0.1
|
4
|
+
|
5
|
+
# The delay in milliseconds that the client waits after sending text via
|
6
|
+
# the #type method
|
7
|
+
attr_accessor :delay
|
8
|
+
attr_accessor :child_pid
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@delay = DEFAULT_POST_INPUT_DELAY
|
12
|
+
setup
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
raise "Supply a block to provide a context in which the application is run" unless block_given?
|
17
|
+
|
18
|
+
create_pipes
|
19
|
+
|
20
|
+
@child_pid = fork
|
21
|
+
|
22
|
+
if child_pid.nil?
|
23
|
+
partial_reader = PartialReader.new(@input_read)
|
24
|
+
driver = Driver.new(partial_reader, @output_write)
|
25
|
+
yield driver
|
26
|
+
|
27
|
+
# if the subject ever returns, kill the child process
|
28
|
+
Process.kill(:KILL, Process.pid)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def cleanup
|
33
|
+
return unless running?
|
34
|
+
|
35
|
+
kill_child_process
|
36
|
+
close_pipes
|
37
|
+
setup
|
38
|
+
end
|
39
|
+
|
40
|
+
def running?
|
41
|
+
not child_pid.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
def type(text)
|
45
|
+
raise 'Client is not running' unless running?
|
46
|
+
|
47
|
+
@input_write << "#{text}\n"
|
48
|
+
sleep delay
|
49
|
+
end
|
50
|
+
|
51
|
+
def output
|
52
|
+
return @output if @output
|
53
|
+
@output_write.close unless @output_write.closed?
|
54
|
+
@output = @output_read.readpartial(PIPE_BUFFER_SIZE)
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def setup
|
60
|
+
@input_read = nil
|
61
|
+
@input_write = nil
|
62
|
+
@output_read = nil
|
63
|
+
@output_write = nil
|
64
|
+
@output = nil
|
65
|
+
@child_pid = nil
|
66
|
+
end
|
67
|
+
|
68
|
+
def create_pipes
|
69
|
+
@input_read, @input_write = IO.pipe
|
70
|
+
@output_read, @output_write = IO.pipe
|
71
|
+
end
|
72
|
+
|
73
|
+
def kill_child_process
|
74
|
+
return if child_pid.nil?
|
75
|
+
|
76
|
+
Process.kill(:KILL, child_pid)
|
77
|
+
rescue Errno::ESRCH => e
|
78
|
+
# swallow errors if the child process has already been killed
|
79
|
+
ensure
|
80
|
+
@child_pid = nil
|
81
|
+
end
|
82
|
+
|
83
|
+
def close_pipes
|
84
|
+
[@input_read, @input_write, @output_read, @output_write].each do |stream|
|
85
|
+
stream.close unless stream.closed?
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'highline'
|
2
|
+
|
3
|
+
module HighLine::Test
|
4
|
+
class Driver
|
5
|
+
attr_reader :input_stream
|
6
|
+
attr_reader :output_stream
|
7
|
+
|
8
|
+
def initialize(input_stream, output_stream)
|
9
|
+
@input_stream = input_stream
|
10
|
+
@output_stream = output_stream
|
11
|
+
end
|
12
|
+
|
13
|
+
# Creates and returns a HighLine instance, set up to use the supplied streams
|
14
|
+
def high_line
|
15
|
+
return @high_line if @high_line
|
16
|
+
HighLine.track_eof = false
|
17
|
+
@high_line = HighLine.new(input_stream, output_stream)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Adds text to the output stream
|
21
|
+
def inject(text)
|
22
|
+
@output_stream << text
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module HighLine::Test
|
2
|
+
# Wraps a pipe, supplying a non-blocking #gets method
|
3
|
+
class PartialReader
|
4
|
+
attr_reader :stream
|
5
|
+
|
6
|
+
def initialize(stream)
|
7
|
+
@stream = stream
|
8
|
+
end
|
9
|
+
|
10
|
+
def gets
|
11
|
+
stream.readpartial(PIPE_BUFFER_SIZE)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,215 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module HighLine::Test
|
4
|
+
describe Client do
|
5
|
+
let(:input_read) { double('IO input pipe - read end', closed?: true) }
|
6
|
+
let(:input_write) { double('IO input pipe - write end', closed?: true) }
|
7
|
+
let(:output_read) { double('IO output pipe - read end', closed?: true) }
|
8
|
+
let(:output_write) { double('IO output pipe - write end', closed?: true) }
|
9
|
+
let(:input_pipe) { [input_read, input_write] }
|
10
|
+
let(:output_pipe) { [output_read, output_write] }
|
11
|
+
let(:streams) { input_pipe + output_pipe }
|
12
|
+
let(:child_pid) { 'child_pid' }
|
13
|
+
let(:running_subject) do
|
14
|
+
subject.run {}
|
15
|
+
subject
|
16
|
+
end
|
17
|
+
|
18
|
+
before do
|
19
|
+
subject.stub(:fork).and_return(child_pid)
|
20
|
+
IO.stub(:pipe).and_return(input_pipe, output_pipe)
|
21
|
+
Process.stub(:kill)
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#delay' do
|
25
|
+
it 'defaults to 0.1' do
|
26
|
+
expect(subject.delay).to eq(0.1)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#delay=' do
|
31
|
+
it 'sets the delay value' do
|
32
|
+
subject.delay = 0.3
|
33
|
+
|
34
|
+
expect(subject.delay).to eq(0.3)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#run' do
|
39
|
+
it 'fails if no block is passed' do
|
40
|
+
expect {
|
41
|
+
subject.run
|
42
|
+
}.to raise_error(RuntimeError, /Supply a block/)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'creates two pipes' do
|
46
|
+
subject.run {}
|
47
|
+
|
48
|
+
expect(IO).to have_received(:pipe).twice
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'forks' do
|
52
|
+
subject.run {}
|
53
|
+
|
54
|
+
expect(subject).to have_received(:fork)
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'child process' do
|
58
|
+
let(:partial_reader) { double('PartialReader') }
|
59
|
+
let(:driver) { double('Driver') }
|
60
|
+
|
61
|
+
before do
|
62
|
+
subject.stub(:fork).and_return(nil)
|
63
|
+
PartialReader.stub(:new).and_return(partial_reader)
|
64
|
+
Driver.stub(:new).with(partial_reader, output_write).and_return(driver)
|
65
|
+
Process.stub(:pid).and_return(child_pid)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'wraps the input stream in a class with a non-blocking #gets method' do
|
69
|
+
subject.run {}
|
70
|
+
|
71
|
+
expect(PartialReader).to have_received(:new).with(input_read)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'sets up a driver' do
|
75
|
+
subject.run {}
|
76
|
+
|
77
|
+
expect(Driver).to have_received(:new).with(partial_reader, output_write)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'calls the block' do
|
81
|
+
calls = 0
|
82
|
+
p = proc { calls += 1 }
|
83
|
+
|
84
|
+
subject.run(&p)
|
85
|
+
|
86
|
+
expect(calls).to eq(1)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'kills the child process if the block returns' do
|
90
|
+
subject.run {}
|
91
|
+
|
92
|
+
expect(Process).to have_received(:pid)
|
93
|
+
expect(Process).to have_received(:kill).with(:KILL, child_pid)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'parent process' do
|
98
|
+
before do
|
99
|
+
PartialReader.stub(:new)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'returns immediately' do
|
103
|
+
subject.run {}
|
104
|
+
|
105
|
+
expect(PartialReader).to_not have_received(:new)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#cleanup' do
|
111
|
+
it 'kills the child process' do
|
112
|
+
running_subject.cleanup
|
113
|
+
|
114
|
+
expect(Process).to have_received(:kill).with(:KILL, child_pid)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'does nothing if not running' do
|
118
|
+
subject.cleanup
|
119
|
+
|
120
|
+
expect(Process).to_not have_received(:kill)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "doesn't fail if the child process has terminated" do
|
124
|
+
Process.stub(:kill).and_raise(Errno::ESRCH)
|
125
|
+
|
126
|
+
expect {
|
127
|
+
running_subject.cleanup
|
128
|
+
}.not_to raise_error
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'closes pipes' do
|
132
|
+
streams.each do |stream|
|
133
|
+
stream.stub(closed?: false)
|
134
|
+
stream.stub(:close)
|
135
|
+
end
|
136
|
+
|
137
|
+
running_subject.cleanup
|
138
|
+
|
139
|
+
streams.each do |stream|
|
140
|
+
expect(stream).to have_received(:close)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe '#running?' do
|
146
|
+
it 'is true in the parent after #run is called' do
|
147
|
+
expect(running_subject.running?).to be_true
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'is false after #cleanup' do
|
151
|
+
running_subject.cleanup
|
152
|
+
|
153
|
+
expect(subject.running?).to be_false
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe '#type' do
|
158
|
+
before do
|
159
|
+
input_write.stub(:<<)
|
160
|
+
subject.stub(:sleep)
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'expects a parameter' do
|
164
|
+
expect {
|
165
|
+
subject.type
|
166
|
+
}.to raise_error(ArgumentError, /0 for 1/)
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'fails if not running' do
|
170
|
+
expect {
|
171
|
+
subject.type 'Ciao'
|
172
|
+
}.to raise_error(RuntimeError, /not running/)
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'appends the text and a new line to the input write stream' do
|
176
|
+
running_subject.type 'Ciao'
|
177
|
+
|
178
|
+
expect(input_write).to have_received(:<<).with("Ciao\n")
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'sleeps for #delay seconds' do
|
182
|
+
running_subject.type 'Ciao'
|
183
|
+
|
184
|
+
expect(running_subject).to have_received(:sleep).with(0.1)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
describe '#output' do
|
189
|
+
before do
|
190
|
+
streams.each do |stream|
|
191
|
+
stream.stub(closed?: false)
|
192
|
+
stream.stub(:close)
|
193
|
+
end
|
194
|
+
output_read.stub(:readpartial).with(4096).and_return('Foo')
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'closes the output write stream' do
|
198
|
+
running_subject.output
|
199
|
+
|
200
|
+
expect(output_write).to have_received(:close)
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'gets the output from HighLine' do
|
204
|
+
running_subject.output
|
205
|
+
|
206
|
+
expect(output_read).to have_received(:readpartial).with(4096)
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'returns the output' do
|
210
|
+
expect(running_subject.output).to eq('Foo')
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module HighLine::Test
|
4
|
+
describe Driver do
|
5
|
+
let(:input_stream) { double('IO input') }
|
6
|
+
let(:output_stream) { double('IO output') }
|
7
|
+
|
8
|
+
subject { Driver.new(input_stream, output_stream) }
|
9
|
+
|
10
|
+
describe '#initialize' do
|
11
|
+
it 'expects an input and an output stream' do
|
12
|
+
expect {
|
13
|
+
Driver.new
|
14
|
+
}.to raise_error(ArgumentError, /0 for 2/)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#input_stream' do
|
19
|
+
it 'returns the supplied input stream' do
|
20
|
+
expect(subject.input_stream).to eq(input_stream)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#output_stream' do
|
25
|
+
it 'returns the supplied output stream' do
|
26
|
+
expect(subject.output_stream).to eq(output_stream)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#high_line' do
|
31
|
+
let(:high_line) { double('HighLine') }
|
32
|
+
|
33
|
+
before do
|
34
|
+
HighLine.stub(:track_eof=)
|
35
|
+
HighLine.stub(:new).and_return(high_line)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'stops HighLine tracking eof' do
|
39
|
+
subject.high_line
|
40
|
+
|
41
|
+
expect(HighLine).to have_received(:track_eof=).with(false)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'sets up a HighLine instance with the supplied streams' do
|
45
|
+
subject.high_line
|
46
|
+
|
47
|
+
expect(HighLine).to have_received(:new).with(input_stream, output_stream)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'returns the HighLine instance' do
|
51
|
+
expect(subject.high_line).to eq(high_line)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'only creates one instance' do
|
55
|
+
subject.high_line
|
56
|
+
subject.high_line
|
57
|
+
|
58
|
+
expect(HighLine).to have_received(:new).once.with(input_stream, output_stream)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#inject' do
|
63
|
+
before do
|
64
|
+
output_stream.stub(:<<)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'adds text to the output stream' do
|
68
|
+
subject.inject('foo')
|
69
|
+
|
70
|
+
expect(output_stream).to have_received(:<<).with('foo')
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module HighLine::Test
|
4
|
+
describe PartialReader do
|
5
|
+
let(:stream) { double('IO') }
|
6
|
+
|
7
|
+
subject { PartialReader.new(stream) }
|
8
|
+
|
9
|
+
describe '#initialize' do
|
10
|
+
it 'expects a stream parameter' do
|
11
|
+
expect {
|
12
|
+
PartialReader.new
|
13
|
+
}.to raise_error(ArgumentError, /0 for 1/)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#stream' do
|
18
|
+
it 'returns the stream' do
|
19
|
+
expect(subject.stream).to eq(stream)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#gets' do
|
24
|
+
let(:output) { 'Hi there' }
|
25
|
+
|
26
|
+
before do
|
27
|
+
stream.stub(:readpartial).and_return(output)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'performs a non-blocking read' do
|
31
|
+
subject.gets
|
32
|
+
|
33
|
+
expect(stream).to have_received(:readpartial).with(4096)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns the result' do
|
37
|
+
expect(subject.gets).to eq(output)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'bourne'
|
3
|
+
require 'highline/test'
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
7
|
+
config.run_all_when_everything_filtered = true
|
8
|
+
config.filter_run :focus
|
9
|
+
|
10
|
+
config.order = 'random'
|
11
|
+
end
|
12
|
+
|
metadata
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: highline-test
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Joe Yates
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-07-07 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: highline
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.3'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.3'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: bourne
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: shoulda-matchers
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description: Test HighLine applications
|
111
|
+
email:
|
112
|
+
- joe.g.yates@gmail.com
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- .gitignore
|
118
|
+
- Gemfile
|
119
|
+
- LICENSE.txt
|
120
|
+
- README.md
|
121
|
+
- Rakefile
|
122
|
+
- highline-test.gemspec
|
123
|
+
- lib/highline/test.rb
|
124
|
+
- lib/highline/test/client.rb
|
125
|
+
- lib/highline/test/driver.rb
|
126
|
+
- lib/highline/test/partial_reader.rb
|
127
|
+
- lib/highline/test/version.rb
|
128
|
+
- spec/lib/highline/test/client_spec.rb
|
129
|
+
- spec/lib/highline/test/driver_spec.rb
|
130
|
+
- spec/lib/highline/test/partial_reader_spec.rb
|
131
|
+
- spec/spec_helper.rb
|
132
|
+
homepage: ''
|
133
|
+
licenses:
|
134
|
+
- MIT
|
135
|
+
post_install_message:
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
none: false
|
141
|
+
requirements:
|
142
|
+
- - ! '>='
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
|
+
none: false
|
147
|
+
requirements:
|
148
|
+
- - ! '>='
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
requirements: []
|
152
|
+
rubyforge_project:
|
153
|
+
rubygems_version: 1.8.23
|
154
|
+
signing_key:
|
155
|
+
specification_version: 3
|
156
|
+
summary: A micro framework that sets up tests for HighLine applications
|
157
|
+
test_files:
|
158
|
+
- spec/lib/highline/test/client_spec.rb
|
159
|
+
- spec/lib/highline/test/driver_spec.rb
|
160
|
+
- spec/lib/highline/test/partial_reader_spec.rb
|
161
|
+
- spec/spec_helper.rb
|
162
|
+
has_rdoc:
|