ruby, tests, rspec, thor

Testing Thor Ruby Required Options

Testing Thor Ruby Required Options

Testing Thor Ruby Required Options

There are lots of tutorials for building a CLI with Thor from scratch, but there aren't a lot of them on how to test Thor, especially covering scenarios such as required options. Learn how to test Thor Ruby options.

Thor Ruby gem is a great tool to quickly build a CLI (Command-line interface) app.

Although there are lots of tutorials for building a CLI with Thor from scratch, there aren’t a lot of them on how to test Thor, especially covering scenarios such as required options.

Thor makes it easy to specify options and arguments for Thor commands. However, I didn’t find it easy to test them in the documentation.

If you’ve been searching for tutorials on how to test Thor with required options, this post is for you ⚡

Thor Ruby CLI with options

CatsExample reads cats information from a file, and provides the option to pass a cat id to return information about a specific cat.

Here is an example:

module CatsExample
  class CLI < Thor
    check_unknown_options!
    package_name "CatsExample"

    def self.exit_on_failure?
      true
    end

    desc "cats", "Displays all cats and their owner's name"
    def cats
      Cat.new.display_cats_summary
    end

    desc "cat", "Displays the summary for a given cat"
    option :cat_id, type: :string, aliases: "-c", required: true
    def cat
      cat_id = options[:cat_id] if options
      Cat.new.display_cat_summary(cat_id)
    end
  end
end

This is how the user can interact with our app through the command-line:

# to get a summary of all cats, run:

bundle exec exe/cats_example cats
# to fetch information about a specific cat with a cat_id, run:

bundle exec exe/cats_example cat -cat 100

# or with the `-c` alias:
bundle exec exe/cats_example cat -c 100

How to test Thor required options

To test Thor required options, this is what we have to do:

  • call the method: :cats
  • add an empty string for the arguments: []
  • add the options inside brackets: {cat_id: "100"}

Here is the RSpec file:

RSpec.describe CatsExample do
  describe "Cat" do
    context "when the cat exists" do
      it "displays the cat summary" do
        path = File.expand_path("test_cat_summary.txt", "../cats_example/spec/fixtures")
        expected_result = File.read(path)

        expect do
          # This is how to test Thor arguments and options <--------
          CatsExample::CLI.new.invoke(:cat, [], {cat_id: "100"}) }
            .to output(
              a_string_including(expected_result)
            ).to_stdout
        end
      end
    end

    # More tests
  end

  describe "Cats" do
    it "lists the cat and the summary of cats" do
      path = File.expand_path("test_cat_summary.txt", "../cats_example/spec/fixtures")
      expected_result = File.read(path)

      expect do
        # This is how to test Thor Ruby invoke call <--------
        CatsExample::CLI.new.invoke(:cats) }.to output(
          a_string_including(expected_result)
        ).to_stdout
      end
    end
  end
end

Testing more Thor commands

This CLI example didn’t provide extra configurations. If yours do, to test it, add it after the arguments and options:

expect do
  # This is how to test Thor Ruby invoke call with arguments, options, and extra_configuration <--------
  CatsExample::CLI.new.invoke(
    :cat, [], {cat_id: "100"}, :extra_configuration => "meow").meow
  ).to output(
    "meow meow 🐱‍🚀"
  ).to_stdout
end

Here is an example from the Thor library.


Now our CLI app handles the scenarios of when a cat exists, and when it doesn’t 🐱‍💻.

I hope this post saves you time and frustration. I couldn’t find examples of how to test required options, so it took me some time to figure it out.

See you in the next post 👋

If you enjoyed this post, share it with your friends!

And don’t forget to subscribe to our newsletter: