2

I'd like to test response to user input. That input is queried using Highline:

def get_name
  return HighLine.new.ask("What is your name?")
end

I'd like to do something similar to this question and put it in my test:

STDOUT.should_receive(:puts).with("What is your name?")
STDIN.should_receive(:read).and_return("Inigo Montoya")
MyClass.new.get_name.should == "Inigo Montoya"

What is the correct way to do this with Highline?

Community
  • 1
  • 1
Ovesh
  • 5,209
  • 11
  • 53
  • 73

4 Answers4

10

The best way to find out how to test Highline is to see how the author tests his package.

class TestHighLine < Test::Unit::TestCase
  def setup
    @input    = StringIO.new
    @output   = StringIO.new
    @terminal = HighLine.new(@input, @output)..
  end
..
  def test_agree
    @input << "y\nyes\nYES\nHell no!\nNo\n"
    @input.rewind

    assert_equal(true, @terminal.agree("Yes or no?  "))
    assert_equal(true, @terminal.agree("Yes or no?  "))
    assert_equal(true, @terminal.agree("Yes or no?  "))
    assert_equal(false, @terminal.agree("Yes or no?  "))
....
    @input.truncate(@input.rewind)
    @input << "yellow"
    @input.rewind

    assert_equal(true, @terminal.agree("Yes or no?  ", :getc))
  end


   def test_ask
     name = "James Edward Gray II"
     @input << name << "\n"
     @input.rewind

     assert_equal(name, @terminal.ask("What is your name?  "))
 ....
     assert_raise(EOFError) { @terminal.ask("Any input left?  ") }
   end

Etc., as shown in his code. You can find this information in the highline source paying close attention to the setup, which I have highlighted in the link.

Notice how he uses the STDIN IO pipe to act in the place of typing the keys on the keyboard.

What this indicates, really, is that you don't need to use highline to test that kind of thing. The setup in his tests are really key here. Along with his use of StringIO as an object.

vgoff
  • 10,980
  • 3
  • 38
  • 56
1

Highline already has it's own tests to make sure that it outputs to STDOUT and reads from STDIN. There is no reason to write these types of tests. It's the same reason that you would not write ActiveRecord tests that make sure attributes can be saved and read from the database.

However... it would be extremely useful if there were a framework for Highline that works in a similar fashion as Capybara for web forms... something that actually drives the input from the UI and tests the logic of your command-line utility.

For example, the following kind of hypothetical test would be nice:

run 'my_utility.rb'
highline.should :show_menu
select :add
highline.should(:ask).with_prompt("name?")
enter "John Doe"
output.should == "created new user"
user132447
  • 1,651
  • 13
  • 6
1

I have published HighLine::Test - it allows you to run your tests in one process and your application in another (in the same way as you would with browser-based tests with Selenium).

titusd
  • 516
  • 6
  • 5
1

I worked on this DSL to try to solve this problem:

https://github.com/bonzofenix/cancun

require 'spec_helper'

describe Foo do
  include Cancun::Highline
  before { init_highline_test }

  describe '#hello' do
    it 'says hello correctly' do
    execute do
      Foo.new.salute
    end.and_type 'bonzo'
    expect(output).to include('Hi bonzo')
  end
bonzofenix
  • 635
  • 5
  • 12