Below I've pasted a ./script/story command I've been using for about a week. It has three modes of operation:
1. ./script/story with no arguments will run all *.story files in the story path 2. ./script/story with a path or glob will run the specified stories 3. If input is passed in via STDIN, it runs that text as a story. This opens up story running via a simple interface (Unix pipes) for integration with other tools. This deals with plain text stories only, and does NOT require an associated .rb runner file for them. Without Ruby runner code for the stories, the problem becomes figuring out what steps to use with a given plain text story file. The solution I put together is quite simple. I declare groups of step matchers in a separate directory, taking care to match the step group name to the file name. When a story file is run, if any steps match a part of the path, they are included. For example, my story in RAILS_ROOT/stories/scenarios/schedule_formatting/weekly.story will attempt to use the step groups "schedule_formatting" and "weekly" if they exist. For cases where that convention is not flexible enough, I added support for including a comment line in the .story file with instructions for which steps it should be run with. I think about this kind of like a she-bang line. So the first line of a .story file could be: # steps: navigations, more_steps And that will override the default behavior. I'm posting this because I hope it might be of immediate use to others using plain text stories right now, and also because I would like to consider possibilities for getting this functionality into RSpec core. WDYT? -- Bryan Helmkamp http://brynary.com -- My blog ----------------------------------------------- #!/usr/bin/env ruby class StoryCommand ROOT_PATH = File.expand_path(File.dirname(__FILE__) + "/..") STORIES_PATH = "#{ROOT_PATH}/stories/scenarios" STEP_MATCHERS_PATH = "#{ROOT_PATH}/stories/steps" HELPER_PATH = "#{ROOT_PATH}/stories/helper" def self.run self.new.run end def run if ARGV.empty? && first_char = using_stdin? setup_and_run_story((first_char + STDIN.read).split("\n")) elsif ARGV.empty? run_story_files(all_story_files) else run_story_files(ARGV) end end def all_story_files Dir["#{STORIES_PATH}/**/*.story"].uniq end def using_stdin? char = nil begin char = STDIN.read_nonblock(1) rescue Errno::EAGAIN return false end return char end def clean_story_paths(paths) paths.map! { |path| File.expand_path(path) } paths.map! { |path| path.gsub(/\.story$/, "") } paths.map! { |path| path.gsub(/#{STORIES_PATH}\//, "") } end def run_story_files(stories) clean_story_paths(stories).each do |story| setup_and_run_story(File.readlines("#{STORIES_PATH}/#{story}.story"), story) end end def setup_and_run_story(lines, story_name = nil) require HELPER_PATH steps = steps_for_story(lines, story_name) steps.reject! { |step| !File.exist?("#{STEP_MATCHERS_PATH}/#{step}.rb") } steps.each { |step| require "#{STEP_MATCHERS_PATH}/#{step}" } run_story(lines, steps) end def steps_for_story(lines, story_name) if lines.first =~ /^# steps: / lines.first.gsub(/^# steps: /, "").split(",").map(&:strip) else story_name.to_s.split("/") end end def run_story(lines, steps) tempfile = Tempfile.new("story") lines.each do |line| tempfile.puts line end tempfile.close with_steps_for(*steps.map(&:to_sym)) do run tempfile.path, :type => RailsStory end end end StoryCommand.run _______________________________________________ rspec-users mailing list [email protected] http://rubyforge.org/mailman/listinfo/rspec-users
