-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extract ExternalCommand class #72
base: master
Are you sure you want to change the base?
Changes from all commits
12515f8
fa92383
7dbcf6a
c9637b7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# frozen_string_literal: true | ||
require 'English' | ||
require_relative 'external_command/result' | ||
|
||
class ExternalCommand | ||
def initialize(command:, env: {}) | ||
@command = command | ||
@env = env | ||
end | ||
|
||
def run | ||
with_tmp_dir do | ||
Result.new( | ||
output: IO.popen(env, command, &:read), | ||
child_status: $CHILD_STATUS | ||
) | ||
end | ||
end | ||
|
||
private | ||
|
||
attr_reader :env, :command | ||
|
||
def with_tmp_dir(&block) | ||
Dir.mktmpdir do |tmp_dir| | ||
Dir.chdir(tmp_dir, &block) | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# frozen_string_literal: true | ||
|
||
class ExternalCommand | ||
class Result | ||
attr_reader :output | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's a bit of a red flag for one of the constructor parameters to be public, and for there to be no behaviour whatsoever in this class related to it. As the only method is really only a very simple delegation to the other constructor, I wonder if this really needs to be a full class at all, or whether a Struct might be enough for now. Or, perhaps this is a sign that this class should really be taking care of things like cleaning up the output, rather than returning it as-is for the caller to clean up? |
||
|
||
def initialize(output:, child_status:) | ||
@output = output | ||
@child_status = child_status | ||
end | ||
|
||
def success? | ||
child_status.success? | ||
end | ||
|
||
private | ||
|
||
attr_reader :child_status | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# frozen_string_literal: true | ||
require 'test_helper' | ||
require_relative '../lib/external_command' | ||
|
||
describe 'ExternalCommand' do | ||
describe 'running a simple command' do | ||
subject { ExternalCommand.new(command: 'echo Hello, world.').run } | ||
|
||
it 'returns the expected output' do | ||
subject.output.must_equal "Hello, world.\n" | ||
end | ||
|
||
it 'is considered to be successful' do | ||
subject.success?.must_equal true | ||
end | ||
end | ||
|
||
describe 'running a command with environment variables set' do | ||
subject { ExternalCommand.new(command: 'echo Hello, $name.', env: { 'name' => 'Bob' }).run } | ||
|
||
it 'returns the expected output' do | ||
subject.output.must_equal "Hello, Bob.\n" | ||
end | ||
|
||
it 'is considered to be successful' do | ||
subject.success?.must_equal true | ||
end | ||
end | ||
|
||
describe 'running an external command that fails' do | ||
subject { ExternalCommand.new(command: 'echo fail; exit 1').run } | ||
|
||
it 'returns the expected output' do | ||
subject.output.must_equal "fail\n" | ||
end | ||
|
||
it 'is considered to be a failure' do | ||
subject.success?.must_equal false | ||
end | ||
end | ||
|
||
describe 'running commands in a tmpdir' do | ||
let(:other_command) { ExternalCommand.new(command: 'pwd').run } | ||
subject { ExternalCommand.new(command: 'pwd').run } | ||
|
||
it 'runs in a different directory each time' do | ||
subject.output.wont_equal other_command.output | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got tripped up by this being named as if it were a pure command method (i.e. would have no return value). I think it would be better to name this
result
or equivalent to highlight that you're actually getting something back from it.