Recently I published Qc, a tool for interacting with QuantConnect using the command-line. It lets you develop your algos in your local box, without having to open QuantConnect web editor to run them.

I wanted to write some system tests that invoked the command line tool and checked the results. As long as I can keep them fast, I love system tests that test the real thing from top to bottom.

It uses the QuantConnect API under the hood. It is HTTP-based, so I could use VCR and not having to mock the API connection for testing purposes. I love VCR, so this was an easy choice.

For testing commands execution, I first tried to use aruba. I had learned about it in this book and I knew RSpec used it for its tests. Unfortunately, I found a blocking issue: for VCR (or any mocking approach) to work, I needed to use the in_process approach, but this mode wouldn’t work with running commands interactively. I needed to exercise how the user interacted with the tool for a couple of cases, so this invalidated aruba for me.

Looking for an alternative, I ended up just using plain Ruby and writing a few simple helpers for my needs:

The resulting helper was very simple and allowed me to write pretty expressive tests like this:

  def test_init_asks_for_project_and_store_it_in_settings_with_default_extension
    sign_in

    type_when_prompted '2', '' do
      run_command 'qc init'
    end

    assert_match /My first C# project/, last_command.output

    assert_stored_project_settings project_id: '799895', file_extensions: 'cs,py'
    assert_equal 0, last_command.exit_status
  end

For dealing with files, I liked aruba’s approach of creating a fixtures directory with files you can use to prepare your tests. Ruby support for scripting with files is wonderful, so it was easy to prepare another helper that allowed me to write tests like this:

class PushTest < SystemTest
  def setup
    prepare_local_files 'file_1.cs', 'file_2.cs'
    ...
  end

  def test_initial_push_should_push_all_the_files
    run_command 'qc push'
    assert_match /Uploading file_1.cs.../, last_command.output
    assert_match /Uploading file_2.cs.../, last_command.output
    assert_files_were_uploaded 'file_1.cs', 'file_2.cs'
  end
  ...
end  

I remember that in my early days with Ruby and Rails I was willing to use whatever gem that more or less matched my needs. These days I fight a lot before adding new libraries. This was a good reminder to check how vanilla works for you before adding third-party solutions.