How to set up Cucumber and RSpec for a non-Rails project

Often times when we use Cucumber and RSpec (and by 'we' I refer to Rails developers, sorry for the narrow focus here), we use them from within a Rails environment.

Here are some instructions on how to set up Cucumber and RSpec for a multi-file Ruby project in a non-Rails environment. Note: if you're here because you want to make your own gem, stop reading and check out jeweler instead. Jeweler will take care of it all for you with one command:

jeweler name_of_gem --cucumber --rspec

If you are not making a gem and just want to bootstrap your own project, here are instructions -- with explanations of what is what. Some may be obvious, but I find that when we are used to using generators it can be easy to overlook what they generate and why. It's the old "the gui made me dumb" syndrome. Therefore, I choose to both err on the side of verbosity in this post and include a link to a bash script that does it for you, at the bottom. For this example, imagine you are going to write a game of Tic Tac Toe in Ruby.

  1. Make sure you have Cucumber, RSpec and their necessary friends installed on your computer:
    sudo gem install gherkin  sudo gem install cucumber  sudo gem install rspec  sudo gem install webrat
    Note: sudo may not be necessary for your set up -- that's a matter of personal preference and your existing setup.
  2. Create project directory. For this example, say you're making a Tic Tac Toe project:
    mkdir tick_tac_toe
  3. Add the following directories and files for Cucumber and RSpec:
    # Cucumber  mkdir tick_tac_toe/features  mkdir tick_tac_toe/features/step_definitions  mkdir tick_tac_toe/features/support  touch tick_tac_toe/features/support/env.rb  # RSpec  mkdir tick_tac_toe/spec  touch tick_tac_toe/spec_helper.rb
  4. Add a lib directory where your own code will go. This is where all of your classes and files will live.
    # Your project code  mkdir tick_tac_toe/lib  touch tick_tac_toe/lib/tick_tac_toe.rb
    Note: some people prefer to have a named directory inside of lib and put all the app files in there. That would look like this:
    mkdir tick_tac_toe/lib  mkdir tick_tac_toe/lib/tick_tac_toe  touch tick_tac_toe/lib/tick_tac_toe.rb
    File organization is a matter of personal preference and I'd say if you're planning on having more than one file, use a nested directory, otherwise just place it directly at the root of lib.
  5. Set up the files so they will recognize each other.
    1. open tick_tac_toe/features/support/env.rb and add the following lines: $: Explanation: the first line adds the lib directory to your load path. The load path is stored in the $: variable. Yes, that is "$:", without the quotes. If you type $: in irb, you'll see an array come back with all of the directories that are looked in by default when you require files. The second line requires spec/expectations, which is what you use in RSpec all the time. Now you can use this behavior in Cucumber. And the third line requires your very own tick_tac_toe.rb file.
    2. Open up spec/spec_helper.rb and add the following lines: $: Explanation: It's that load path again ($:). And you're doing the same thing as before, adding your lib directory to it. Notice the difference between the Cucumber setup and the RSpec setup with regard to this line? spec_helper.rb is only one level below lib ("/../lib") while env.rb is two. It's all just about finding the files where they are in the tree. The second line requires spec, (RSpec). And the third line requires your very own tick_tac_toe.rb file.
  6. That's it! It boils down to this file structure:
    tic_tac_toe--features----step_definitions----support------env.rb--lib----tic_tac_toe.rb--spec----spec_helper.rb----tic_tac_toe_spec.rb
    And then add your *.feature files inside of features/; your step files inside of features/step_definitions; and your *_spec.rb files inside of spec/.
    P.S. I wrote a bash script to automate this for myself and put it on github: feel free to use or improve.