Skip to content

Instantly share code, notes, and snippets.

@smoll
Created September 29, 2014 15:19

Revisions

  1. smoll created this gist Sep 29, 2014.
    105 changes: 105 additions & 0 deletions rerun.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,105 @@
    require 'cucumber/formatter/io'

    module Cucumber
    module Formatter
    # The formatter used for <tt>--format rerun</tt>
    #
    # This formatter keeps track of all failing features and print out their location.
    # Example:
    #
    # features/foo.feature:34 features/bar.feature:11:76:81
    #
    # This formatter is used by AutoTest - it will use the output to decide what
    # to run the next time, simply passing the output string on the command line.
    #
    class Rerun
    include Io

    def initialize(runtime, path_or_io, options)
    @io = ensure_io(path_or_io, "rerun")
    @options = options
    @file_names = []
    @file_colon_lines = Hash.new{|h,k| h[k] = []}
    end

    def before_feature(feature_element)
    @lines = []
    @file = feature_element.file
    end

    def after_feature(*)
    unless @lines.empty?
    after_first_time do
    @io.print ' '
    end
    @io.print "#{@file}:#{@lines.join(':')}"
    @io.flush
    end
    end

    def after_features(features)
    @io.close
    end

    def before_feature_element(feature_element)
    @rerun = false
    end

    def after_feature_element(feature_element)
    return if Cucumber::Ast::ScenarioOutline === feature_element
    if @rerun || feature_element.failed? || feature_element.status == :skipped
    @lines << feature_element.line
    end
    end

    def after_table_row(table_row)
    return unless @in_examples and Cucumber::Ast::OutlineTable::ExampleRow === table_row
    unless @header_row
    if table_row.failed? || table_row.status == :skipped
    @rerun = true
    @lines << table_row.line
    end
    end

    @header_row = false if @header_row
    end

    def before_examples(*args)
    @header_row = true
    @in_examples = true
    @current_example_line = nil
    end

    def after_examples(*args)
    @in_examples = false
    if @current_example_line and @rerun
    @lines << @current_example_line
    end
    end

    def before_table_row(table_row)
    return unless @in_examples
    end

    def step_name(keyword, step_match, status, source_indent, background, file_colon_line)
    @rerun = true if [:failed, :pending, :undefined].index(status)
    end

    def scenario_name(keyword, name, file_colon_line, source_indent)
    return unless @in_examples
    if @current_example_line and @rerun
    @lines << @current_example_line
    end
    @rerun = false
    @current_example_line = file_colon_line.split(':')[1]
    end

    private

    def after_first_time
    yield if @not_first_time
    @not_first_time = true
    end
    end
    end
    end
    30 changes: 30 additions & 0 deletions rerun_failed_only.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,30 @@
    require 'cucumber/formatter/rerun'

    # Identical to the rerun formatter Cucumber::Formatter::Rerun that ships with
    # Cucumber v1.3.17, however, I override any methods that log :skipped, :pending,
    # or :undefined steps to the rerun output so we only run FAILED scenarios, not
    # scenarios with SKIPPED, PENDING, or UNDEFINED steps.
    class RerunFailedOnly < Cucumber::Formatter::Rerun
    def after_feature_element(feature_element)
    return if Cucumber::Ast::ScenarioOutline === feature_element # Remove: || feature_element.status == :skipped
    if @rerun || feature_element.failed?
    @lines << feature_element.line
    end
    end

    def after_table_row(table_row)
    return unless @in_examples and Cucumber::Ast::OutlineTable::ExampleRow === table_row
    unless @header_row
    if table_row.failed? # Remove: || table_row.status == :skipped
    @rerun = true
    @lines << table_row.line
    end
    end

    @header_row = false if @header_row
    end

    def step_name(keyword, step_match, status, source_indent, background, file_colon_line)
    @rerun = true if [:failed].index(status) # Remove [:pending, :undefined] from Array
    end
    end