class Launcuke::Runner

Actual clas that will spawn one command process per directory of features collected according to configuration

Attributes

dry_run[RW]

Optional. If true will generate index file but not launch processes. Used for testing.

excluded_dirs[RW]

Optional regexp for name of features directories to exclude.

extra_options[RW]

Array of extra options to pass to the command. Ex: [“-p”, “my_profile”, “–backtrace”]

features_root_path[RW]

Root path to your features directory. Ex: your_project/features

forks_pool_size[RW]

Define the size for the pool of forks. Default is 5

included_only_dirs[RW]

Optional only the features directories to be included

launch_time[RW]

Define last launch time, display in index.html

mode[RW]

Define the launch mode, parallel or sequential

output_dir_name[RW]

Optional name for directory containing the reports. Default to 'cucumber_reports'

output_path[RW]

Optional full path for generated reports. Default to ../{features_root_path}.

reports_path[R]

Full final path where html reports will be generated

require_features_root_option[RW]

Add cucumber –require option load *.rb files under features root path by default unless specified to false.

system_command[RW]

Delegate to a wrapper of system call in order mock/test

Public Class Methods

new(features_root) { |self| ... } click to toggle source
# File lib/launcuke/runner.rb, line 102
def initialize(features_root)
  @features_root_path = features_root
  yield self if block_given?
  @extra_options ||= []
  @mode = @extra_options[2]? "#{@extra_options[2]}" : 'sequential'
  @extra_options.delete_at(2)
  @dry_run = false if dry_run.nil?
  @forks_pool_size ||= 5
  @require_features_root_option = true if require_features_root_option.nil?
  @output_dir_name = "#{@extra_options[1]}" unless output_dir_name
  @output_path = File.expand_path("../reports", output_dir_name) unless output_path
  @excluded_dirs ||= []
  @included_only_dirs ||= []
  @launch_time = Time.now.strftime('%Y-%m-%d %H:%M:%S')
  @reports_path = File.join(output_path, output_dir_name)
  @system_command ||= SystemCommand.new
end

Public Instance Methods

start() click to toggle source
# File lib/launcuke/runner.rb, line 120
def start
  FileUtils.mkdir_p reports_path
  exit_status = launch_process
  collect_results
  reports = ReportsIndex.new(reports_path, features_dirs, @launch_time).generate
  puts "See reports index at #{reports.index_path}" if reports
  system_command.exit(exit_status)
end

Private Instance Methods

collect_results() click to toggle source
# File lib/launcuke/runner.rb, line 173
def collect_results
  features_dirs.each { |features_dir|
    feature_file = File.join(reports_path, "#{features_dir.dir_name}.html")
    File.open(feature_file) { |file|
      content = file.read
      duration_match = content.match(/Finished in\s+<\w+>(.*?)</)
      duration = duration_match ? duration_match.captures.first : ""
      scenarios_match = content.match(/\d+ scenarios? \((.*?)\)/)
      scenarios =  scenarios_match ? scenarios_match.captures.first : ""
      steps_match = content.match(/\d+ steps? \((.*?)\)/)
      steps =  steps_match ? steps_match.captures.first : ""
      features_dir.last_tested_time = Time.now.strftime('%Y-%m-%d %H:%M:%S')
      features_dir.scenarios_results = scenarios
      features_dir.steps_results = steps
      features_dir.duration = duration
    } if File.exists?(feature_file)
  }
end
configured_dir?(path) click to toggle source
# File lib/launcuke/runner.rb, line 207
def configured_dir?(path)
  if included_only_dirs.empty?
    included_dir?(path)
  else
    exact_word_match_expressions = included_only_dirs.map { |dir_name|
      "\\b#{dir_name}\\b"
    }
    path.match(Regexp.new(exact_word_match_expressions.join("|")))
  end
end
features_dirs() click to toggle source
# File lib/launcuke/runner.rb, line 192
def features_dirs
  @features_dirs ||= resolve_features_dirs_name
end
included_dir?(path) click to toggle source
# File lib/launcuke/runner.rb, line 218
def included_dir?(path)
  excluded_dirs.empty? || (not path.match(Regexp.new(excluded_dirs.join("|"))))
end
launch_process() click to toggle source
# File lib/launcuke/runner.rb, line 131
def launch_process
  if dry_run
    0
  else
    case @mode
      when 'sequential'
        p "Running test in sequential"
        results = []
        features_dirs.each { |features_dir|
          report_file_path = File.join(reports_path, "#{features_dir.dir_name}.html")
          feature_full_path = File.join(features_root_path, "#{features_dir.dir_name}")
          main_command = %W[bundle exec cucumber #{feature_full_path}]
          options = %W[--format html --out #{report_file_path}]
          options.concat %W[--require #{features_root_path}] if require_features_root_option
          full_command = main_command + options + extra_options
          result = system_command.run full_command
          puts "Features '#{features_dir.dir_name.upcase}' finished. #{result ? 'SUCCESS' : 'FAILURE'} (pid: #{Process.pid})"
          results.push(result)
        }
      when 'parallel'
        p "Running test in parallel"
        results = features_dirs.forkoff!(:processes => forks_pool_size) { |features_dir|
          report_file_path = File.join(reports_path, "#{features_dir.dir_name}.html")
          feature_full_path = File.join(features_root_path, "#{features_dir.dir_name}")
          main_command = %W[bundle exec cucumber #{feature_full_path}]
          options = %W[--format html --out #{report_file_path}]
          options.concat %W[--require #{features_root_path}] if require_features_root_option
          full_command = main_command + options + extra_options
          result = system_command.run full_command
          puts "Features '#{features_dir.dir_name.upcase}' finished. #{result ? 'SUCCESS' : 'FAILURE'} (pid: #{Process.pid})"
          result
        }
    end
    p results
    global_exit_status = results.inject(0) { |acc, result|
      result ? acc : acc + 1
    }
    puts "Global exit status = #{global_exit_status}"
    global_exit_status
  end
end
resolve_features_dirs_name() click to toggle source
# File lib/launcuke/runner.rb, line 196
def resolve_features_dirs_name
  Dir.glob(File.join(features_root_path, "*", "*.feature")).select{ |path|
    configured_dir?(path)
  }.map { |feature_path|
    dir_name = File.basename(File.dirname(feature_path))
    FeaturesDir.new(dir_name)
  }.uniq { |feature_dir|
    feature_dir.dir_name
  }
end