cuke_sniffer 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/cuke_sniffer.rb +11 -2
- data/lib/cuke_sniffer.rb +2 -0
- data/lib/cuke_sniffer/cli.rb +79 -11
- data/lib/cuke_sniffer/feature.rb +20 -10
- data/lib/cuke_sniffer/feature_rules_evaluator.rb +69 -69
- data/lib/cuke_sniffer/report/markup.rhtml +16 -7
- data/lib/cuke_sniffer/rule_config.rb +183 -152
- data/lib/cuke_sniffer/rules_evaluator.rb +4 -1
- data/lib/cuke_sniffer/scenario.rb +32 -18
- data/lib/cuke_sniffer/step_definition.rb +75 -16
- metadata +20 -10
    
        data/bin/cuke_sniffer.rb
    CHANGED
    
    | @@ -6,8 +6,9 @@ Calling CukeSniffer with no arguments will run it against the current directory. | |
| 6 6 | 
             
            Other Options for Running include:
         | 
| 7 7 | 
             
              <feature_file_path>, <step_def_file_path> : Runs CukeSniffer against the
         | 
| 8 8 | 
             
                                                          specified paths.
         | 
| 9 | 
            -
              -o, --out  | 
| 10 | 
            -
                                                           | 
| 9 | 
            +
              -o, --out <type> (name)                   : Where <type> is 'html' or 'xml'.
         | 
| 10 | 
            +
                                                          Runs CukeSniffer then outputs an
         | 
| 11 | 
            +
                                                          html/xml file in the current
         | 
| 11 12 | 
             
                                                          directory (with optional name).
         | 
| 12 13 | 
             
              -h, --help                                : You get this lovely document."
         | 
| 13 14 |  | 
| @@ -41,6 +42,14 @@ if ARGV.include? "--out" or ARGV.include? "-o" | |
| 41 42 | 
             
                    file_name = file_name + ".html" unless file_name =~ /\.html$/
         | 
| 42 43 | 
             
                    cuke_sniffer.output_html(file_name)
         | 
| 43 44 | 
             
                  end
         | 
| 45 | 
            +
                when "xml"
         | 
| 46 | 
            +
                  file_name = ARGV[index + 2]
         | 
| 47 | 
            +
                  if file_name.nil?
         | 
| 48 | 
            +
                    cuke_sniffer.output_xml
         | 
| 49 | 
            +
                  else
         | 
| 50 | 
            +
                    file_name = file_name + ".xml" unless file_name =~ /\.xml$/
         | 
| 51 | 
            +
                    cuke_sniffer.output_xml(file_name)
         | 
| 52 | 
            +
                  end
         | 
| 44 53 | 
             
                else
         | 
| 45 54 | 
             
                  print_results(cuke_sniffer)
         | 
| 46 55 | 
             
              end
         | 
    
        data/lib/cuke_sniffer.rb
    CHANGED
    
    
    
        data/lib/cuke_sniffer/cli.rb
    CHANGED
    
    | @@ -1,10 +1,30 @@ | |
| 1 1 | 
             
            require 'erb'
         | 
| 2 | 
            +
            require 'roxml'
         | 
| 2 3 |  | 
| 3 4 | 
             
            module CukeSniffer
         | 
| 4 5 | 
             
              class CLI
         | 
| 5 6 | 
             
                include CukeSniffer::Constants
         | 
| 7 | 
            +
                include ROXML
         | 
| 6 8 |  | 
| 7 | 
            -
                 | 
| 9 | 
            +
                class SummaryNode
         | 
| 10 | 
            +
                  include ROXML
         | 
| 11 | 
            +
                  xml_accessor :score
         | 
| 12 | 
            +
                  xml_accessor :count
         | 
| 13 | 
            +
                  xml_accessor :average
         | 
| 14 | 
            +
                  xml_accessor :good
         | 
| 15 | 
            +
                  xml_accessor :bad
         | 
| 16 | 
            +
                  xml_accessor :threshold
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                xml_name "cuke_sniffer"
         | 
| 20 | 
            +
                xml_accessor :features_summary, :as => SummaryNode
         | 
| 21 | 
            +
                xml_accessor :scenarios_summary, :as => SummaryNode
         | 
| 22 | 
            +
                xml_accessor :step_definitions_summary, :as => SummaryNode
         | 
| 23 | 
            +
                xml_accessor :improvement_list, :as => {:key => "rule", :value => "total"}, :in =>  "improvement_list", :from => "improvement"
         | 
| 24 | 
            +
                xml_accessor :features, :as => [CukeSniffer::Feature], :in => "features"
         | 
| 25 | 
            +
                xml_accessor :step_definitions, :as => [CukeSniffer::StepDefinition], :in => "step_definitions"
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                attr_accessor :summary, :features_location, :step_definitions_location, :scenarios
         | 
| 8 28 |  | 
| 9 29 | 
             
                def initialize(features_location = Dir.getwd, step_definitions_location = Dir.getwd)
         | 
| 10 30 | 
             
                  @features_location = features_location
         | 
| @@ -50,6 +70,21 @@ module CukeSniffer | |
| 50 70 | 
             
                  catalog_step_calls
         | 
| 51 71 | 
             
                  puts "\nAssessing Score: "
         | 
| 52 72 | 
             
                  assess_score
         | 
| 73 | 
            +
                  @improvement_list = @summary[:improvement_list]
         | 
| 74 | 
            +
                  @features_summary = load_summary_data(@summary[:features])
         | 
| 75 | 
            +
                  @scenarios_summary = load_summary_data(@summary[:scenarios])
         | 
| 76 | 
            +
                  @step_definitions_summary = load_summary_data(@summary[:step_definitions])
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                def load_summary_data(summary_hash)
         | 
| 80 | 
            +
                  summary_node = SummaryNode.new
         | 
| 81 | 
            +
                  summary_node.count = summary_hash[:total]
         | 
| 82 | 
            +
                  summary_node.score = summary_hash[:total_score]
         | 
| 83 | 
            +
                  summary_node.average = summary_hash[:average]
         | 
| 84 | 
            +
                  summary_node.threshold = summary_hash[:threshold]
         | 
| 85 | 
            +
                  summary_node.good = summary_hash[:good]
         | 
| 86 | 
            +
                  summary_node.bad = summary_hash[:bad]
         | 
| 87 | 
            +
                  summary_node
         | 
| 53 88 | 
             
                end
         | 
| 54 89 |  | 
| 55 90 | 
             
                def good?
         | 
| @@ -183,16 +218,27 @@ module CukeSniffer | |
| 183 218 | 
             
                  output
         | 
| 184 219 | 
             
                end
         | 
| 185 220 |  | 
| 221 | 
            +
                def extract_steps_hash(scenario)
         | 
| 222 | 
            +
                  steps_hash = {}
         | 
| 223 | 
            +
                  counter = 1
         | 
| 224 | 
            +
                  scenario.steps.each do |step|
         | 
| 225 | 
            +
                    location = scenario.location.gsub(/:\d*$/, ":#{scenario.start_line + counter}")
         | 
| 226 | 
            +
                    steps_hash[location] = step
         | 
| 227 | 
            +
                    counter += 1
         | 
| 228 | 
            +
                  end
         | 
| 229 | 
            +
                  steps_hash
         | 
| 230 | 
            +
                end
         | 
| 231 | 
            +
             | 
| 186 232 | 
             
                def get_all_steps
         | 
| 187 233 | 
             
                  steps = {}
         | 
| 188 234 | 
             
                  @features.each do |feature|
         | 
| 235 | 
            +
                    unless feature.background.nil?
         | 
| 236 | 
            +
                      background_steps = extract_steps_hash(feature.background)
         | 
| 237 | 
            +
                      background_steps.each_key { |key| steps[key] = background_steps[key] }
         | 
| 238 | 
            +
                    end
         | 
| 189 239 | 
             
                    feature.scenarios.each do |scenario|
         | 
| 190 | 
            -
                       | 
| 191 | 
            -
                       | 
| 192 | 
            -
                        location = scenario.location.gsub(/:\d*$/, ":#{scenario.start_line + counter}")
         | 
| 193 | 
            -
                        steps[location] = step
         | 
| 194 | 
            -
                        counter += 1
         | 
| 195 | 
            -
                      end
         | 
| 240 | 
            +
                      scenario_steps = extract_steps_hash(scenario)
         | 
| 241 | 
            +
                      scenario_steps.each_key { |key| steps[key] = scenario_steps[key] }
         | 
| 196 242 | 
             
                    end
         | 
| 197 243 | 
             
                  end
         | 
| 198 244 | 
             
                  @step_definitions.each do |definition|
         | 
| @@ -215,12 +261,25 @@ module CukeSniffer | |
| 215 261 | 
             
                end
         | 
| 216 262 |  | 
| 217 263 | 
             
                def get_dead_steps
         | 
| 218 | 
            -
                   | 
| 264 | 
            +
                  dead_steps_hash = {}
         | 
| 219 265 | 
             
                  @step_definitions.each do |step_definition|
         | 
| 220 | 
            -
                     | 
| 266 | 
            +
                    location_match = step_definition.location.match(/(?<file>.*).rb:(?<line>\d+)/)
         | 
| 267 | 
            +
                    file_name = location_match[:file]
         | 
| 268 | 
            +
                    regex = step_definition.regex.to_s.match(/\(\?\-mix\:(?<regex>.*)\)/)[:regex]
         | 
| 269 | 
            +
                    dead_steps_hash[file_name] ||= []
         | 
| 270 | 
            +
                    dead_steps_hash[file_name] << "#{location_match[:line]}: /#{regex}/" if step_definition.calls.empty?
         | 
| 221 271 | 
             
                  end
         | 
| 222 | 
            -
             | 
| 223 | 
            -
                   | 
| 272 | 
            +
                  total = 0
         | 
| 273 | 
            +
                  dead_steps_hash.each_key do |key|
         | 
| 274 | 
            +
                    unless dead_steps_hash[key] == []
         | 
| 275 | 
            +
                      total += dead_steps_hash[key].size
         | 
| 276 | 
            +
                      dead_steps_hash[key].sort_by! {|row| row[/^\d+/].to_i}
         | 
| 277 | 
            +
                    else
         | 
| 278 | 
            +
                      dead_steps_hash.delete(key)
         | 
| 279 | 
            +
                    end
         | 
| 280 | 
            +
                  end
         | 
| 281 | 
            +
                  dead_steps_hash[:total] = total
         | 
| 282 | 
            +
                  dead_steps_hash
         | 
| 224 283 | 
             
                end
         | 
| 225 284 |  | 
| 226 285 | 
             
                def extract_markup
         | 
| @@ -242,5 +301,14 @@ module CukeSniffer | |
| 242 301 | 
             
                    f.write(output)
         | 
| 243 302 | 
             
                  end
         | 
| 244 303 | 
             
                end
         | 
| 304 | 
            +
             | 
| 305 | 
            +
                def output_xml(file_name = "cuke_sniffer.xml")
         | 
| 306 | 
            +
                  doc = Nokogiri::XML::Document.new
         | 
| 307 | 
            +
                  doc.root = self.to_xml
         | 
| 308 | 
            +
                  open(file_name, "w") do |file|
         | 
| 309 | 
            +
                    file << doc.serialize
         | 
| 310 | 
            +
                  end
         | 
| 311 | 
            +
             | 
| 312 | 
            +
                end
         | 
| 245 313 | 
             
              end
         | 
| 246 314 | 
             
            end
         | 
    
        data/lib/cuke_sniffer/feature.rb
    CHANGED
    
    | @@ -2,28 +2,38 @@ module CukeSniffer | |
| 2 2 | 
             
              class Feature < FeatureRulesEvaluator
         | 
| 3 3 | 
             
                include CukeSniffer::Constants
         | 
| 4 4 | 
             
                include CukeSniffer::RuleConfig
         | 
| 5 | 
            +
                include ROXML
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                xml_accessor :scenarios, :as => [CukeSniffer::FeatureRulesEvaluator], :in => "scenarios"
         | 
| 5 8 |  | 
| 6 9 | 
             
                SCENARIO_TITLE_REGEX = /#{COMMENT_REGEX}#{SCENARIO_TITLE_STYLES}(?<name>.*)/
         | 
| 7 10 |  | 
| 8 | 
            -
                attr_accessor :background, :scenarios, :scenarios_score | 
| 11 | 
            +
                attr_accessor :background, :scenarios, :scenarios_score,:total_score
         | 
| 9 12 |  | 
| 10 13 | 
             
                def initialize(file_name)
         | 
| 11 14 | 
             
                  super(file_name)
         | 
| 12 15 | 
             
                  @scenarios = []
         | 
| 13 | 
            -
                  @ | 
| 16 | 
            +
                  @RULES_hash = {}
         | 
| 14 17 | 
             
                  @scenarios_score = 0
         | 
| 15 18 | 
             
                  @total_score = 0
         | 
| 16 | 
            -
                   | 
| 17 | 
            -
                   | 
| 19 | 
            +
                  feature_lines = extract_feature_from_file(file_name)
         | 
| 20 | 
            +
                  if feature_lines == []
         | 
| 21 | 
            +
                    store_rule(RULES[:empty_feature])
         | 
| 22 | 
            +
                  else
         | 
| 23 | 
            +
                    split_feature(file_name, feature_lines)
         | 
| 24 | 
            +
                    evaluate_score
         | 
| 25 | 
            +
                  end
         | 
| 18 26 | 
             
                end
         | 
| 19 27 |  | 
| 20 | 
            -
                def  | 
| 28 | 
            +
                def extract_feature_from_file(file_name)
         | 
| 21 29 | 
             
                  feature_lines = []
         | 
| 22 | 
            -
             | 
| 23 30 | 
             
                  feature_file = File.open(file_name)
         | 
| 24 31 | 
             
                  feature_file.each_line { |line| feature_lines << line }
         | 
| 25 32 | 
             
                  feature_file.close
         | 
| 33 | 
            +
                  feature_lines
         | 
| 34 | 
            +
                end
         | 
| 26 35 |  | 
| 36 | 
            +
                def split_feature(file_name, feature_lines)
         | 
| 27 37 | 
             
                  index = 0
         | 
| 28 38 | 
             
                  until feature_lines[index].match /Feature:\s*(?<name>.*)/
         | 
| 29 39 | 
             
                    update_tag_list(feature_lines[index])
         | 
| @@ -87,20 +97,20 @@ module CukeSniffer | |
| 87 97 | 
             
                end
         | 
| 88 98 |  | 
| 89 99 | 
             
                def rule_no_scenarios
         | 
| 90 | 
            -
                  store_rule( | 
| 100 | 
            +
                  store_rule(RULES[:no_scenarios]) if @scenarios.empty?
         | 
| 91 101 | 
             
                end
         | 
| 92 102 |  | 
| 93 103 | 
             
                def rule_too_many_scenarios
         | 
| 94 | 
            -
                  rule =  | 
| 104 | 
            +
                  rule = RULES[:too_many_scenarios]
         | 
| 95 105 | 
             
                  store_rule(rule) if @scenarios.size >= rule[:max]
         | 
| 96 106 | 
             
                end
         | 
| 97 107 |  | 
| 98 108 | 
             
                def rule_background_with_no_scenarios
         | 
| 99 | 
            -
                  store_rule(  | 
| 109 | 
            +
                  store_rule( RULES[:background_with_no_scenarios]) if @scenarios.empty? and !@background.nil?
         | 
| 100 110 | 
             
                end
         | 
| 101 111 |  | 
| 102 112 | 
             
                def rule_background_with_one_scenario
         | 
| 103 | 
            -
                  store_rule( | 
| 113 | 
            +
                  store_rule(RULES[:background_with_one_scenario]) if @scenarios.size == 1 and !@background.nil?
         | 
| 104 114 | 
             
                end
         | 
| 105 115 |  | 
| 106 116 | 
             
              end
         | 
| @@ -1,69 +1,69 @@ | |
| 1 | 
            -
            require 'cuke_sniffer/constants'
         | 
| 2 | 
            -
            require 'cuke_sniffer/rule_config'
         | 
| 3 | 
            -
            require 'cuke_sniffer/rules_evaluator'
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            module CukeSniffer
         | 
| 6 | 
            -
              class FeatureRulesEvaluator < RulesEvaluator
         | 
| 7 | 
            -
                include CukeSniffer::Constants
         | 
| 8 | 
            -
                include CukeSniffer::RuleConfig
         | 
| 9 | 
            -
                
         | 
| 10 | 
            -
                attr_accessor :tags, :name
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                def initialize(location)
         | 
| 13 | 
            -
                  @name = ""
         | 
| 14 | 
            -
                  @tags = []
         | 
| 15 | 
            -
                  super(location)
         | 
| 16 | 
            -
                end
         | 
| 17 | 
            -
             | 
| 18 | 
            -
                def create_name(line, filter)
         | 
| 19 | 
            -
                  line.gsub!(/#{COMMENT_REGEX}#{filter}/, "")
         | 
| 20 | 
            -
                  line.strip!
         | 
| 21 | 
            -
                  @name += " " unless @name.empty? or line.empty?
         | 
| 22 | 
            -
                  @name += line
         | 
| 23 | 
            -
                end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                def update_tag_list(line)
         | 
| 26 | 
            -
                  if TAG_REGEX.match(line) && !is_comment?(line)
         | 
| 27 | 
            -
                    line.scan(TAG_REGEX).each { |tag| @tags << tag[0] }
         | 
| 28 | 
            -
                  else
         | 
| 29 | 
            -
                    @tags << line.strip unless line.empty?
         | 
| 30 | 
            -
                  end
         | 
| 31 | 
            -
                end
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                def evaluate_score
         | 
| 34 | 
            -
                  super
         | 
| 35 | 
            -
                  cls_name = self.class.to_s.gsub('CukeSniffer::', '')
         | 
| 36 | 
            -
                  rule_too_many_tags(cls_name)
         | 
| 37 | 
            -
                  rule_no_description(cls_name)
         | 
| 38 | 
            -
                  rule_numbers_in_name(cls_name)
         | 
| 39 | 
            -
                  rule_long_name(cls_name)
         | 
| 40 | 
            -
                end
         | 
| 41 | 
            -
             | 
| 42 | 
            -
                def rule_too_many_tags(type)
         | 
| 43 | 
            -
                  rule =  | 
| 44 | 
            -
                  store_updated_rule(rule, rule[:phrase].gsub(/{.*}/, type)) if tags.size >= rule[:max]
         | 
| 45 | 
            -
                end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                def rule_no_description(type)
         | 
| 48 | 
            -
                  rule =  | 
| 49 | 
            -
                  store_updated_rule(rule, rule[:phrase].gsub(/{.*}/, type)) if name.empty?
         | 
| 50 | 
            -
                end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                def rule_numbers_in_name(type)
         | 
| 53 | 
            -
                  rule =  | 
| 54 | 
            -
                  store_updated_rule(rule, rule[:phrase].gsub(/{.*}/, type)) if name =~ /\d/
         | 
| 55 | 
            -
                end
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                def rule_long_name(type)
         | 
| 58 | 
            -
                  rule =  | 
| 59 | 
            -
                  store_updated_rule(rule, rule[:phrase].gsub(/{.*}/, type))  if name.size >= rule[:max]
         | 
| 60 | 
            -
                end
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                def == (comparison_object)
         | 
| 63 | 
            -
                  super(comparison_object)
         | 
| 64 | 
            -
                  comparison_object.name == name
         | 
| 65 | 
            -
                  comparison_object.tags == tags
         | 
| 66 | 
            -
                end
         | 
| 67 | 
            -
             | 
| 68 | 
            -
              end
         | 
| 69 | 
            -
            end
         | 
| 1 | 
            +
            require 'cuke_sniffer/constants'
         | 
| 2 | 
            +
            require 'cuke_sniffer/rule_config'
         | 
| 3 | 
            +
            require 'cuke_sniffer/rules_evaluator'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module CukeSniffer
         | 
| 6 | 
            +
              class FeatureRulesEvaluator < RulesEvaluator
         | 
| 7 | 
            +
                include CukeSniffer::Constants
         | 
| 8 | 
            +
                include CukeSniffer::RuleConfig
         | 
| 9 | 
            +
                
         | 
| 10 | 
            +
                attr_accessor :tags, :name
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def initialize(location)
         | 
| 13 | 
            +
                  @name = ""
         | 
| 14 | 
            +
                  @tags = []
         | 
| 15 | 
            +
                  super(location)
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def create_name(line, filter)
         | 
| 19 | 
            +
                  line.gsub!(/#{COMMENT_REGEX}#{filter}/, "")
         | 
| 20 | 
            +
                  line.strip!
         | 
| 21 | 
            +
                  @name += " " unless @name.empty? or line.empty?
         | 
| 22 | 
            +
                  @name += line
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def update_tag_list(line)
         | 
| 26 | 
            +
                  if TAG_REGEX.match(line) && !is_comment?(line)
         | 
| 27 | 
            +
                    line.scan(TAG_REGEX).each { |tag| @tags << tag[0] }
         | 
| 28 | 
            +
                  else
         | 
| 29 | 
            +
                    @tags << line.strip unless line.empty?
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def evaluate_score
         | 
| 34 | 
            +
                  super
         | 
| 35 | 
            +
                  cls_name = self.class.to_s.gsub('CukeSniffer::', '')
         | 
| 36 | 
            +
                  rule_too_many_tags(cls_name)
         | 
| 37 | 
            +
                  rule_no_description(cls_name)
         | 
| 38 | 
            +
                  rule_numbers_in_name(cls_name)
         | 
| 39 | 
            +
                  rule_long_name(cls_name)
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                def rule_too_many_tags(type)
         | 
| 43 | 
            +
                  rule = RULES[:too_many_tags]
         | 
| 44 | 
            +
                  store_updated_rule(rule, rule[:phrase].gsub(/{.*}/, type)) if tags.size >= rule[:max]
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                def rule_no_description(type)
         | 
| 48 | 
            +
                  rule = RULES[:no_description]
         | 
| 49 | 
            +
                  store_updated_rule(rule, rule[:phrase].gsub(/{.*}/, type)) if name.empty?
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def rule_numbers_in_name(type)
         | 
| 53 | 
            +
                  rule = RULES[:numbers_in_description]
         | 
| 54 | 
            +
                  store_updated_rule(rule, rule[:phrase].gsub(/{.*}/, type)) if name =~ /\d/
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def rule_long_name(type)
         | 
| 58 | 
            +
                  rule = RULES[:long_name]
         | 
| 59 | 
            +
                  store_updated_rule(rule, rule[:phrase].gsub(/{.*}/, type))  if name.size >= rule[:max]
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                def == (comparison_object)
         | 
| 63 | 
            +
                  super(comparison_object)
         | 
| 64 | 
            +
                  comparison_object.name == name
         | 
| 65 | 
            +
                  comparison_object.tags == tags
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
              end
         | 
| 69 | 
            +
            end
         | 
| @@ -209,13 +209,22 @@ | |
| 209 209 |  | 
| 210 210 | 
             
            <div class="sections">
         | 
| 211 211 | 
             
              <div name="dead_steps" class="shrink_section" id="dead_steps">
         | 
| 212 | 
            +
                <% dead_steps = cuke_sniffer.get_dead_steps %>
         | 
| 213 | 
            +
                <br>
         | 
| 212 214 | 
             
                <div style="font:bold;padding-left:3%;font:bold;font-size:14pt;">Total Dead
         | 
| 213 | 
            -
                  Steps: <%=  | 
| 214 | 
            -
                <%  | 
| 215 | 
            -
             | 
| 216 | 
            -
             | 
| 217 | 
            -
                       | 
| 218 | 
            -
             | 
| 215 | 
            +
                  Steps: <%= dead_steps[:total] %></div>
         | 
| 216 | 
            +
                <% dead_steps.delete :total%>
         | 
| 217 | 
            +
                <% dead_steps.each_key do |step_file| %>
         | 
| 218 | 
            +
                    <div style="font:bold;padding-left:3%;font-size:14pt;">
         | 
| 219 | 
            +
                      <%= step_file %>
         | 
| 220 | 
            +
                      <br>
         | 
| 221 | 
            +
                      <div style="padding-left:3%;font-size:12pt;">
         | 
| 222 | 
            +
                        <%dead_steps[step_file].each  do |regex|%>
         | 
| 223 | 
            +
                            <%= regex %>
         | 
| 224 | 
            +
                            <br>
         | 
| 225 | 
            +
                        <% end %>
         | 
| 226 | 
            +
                      </div></div>
         | 
| 227 | 
            +
                    <br>
         | 
| 219 228 | 
             
                <% end %>
         | 
| 220 229 | 
             
              </div>
         | 
| 221 230 | 
             
            </div>
         | 
| @@ -320,7 +329,7 @@ | |
| 320 329 | 
             
                <% i=0 %>
         | 
| 321 330 | 
             
                <% cuke_sniffer.step_definitions.each do |step_definition| %>
         | 
| 322 331 | 
             
                    <div style="cursor: hand;" onclick="toggle(this,4)" class="feature <%= i%2==0 ? "even" : "odd" %>">
         | 
| 323 | 
            -
                      <% next if step_definition.score <= 0  | 
| 332 | 
            +
                      <% next if step_definition.score <= 0 or step_definition.calls.empty? %>
         | 
| 324 333 | 
             
                      <div style="float:left;padding:4px;font-weight:bold;color:red;"><%= step_definition.score %></div>
         | 
| 325 334 | 
             
                      <div style="width:55%;padding:4px; float:left;">
         | 
| 326 335 |  | 
| @@ -1,160 +1,191 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 3 1 | 
             
            module CukeSniffer
         | 
| 4 2 | 
             
              module RuleConfig
         | 
| 5 3 |  | 
| 6 | 
            -
                FATAL =  | 
| 7 | 
            -
                ERROR = | 
| 8 | 
            -
                WARNING = 10 | 
| 9 | 
            -
                INFO = | 
| 10 | 
            -
             | 
| 11 | 
            -
                SHARED_RULES = {
         | 
| 12 | 
            -
                  :too_many_tags => {
         | 
| 13 | 
            -
                    :enabled => true,
         | 
| 14 | 
            -
                    :phrase => "{class} has too many tags.",
         | 
| 15 | 
            -
                    :score => INFO,
         | 
| 16 | 
            -
                    :max => 8
         | 
| 17 | 
            -
                  },
         | 
| 18 | 
            -
                  :no_description => {
         | 
| 19 | 
            -
                    :enabled => true,
         | 
| 20 | 
            -
                    :phrase => "{class} has no description.",
         | 
| 21 | 
            -
                    :score => ERROR,
         | 
| 22 | 
            -
                  },
         | 
| 23 | 
            -
                  :numbers_in_description => {
         | 
| 24 | 
            -
                    :enabled => true,
         | 
| 25 | 
            -
                    :phrase => "{class} has numbers in the description.",
         | 
| 26 | 
            -
                    :score => WARNING,
         | 
| 27 | 
            -
                  },
         | 
| 28 | 
            -
                  :long_name => {
         | 
| 29 | 
            -
                    :enabled => true,
         | 
| 30 | 
            -
                    :phrase => "{class} has a long description.",
         | 
| 31 | 
            -
                    :score => INFO,
         | 
| 32 | 
            -
                    :max => 180
         | 
| 33 | 
            -
                  },
         | 
| 34 | 
            -
                  :implementation_word => {
         | 
| 35 | 
            -
                    :enabled => true,
         | 
| 36 | 
            -
                    :phrase => "Implementation word used: {word}.",
         | 
| 37 | 
            -
                    :score => INFO,
         | 
| 38 | 
            -
                    :words => ["page", "site", "url", "button", "drop down", "dropdown", "select list", "click", "text box", "radio button", "check box", "xml", "window", "pop up", "pop-up", "screen"]
         | 
| 39 | 
            -
                  }
         | 
| 40 | 
            -
                }
         | 
| 41 | 
            -
             | 
| 42 | 
            -
                FEATURE_RULES = {
         | 
| 43 | 
            -
                  :background_with_no_scenarios => {
         | 
| 44 | 
            -
                    :enabled => true,
         | 
| 45 | 
            -
                    :phrase => "Feature has a background with no scenarios.",
         | 
| 46 | 
            -
                    :score => WARNING,
         | 
| 47 | 
            -
                  },
         | 
| 48 | 
            -
                  :background_with_one_scenario => {
         | 
| 49 | 
            -
                    :enabled => true,
         | 
| 50 | 
            -
                    :phrase => "Feature has a background with one scenario.",
         | 
| 51 | 
            -
                    :score => WARNING,
         | 
| 52 | 
            -
                  },
         | 
| 53 | 
            -
                  :no_scenarios => {
         | 
| 54 | 
            -
                    :enabled => true,
         | 
| 55 | 
            -
                    :phrase => "Feature with no scenarios.",
         | 
| 56 | 
            -
                    :score => ERROR,
         | 
| 57 | 
            -
                  },
         | 
| 58 | 
            -
                  :too_many_scenarios => {
         | 
| 59 | 
            -
                    :enabled => true,
         | 
| 60 | 
            -
                    :phrase => "Feature with too many scenarios.",
         | 
| 61 | 
            -
                    :score => INFO,
         | 
| 62 | 
            -
                    :max => 10,
         | 
| 63 | 
            -
                  },
         | 
| 64 | 
            -
                }
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                SCENARIO_RULES = {
         | 
| 67 | 
            -
                  :too_many_steps => {
         | 
| 68 | 
            -
                    :enabled => true,
         | 
| 69 | 
            -
                    :phrase => "Scenario with too many steps.",
         | 
| 70 | 
            -
                    :score => WARNING,
         | 
| 71 | 
            -
                    :max => 7,
         | 
| 72 | 
            -
                  },
         | 
| 73 | 
            -
                  :out_of_order_steps  => {
         | 
| 74 | 
            -
                    :enabled => true,
         | 
| 75 | 
            -
                    :phrase => "Scenario steps out of Given/When/Then order.",
         | 
| 76 | 
            -
                    :score => WARNING,
         | 
| 77 | 
            -
                  },
         | 
| 78 | 
            -
                  :invalid_first_step  => {
         | 
| 79 | 
            -
                    :enabled => true,
         | 
| 80 | 
            -
                    :phrase => "Invalid first step. Began with And/But.",
         | 
| 81 | 
            -
                    :score => WARNING,
         | 
| 82 | 
            -
                  },
         | 
| 83 | 
            -
                  :asterisk_step => {
         | 
| 84 | 
            -
                    :enabled => true,
         | 
| 85 | 
            -
                    :phrase => "Step includes a * instead of Given/When/Then/And/But.",
         | 
| 86 | 
            -
                    :score => WARNING,
         | 
| 87 | 
            -
                  },
         | 
| 88 | 
            -
                  :commented_step => {
         | 
| 89 | 
            -
                    :enabled => true,
         | 
| 90 | 
            -
                    :phrase => "Commented step.",
         | 
| 91 | 
            -
                    :score => ERROR,
         | 
| 92 | 
            -
                  },
         | 
| 93 | 
            -
                  :commented_example => {
         | 
| 94 | 
            -
                    :enabled => true,
         | 
| 95 | 
            -
                    :phrase => "Commented example.",
         | 
| 96 | 
            -
                    :score => ERROR,
         | 
| 97 | 
            -
                  },
         | 
| 98 | 
            -
                  :no_examples => {
         | 
| 99 | 
            -
                    :enabled => true,
         | 
| 100 | 
            -
                    :phrase => "Scenario Outline with no examples.",
         | 
| 101 | 
            -
                    :score => FATAL,
         | 
| 102 | 
            -
                  },
         | 
| 103 | 
            -
                  :one_example => {
         | 
| 104 | 
            -
                    :enabled => true,
         | 
| 105 | 
            -
                    :phrase => "Scenario Outline with only one example.",
         | 
| 106 | 
            -
                    :score => WARNING,
         | 
| 107 | 
            -
                  },
         | 
| 108 | 
            -
                  :no_examples_table => {
         | 
| 109 | 
            -
                    :enabled => true,
         | 
| 110 | 
            -
                    :phrase => "Scenario Outline with no examples table.",
         | 
| 111 | 
            -
                    :score => FATAL,
         | 
| 112 | 
            -
                  },
         | 
| 113 | 
            -
                  :too_many_examples => {
         | 
| 114 | 
            -
                    :enabled => true,
         | 
| 115 | 
            -
                    :phrase => "Scenario Outline with too many examples.",
         | 
| 116 | 
            -
                    :score => WARNING,
         | 
| 117 | 
            -
                    :max => 10
         | 
| 118 | 
            -
                  },
         | 
| 119 | 
            -
                  :date_used => {
         | 
| 120 | 
            -
                    :enabled => true,
         | 
| 121 | 
            -
                    :phrase => "Date used.",
         | 
| 122 | 
            -
                    :score => INFO,
         | 
| 123 | 
            -
                  },
         | 
| 124 | 
            -
                  :no_steps => {
         | 
| 125 | 
            -
                    :enabled => true,
         | 
| 126 | 
            -
                    :phrase => "No steps in Scenario.",
         | 
| 127 | 
            -
                    :score => ERROR,
         | 
| 128 | 
            -
                  },
         | 
| 129 | 
            -
                }
         | 
| 4 | 
            +
                FATAL =   100 #will prevent suite from executing properly
         | 
| 5 | 
            +
                ERROR =   25  #will cause problem with debugging
         | 
| 6 | 
            +
                WARNING = 10  #readibility/misuse of cucumber
         | 
| 7 | 
            +
                INFO =    1   #Small improvements that can be made
         | 
| 130 8 |  | 
| 131 | 
            -
                 | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
                    : | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
             | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 153 | 
            -
             | 
| 154 | 
            -
                    : | 
| 155 | 
            -
             | 
| 9 | 
            +
                RULES = {
         | 
| 10 | 
            +
                    :too_many_tags => {
         | 
| 11 | 
            +
                        :enabled => true,
         | 
| 12 | 
            +
                        :phrase => "{class} has too many tags.",
         | 
| 13 | 
            +
                        :score => INFO,
         | 
| 14 | 
            +
                        :max => 8
         | 
| 15 | 
            +
                    },
         | 
| 16 | 
            +
                    :no_description => {
         | 
| 17 | 
            +
                        :enabled => true,
         | 
| 18 | 
            +
                        :phrase => "{class} has no description.",
         | 
| 19 | 
            +
                        :score => ERROR,
         | 
| 20 | 
            +
                    },
         | 
| 21 | 
            +
                    :numbers_in_description => {
         | 
| 22 | 
            +
                        :enabled => true,
         | 
| 23 | 
            +
                        :phrase => "{class} has numbers in the description.",
         | 
| 24 | 
            +
                        :score => WARNING,
         | 
| 25 | 
            +
                    },
         | 
| 26 | 
            +
                    :long_name => {
         | 
| 27 | 
            +
                        :enabled => true,
         | 
| 28 | 
            +
                        :phrase => "{class} has a long description.",
         | 
| 29 | 
            +
                        :score => INFO,
         | 
| 30 | 
            +
                        :max => 180
         | 
| 31 | 
            +
                    },
         | 
| 32 | 
            +
                    :implementation_word => {
         | 
| 33 | 
            +
                        :enabled => true,
         | 
| 34 | 
            +
                        :phrase => "Implementation word used: {word}.",
         | 
| 35 | 
            +
                        :score => INFO,
         | 
| 36 | 
            +
                        :words => ["page", "site", "url", "button", "drop down", "dropdown", "select list", "click", "text box", "radio button", "check box", "xml", "window", "pop up", "pop-up", "screen"]
         | 
| 37 | 
            +
                    },
         | 
| 38 | 
            +
                    :empty_feature => {
         | 
| 39 | 
            +
                        :enabled => true,
         | 
| 40 | 
            +
                        :phrase => "Feature file has no content.",
         | 
| 41 | 
            +
                        :score => WARNING,
         | 
| 42 | 
            +
                    },
         | 
| 43 | 
            +
                    :background_with_no_scenarios => {
         | 
| 44 | 
            +
                        :enabled => true,
         | 
| 45 | 
            +
                        :phrase => "Feature has a background with no scenarios.",
         | 
| 46 | 
            +
                        :score => WARNING,
         | 
| 47 | 
            +
                    },
         | 
| 48 | 
            +
                    :background_with_one_scenario => {
         | 
| 49 | 
            +
                        :enabled => true,
         | 
| 50 | 
            +
                        :phrase => "Feature has a background with one scenario.",
         | 
| 51 | 
            +
                        :score => WARNING,
         | 
| 52 | 
            +
                    },
         | 
| 53 | 
            +
                    :no_scenarios => {
         | 
| 54 | 
            +
                        :enabled => true,
         | 
| 55 | 
            +
                        :phrase => "Feature with no scenarios.",
         | 
| 56 | 
            +
                        :score => ERROR,
         | 
| 57 | 
            +
                    },
         | 
| 58 | 
            +
                    :too_many_scenarios => {
         | 
| 59 | 
            +
                        :enabled => true,
         | 
| 60 | 
            +
                        :phrase => "Feature with too many scenarios.",
         | 
| 61 | 
            +
                        :score => INFO,
         | 
| 62 | 
            +
                        :max => 10,
         | 
| 63 | 
            +
                    },
         | 
| 64 | 
            +
                    :too_many_steps => {
         | 
| 65 | 
            +
                        :enabled => true,
         | 
| 66 | 
            +
                        :phrase => "Scenario with too many steps.",
         | 
| 67 | 
            +
                        :score => WARNING,
         | 
| 68 | 
            +
                        :max => 7,
         | 
| 69 | 
            +
                    },
         | 
| 70 | 
            +
                    :out_of_order_steps => {
         | 
| 71 | 
            +
                        :enabled => true,
         | 
| 72 | 
            +
                        :phrase => "Scenario steps out of Given/When/Then order.",
         | 
| 73 | 
            +
                        :score => WARNING,
         | 
| 74 | 
            +
                    },
         | 
| 75 | 
            +
                    :invalid_first_step => {
         | 
| 76 | 
            +
                        :enabled => true,
         | 
| 77 | 
            +
                        :phrase => "Invalid first step. Began with And/But.",
         | 
| 78 | 
            +
                        :score => WARNING,
         | 
| 79 | 
            +
                    },
         | 
| 80 | 
            +
                    :asterisk_step => {
         | 
| 81 | 
            +
                        :enabled => true,
         | 
| 82 | 
            +
                        :phrase => "Step includes a * instead of Given/When/Then/And/But.",
         | 
| 83 | 
            +
                        :score => WARNING,
         | 
| 84 | 
            +
                    },
         | 
| 85 | 
            +
                    :commented_step => {
         | 
| 86 | 
            +
                        :enabled => true,
         | 
| 87 | 
            +
                        :phrase => "Commented step.",
         | 
| 88 | 
            +
                        :score => ERROR,
         | 
| 89 | 
            +
                    },
         | 
| 90 | 
            +
                    :commented_example => {
         | 
| 91 | 
            +
                        :enabled => true,
         | 
| 92 | 
            +
                        :phrase => "Commented example.",
         | 
| 93 | 
            +
                        :score => ERROR,
         | 
| 94 | 
            +
                    },
         | 
| 95 | 
            +
                    :no_examples => {
         | 
| 96 | 
            +
                        :enabled => true,
         | 
| 97 | 
            +
                        :phrase => "Scenario Outline with no examples.",
         | 
| 98 | 
            +
                        :score => FATAL,
         | 
| 99 | 
            +
                    },
         | 
| 100 | 
            +
                    :one_example => {
         | 
| 101 | 
            +
                        :enabled => true,
         | 
| 102 | 
            +
                        :phrase => "Scenario Outline with only one example.",
         | 
| 103 | 
            +
                        :score => WARNING,
         | 
| 104 | 
            +
                    },
         | 
| 105 | 
            +
                    :no_examples_table => {
         | 
| 106 | 
            +
                        :enabled => true,
         | 
| 107 | 
            +
                        :phrase => "Scenario Outline with no examples table.",
         | 
| 108 | 
            +
                        :score => FATAL,
         | 
| 109 | 
            +
                    },
         | 
| 110 | 
            +
                    :too_many_examples => {
         | 
| 111 | 
            +
                        :enabled => true,
         | 
| 112 | 
            +
                        :phrase => "Scenario Outline with too many examples.",
         | 
| 113 | 
            +
                        :score => WARNING,
         | 
| 114 | 
            +
                        :max => 10
         | 
| 115 | 
            +
                    },
         | 
| 116 | 
            +
                    :date_used => {
         | 
| 117 | 
            +
                        :enabled => true,
         | 
| 118 | 
            +
                        :phrase => "Date used.",
         | 
| 119 | 
            +
                        :score => INFO,
         | 
| 120 | 
            +
                    },
         | 
| 121 | 
            +
                    :no_steps => {
         | 
| 122 | 
            +
                        :enabled => true,
         | 
| 123 | 
            +
                        :phrase => "No steps in Scenario.",
         | 
| 124 | 
            +
                        :score => ERROR,
         | 
| 125 | 
            +
                    },
         | 
| 126 | 
            +
                    :one_word_step => {
         | 
| 127 | 
            +
                        :enabled => true,
         | 
| 128 | 
            +
                        :phrase => "Step that is only one word long.",
         | 
| 129 | 
            +
                        :score => ERROR,
         | 
| 130 | 
            +
                    },
         | 
| 131 | 
            +
                    :multiple_given_when_then => {
         | 
| 132 | 
            +
                        :enabled => true,
         | 
| 133 | 
            +
                        :phrase => "Given/When/Then used multiple times in the same scenario.",
         | 
| 134 | 
            +
                        :score => WARNING,
         | 
| 135 | 
            +
                    },
         | 
| 136 | 
            +
                    :no_code => {
         | 
| 137 | 
            +
                        :enabled => true,
         | 
| 138 | 
            +
                        :phrase => "No code in Step Definition.",
         | 
| 139 | 
            +
                        :score => ERROR,
         | 
| 140 | 
            +
                    },
         | 
| 141 | 
            +
                    :too_many_parameters => {
         | 
| 142 | 
            +
                        :enabled => true,
         | 
| 143 | 
            +
                        :phrase => "Too many parameters in Step Definition.",
         | 
| 144 | 
            +
                        :score => WARNING,
         | 
| 145 | 
            +
                        :max => 4
         | 
| 146 | 
            +
                    },
         | 
| 147 | 
            +
                    :nested_step => {
         | 
| 148 | 
            +
                        :enabled => true,
         | 
| 149 | 
            +
                        :phrase => "Nested step call.",
         | 
| 150 | 
            +
                        :score => INFO,
         | 
| 151 | 
            +
                    },
         | 
| 152 | 
            +
                    :recursive_nested_step => {
         | 
| 153 | 
            +
                        :enabled => true,
         | 
| 154 | 
            +
                        :phrase => "Recursive nested step call.",
         | 
| 155 | 
            +
                        :score => FATAL,
         | 
| 156 | 
            +
                    },
         | 
| 157 | 
            +
                    :commented_code => {
         | 
| 158 | 
            +
                        :enabled => true,
         | 
| 159 | 
            +
                        :phrase => "Commented code in Step Definition.",
         | 
| 160 | 
            +
                        :score => INFO,
         | 
| 161 | 
            +
                    },
         | 
| 162 | 
            +
                    :lazy_debugging => {
         | 
| 163 | 
            +
                        :enabled => true,
         | 
| 164 | 
            +
                        :phrase => "Lazy Debugging through puts, p, or print",
         | 
| 165 | 
            +
                        :score => WARNING,
         | 
| 166 | 
            +
                    },
         | 
| 167 | 
            +
                    :pending => {
         | 
| 168 | 
            +
                        :enabled => true,
         | 
| 169 | 
            +
                        :phrase => "Pending step definition. Implement or remove.",
         | 
| 170 | 
            +
                        :score => WARNING,
         | 
| 171 | 
            +
                    },
         | 
| 172 | 
            +
                    :small_sleep => {
         | 
| 173 | 
            +
                        :enabled => true,
         | 
| 174 | 
            +
                        :phrase => "Small sleeps used. Use a wait_until like method.",
         | 
| 175 | 
            +
                        :score => INFO,
         | 
| 176 | 
            +
                        :max => 2
         | 
| 177 | 
            +
                    },
         | 
| 178 | 
            +
                    :large_sleep => {
         | 
| 179 | 
            +
                    :enabled => true,
         | 
| 180 | 
            +
                    :phrase => "Large sleeps used. Use a wait_until like method.",
         | 
| 156 181 | 
             
                    :score => INFO,
         | 
| 157 | 
            -
             | 
| 182 | 
            +
                    :min => 2
         | 
| 183 | 
            +
                    },
         | 
| 184 | 
            +
                    :todo => {
         | 
| 185 | 
            +
                        :enabled => true,
         | 
| 186 | 
            +
                        :phrase => "Todo found. Resolve it.",
         | 
| 187 | 
            +
                        :score => INFO,
         | 
| 188 | 
            +
                    },
         | 
| 158 189 | 
             
                }
         | 
| 159 190 |  | 
| 160 191 | 
             
              end
         | 
| @@ -1,6 +1,9 @@ | |
| 1 | 
            +
            require 'roxml'
         | 
| 1 2 | 
             
            module CukeSniffer
         | 
| 2 3 | 
             
              class RulesEvaluator
         | 
| 3 | 
            -
                 | 
| 4 | 
            +
                include ROXML
         | 
| 5 | 
            +
                xml_accessor :score, :location
         | 
| 6 | 
            +
                xml_accessor :rules_hash, :as => {:key => "phrase", :value => "score"}, :in => "rules", :from => "rule"
         | 
| 4 7 |  | 
| 5 8 | 
             
                def initialize(location)
         | 
| 6 9 | 
             
                  @location = location
         | 
| @@ -1,12 +1,13 @@ | |
| 1 | 
            -
            require 'cuke_sniffer/constants'
         | 
| 2 | 
            -
            require 'cuke_sniffer/rule_config'
         | 
| 3 | 
            -
             | 
| 4 1 | 
             
            module CukeSniffer
         | 
| 5 2 | 
             
              class Scenario < FeatureRulesEvaluator
         | 
| 6 3 | 
             
                include CukeSniffer::Constants
         | 
| 7 4 | 
             
                include CukeSniffer::RuleConfig
         | 
| 8 | 
            -
             | 
| 9 | 
            -
                 | 
| 5 | 
            +
             | 
| 6 | 
            +
                xml_accessor :start_line
         | 
| 7 | 
            +
                xml_accessor :steps, :as => [], :in => "steps"
         | 
| 8 | 
            +
                xml_accessor :examples_table, :as => [], :in => "examples"
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                attr_accessor :type, :inline_tables
         | 
| 10 11 |  | 
| 11 12 | 
             
                def initialize(location, scenario)
         | 
| 12 13 | 
             
                  super(location)
         | 
| @@ -81,9 +82,22 @@ module CukeSniffer | |
| 81 82 | 
             
                  rule_commented_step
         | 
| 82 83 | 
             
                  rule_implementation_words
         | 
| 83 84 | 
             
                  rule_date_used_in_step
         | 
| 85 | 
            +
                  rule_one_word_step
         | 
| 86 | 
            +
                  rule_multiple_given_when_then
         | 
| 84 87 | 
             
                  evaluate_outline_scores if type == "Scenario Outline"
         | 
| 85 88 | 
             
                end
         | 
| 86 89 |  | 
| 90 | 
            +
                def rule_multiple_given_when_then
         | 
| 91 | 
            +
                  step_order = get_step_order
         | 
| 92 | 
            +
                  %w(Given When Then).each { |type| store_rule(RULES[:multiple_given_when_then]) if step_order.count(type) > 1 }
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                def rule_one_word_step
         | 
| 96 | 
            +
                  @steps.each do |step|
         | 
| 97 | 
            +
                    store_rule(RULES[:one_word_step]) if step.split.count == 2
         | 
| 98 | 
            +
                  end
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
             | 
| 87 101 | 
             
                def evaluate_outline_scores
         | 
| 88 102 | 
             
                  rule_no_examples_table
         | 
| 89 103 | 
             
                  rule_no_examples
         | 
| @@ -93,37 +107,37 @@ module CukeSniffer | |
| 93 107 | 
             
                end
         | 
| 94 108 |  | 
| 95 109 | 
             
                def rule_empty_scenario
         | 
| 96 | 
            -
                  store_rule( | 
| 110 | 
            +
                  store_rule(RULES[:no_steps]) if @steps.empty?
         | 
| 97 111 | 
             
                end
         | 
| 98 112 |  | 
| 99 113 | 
             
                def rule_too_many_steps
         | 
| 100 | 
            -
                  rule =  | 
| 114 | 
            +
                  rule = RULES[:too_many_steps]
         | 
| 101 115 | 
             
                  store_rule(rule) if @steps.size >= rule[:max]
         | 
| 102 116 | 
             
                end
         | 
| 103 117 |  | 
| 104 118 | 
             
                def rule_step_order
         | 
| 105 119 | 
             
                  step_order = get_step_order.uniq
         | 
| 106 120 | 
             
                  %w(But * And).each { |type| step_order.delete(type) }
         | 
| 107 | 
            -
                  store_rule( | 
| 121 | 
            +
                  store_rule(RULES[:out_of_order_steps]) unless step_order == %w(Given When Then) or step_order == %w(When Then)
         | 
| 108 122 | 
             
                end
         | 
| 109 123 |  | 
| 110 124 | 
             
                def rule_invalid_first_step
         | 
| 111 125 | 
             
                  first_step = get_step_order.first
         | 
| 112 | 
            -
                  store_rule( | 
| 126 | 
            +
                  store_rule(RULES[:invalid_first_step]) if %w(And But).include?(first_step)
         | 
| 113 127 | 
             
                end
         | 
| 114 128 |  | 
| 115 129 | 
             
                def rule_asterisk_step
         | 
| 116 | 
            -
                  get_step_order.count('*').times { store_rule( | 
| 130 | 
            +
                  get_step_order.count('*').times { store_rule(RULES[:asterisk_step]) }
         | 
| 117 131 | 
             
                end
         | 
| 118 132 |  | 
| 119 133 | 
             
                def rule_commented_step
         | 
| 120 134 | 
             
                  @steps.each do |step|
         | 
| 121 | 
            -
                    store_rule( | 
| 135 | 
            +
                    store_rule(RULES[:commented_step]) if is_comment?(step)
         | 
| 122 136 | 
             
                  end
         | 
| 123 137 | 
             
                end
         | 
| 124 138 |  | 
| 125 139 | 
             
                def rule_implementation_words
         | 
| 126 | 
            -
                  rule =  | 
| 140 | 
            +
                  rule = RULES[:implementation_word]
         | 
| 127 141 | 
             
                  @steps.each do |step|
         | 
| 128 142 | 
             
                    next if is_comment?(step)
         | 
| 129 143 | 
             
                    rule[:words].each do |word|
         | 
| @@ -134,29 +148,29 @@ module CukeSniffer | |
| 134 148 |  | 
| 135 149 | 
             
                def rule_date_used_in_step
         | 
| 136 150 | 
             
                  @steps.each do |step|
         | 
| 137 | 
            -
                    store_rule( | 
| 151 | 
            +
                    store_rule(RULES[:date_used]) if step =~ DATE_REGEX
         | 
| 138 152 | 
             
                  end
         | 
| 139 153 | 
             
                end
         | 
| 140 154 |  | 
| 141 155 | 
             
                def rule_no_examples_table
         | 
| 142 | 
            -
                  store_rule( | 
| 156 | 
            +
                  store_rule(RULES[:no_examples_table]) if @examples_table.empty?
         | 
| 143 157 | 
             
                end
         | 
| 144 158 |  | 
| 145 159 | 
             
                def rule_no_examples
         | 
| 146 | 
            -
                  store_rule( | 
| 160 | 
            +
                  store_rule(RULES[:no_examples]) if @examples_table.size == 1
         | 
| 147 161 | 
             
                end
         | 
| 148 162 |  | 
| 149 163 | 
             
                def rule_one_example
         | 
| 150 | 
            -
                  store_rule( | 
| 164 | 
            +
                  store_rule(RULES[:one_example]) if @examples_table.size == 2 and !is_comment?(@examples_table[1])
         | 
| 151 165 | 
             
                end
         | 
| 152 166 |  | 
| 153 167 | 
             
                def rule_too_many_examples
         | 
| 154 | 
            -
                  store_rule( | 
| 168 | 
            +
                  store_rule(RULES[:too_many_examples]) if (@examples_table.size - 1) >= 8
         | 
| 155 169 | 
             
                end
         | 
| 156 170 |  | 
| 157 171 | 
             
                def rule_commented_example
         | 
| 158 172 | 
             
                  @examples_table.each do |example|
         | 
| 159 | 
            -
                    store_rule( | 
| 173 | 
            +
                    store_rule(RULES[:commented_example]) if is_comment?(example)
         | 
| 160 174 | 
             
                  end
         | 
| 161 175 | 
             
                end
         | 
| 162 176 |  | 
| @@ -1,15 +1,22 @@ | |
| 1 | 
            +
            require 'roxml'
         | 
| 1 2 | 
             
            module CukeSniffer
         | 
| 2 3 | 
             
              class StepDefinition < RulesEvaluator
         | 
| 3 4 | 
             
                include CukeSniffer::Constants
         | 
| 4 5 | 
             
                include CukeSniffer::RuleConfig
         | 
| 5 6 |  | 
| 7 | 
            +
                xml_accessor :start_line
         | 
| 8 | 
            +
                xml_accessor :regex
         | 
| 9 | 
            +
                xml_accessor :parameters, :as => [], :in => "parameters"
         | 
| 10 | 
            +
                xml_accessor :nested_steps, :as => {:key => 'location', :value => 'call'}, :in => "nested_steps"
         | 
| 11 | 
            +
                xml_accessor :calls, :as => {:key => 'location', :value => 'call'}, :in => "calls"
         | 
| 12 | 
            +
                xml_accessor :code, :as => [], :in => "code"
         | 
| 13 | 
            +
             | 
| 6 14 | 
             
                SIMPLE_NESTED_STEP_REGEX = /steps\s"#{STEP_STYLES}(?<step_string>.*)"$/
         | 
| 7 | 
            -
                 | 
| 8 | 
            -
                 | 
| 15 | 
            +
                START_COMPLEX_STEP_REGEX = /^steps\s%(q|Q)?\{\s*/
         | 
| 16 | 
            +
                SAME_LINE_COMPLEX_STEP_REGEX = /#{START_COMPLEX_STEP_REGEX}#{STEP_STYLES}(?<step_string>.*)}$/
         | 
| 9 17 | 
             
                END_COMPLEX_STEP_REGEX = /}$/
         | 
| 10 | 
            -
                START_COMPLEX_WITH_STEP_REGEX = /steps\s%Q?\{#{STEP_STYLES}(?<step_string>.*)$/
         | 
| 18 | 
            +
                START_COMPLEX_WITH_STEP_REGEX = /steps\s%(q|Q)?\{#{STEP_STYLES}(?<step_string>.*)$/
         | 
| 11 19 | 
             
                END_COMPLEX_WITH_STEP_REGEX = /#{STEP_STYLES}(?<step_string>.*)}$/
         | 
| 12 | 
            -
                attr_accessor :start_line, :regex, :code, :parameters, :calls, :nested_steps
         | 
| 13 20 |  | 
| 14 21 | 
             
                def initialize(location, raw_code)
         | 
| 15 22 | 
             
                  super(location)
         | 
| @@ -17,7 +24,7 @@ module CukeSniffer | |
| 17 24 | 
             
                  @parameters = []
         | 
| 18 25 | 
             
                  @calls = {}
         | 
| 19 26 | 
             
                  @nested_steps = {}
         | 
| 20 | 
            -
                  @start_line = location.match(/:(?<line>\d*) | 
| 27 | 
            +
                  @start_line = location.match(/:(?<line>\d*)$/)[:line].to_i
         | 
| 21 28 |  | 
| 22 29 | 
             
                  end_match_index = (raw_code.size - 1) - raw_code.reverse.index("end")
         | 
| 23 30 | 
             
                  @code = raw_code[1...end_match_index]
         | 
| @@ -46,13 +53,26 @@ module CukeSniffer | |
| 46 53 | 
             
                    case line
         | 
| 47 54 | 
             
                      when SIMPLE_NESTED_STEP_REGEX
         | 
| 48 55 | 
             
                        regex = SIMPLE_NESTED_STEP_REGEX
         | 
| 56 | 
            +
                      when START_COMPLEX_WITH_STEP_REGEX
         | 
| 57 | 
            +
                        if line =~ /\}$/
         | 
| 58 | 
            +
                          if line.include?('#{')
         | 
| 59 | 
            +
                            reversed_line = line.reverse
         | 
| 60 | 
            +
                            last_capture = reversed_line[0..reversed_line.index('#')].reverse
         | 
| 61 | 
            +
                            if last_capture =~ /{.*}$/
         | 
| 62 | 
            +
                              multi_line_step_flag = true
         | 
| 63 | 
            +
                              regex = START_COMPLEX_WITH_STEP_REGEX
         | 
| 64 | 
            +
                            else
         | 
| 65 | 
            +
                              regex = SAME_LINE_COMPLEX_STEP_REGEX
         | 
| 66 | 
            +
                            end
         | 
| 67 | 
            +
                          else
         | 
| 68 | 
            +
                            regex = SAME_LINE_COMPLEX_STEP_REGEX
         | 
| 69 | 
            +
                          end
         | 
| 70 | 
            +
                        else
         | 
| 71 | 
            +
                          multi_line_step_flag = true
         | 
| 72 | 
            +
                          regex = START_COMPLEX_WITH_STEP_REGEX
         | 
| 73 | 
            +
                        end
         | 
| 49 74 | 
             
                      when SAME_LINE_COMPLEX_STEP_REGEX
         | 
| 50 75 | 
             
                        regex = SAME_LINE_COMPLEX_STEP_REGEX
         | 
| 51 | 
            -
                      when START_COMPLEX_WITH_STEP_REGEX
         | 
| 52 | 
            -
                        multi_line_step_flag = true
         | 
| 53 | 
            -
                        regex = START_COMPLEX_WITH_STEP_REGEX
         | 
| 54 | 
            -
                      when START_COMPLEX_STEP_REGEX
         | 
| 55 | 
            -
                        multi_line_step_flag = true
         | 
| 56 76 | 
             
                      when END_COMPLEX_WITH_STEP_REGEX
         | 
| 57 77 | 
             
                        if line =~ /[#]{.*}$/ && multi_line_step_flag
         | 
| 58 78 | 
             
                          regex = STEP_REGEX
         | 
| @@ -60,6 +80,8 @@ module CukeSniffer | |
| 60 80 | 
             
                          regex = END_COMPLEX_WITH_STEP_REGEX
         | 
| 61 81 | 
             
                          multi_line_step_flag = false
         | 
| 62 82 | 
             
                        end
         | 
| 83 | 
            +
                      when START_COMPLEX_STEP_REGEX
         | 
| 84 | 
            +
                        multi_line_step_flag = true
         | 
| 63 85 | 
             
                      when STEP_REGEX
         | 
| 64 86 | 
             
                        regex = STEP_REGEX if multi_line_step_flag
         | 
| 65 87 | 
             
                      when END_COMPLEX_STEP_REGEX
         | 
| @@ -89,7 +111,7 @@ module CukeSniffer | |
| 89 111 |  | 
| 90 112 | 
             
                def condensed_call_list
         | 
| 91 113 | 
             
                  condensed_list = {}
         | 
| 92 | 
            -
                  @calls.each{|call, step_string|
         | 
| 114 | 
            +
                  @calls.each { |call, step_string|
         | 
| 93 115 | 
             
                    condensed_list[step_string] ||= []
         | 
| 94 116 | 
             
                    condensed_list[step_string] << call
         | 
| 95 117 | 
             
                  }
         | 
| @@ -112,30 +134,67 @@ module CukeSniffer | |
| 112 134 | 
             
                  rule_nested_steps
         | 
| 113 135 | 
             
                  rule_recursive_nested_step
         | 
| 114 136 | 
             
                  rule_commented_code
         | 
| 137 | 
            +
                  rule_lazy_debugging
         | 
| 138 | 
            +
                  rule_pending
         | 
| 139 | 
            +
                  rule_todo
         | 
| 140 | 
            +
                  sleep_rules
         | 
| 141 | 
            +
                end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                def rule_todo
         | 
| 144 | 
            +
                  code.each do |line|
         | 
| 145 | 
            +
                    store_rule(RULES[:todo]) if line =~ /\#(TODO|todo)/
         | 
| 146 | 
            +
                  end
         | 
| 147 | 
            +
                end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                def sleep_rules
         | 
| 150 | 
            +
                  code.each do |line|
         | 
| 151 | 
            +
                    match_data = line.match /^\s*sleep(\s|\()(?<sleep_time>.*)\)?/
         | 
| 152 | 
            +
                    unless match_data.nil?
         | 
| 153 | 
            +
                      sleep_value = match_data[:sleep_time].to_f
         | 
| 154 | 
            +
                      store_rule(RULES[:small_sleep]) if sleep_value <= RULES[:small_sleep][:max]
         | 
| 155 | 
            +
                      store_rule(RULES[:large_sleep]) if sleep_value > RULES[:large_sleep][:min]
         | 
| 156 | 
            +
                    end
         | 
| 157 | 
            +
                  end
         | 
| 158 | 
            +
                end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                def rule_pending
         | 
| 161 | 
            +
                  code.each do |line|
         | 
| 162 | 
            +
                    if line =~ /^\s*pending\s*$/
         | 
| 163 | 
            +
                      store_rule(RULES[:pending])
         | 
| 164 | 
            +
                      return
         | 
| 165 | 
            +
                    end
         | 
| 166 | 
            +
                  end
         | 
| 167 | 
            +
                end
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                def rule_lazy_debugging
         | 
| 170 | 
            +
                  code.each do |line|
         | 
| 171 | 
            +
                    next if is_comment?(line)
         | 
| 172 | 
            +
                    store_rule(RULES[:lazy_debugging]) if line.strip =~ /^(p|puts)( |\()('|"|%(q|Q)?\{)/
         | 
| 173 | 
            +
                  end
         | 
| 115 174 | 
             
                end
         | 
| 116 175 |  | 
| 117 176 | 
             
                def rule_no_code
         | 
| 118 | 
            -
                  store_rule( | 
| 177 | 
            +
                  store_rule(RULES[:no_code]) if code.empty?
         | 
| 119 178 | 
             
                end
         | 
| 120 179 |  | 
| 121 180 | 
             
                def rule_too_many_parameters
         | 
| 122 | 
            -
                  rule =  | 
| 181 | 
            +
                  rule = RULES[:too_many_parameters]
         | 
| 123 182 | 
             
                  store_rule(rule) if parameters.size >= rule[:max]
         | 
| 124 183 | 
             
                end
         | 
| 125 184 |  | 
| 126 185 | 
             
                def rule_nested_steps
         | 
| 127 | 
            -
                  store_rule( | 
| 186 | 
            +
                  store_rule(RULES[:nested_step]) unless nested_steps.empty?
         | 
| 128 187 | 
             
                end
         | 
| 129 188 |  | 
| 130 189 | 
             
                def rule_recursive_nested_step
         | 
| 131 190 | 
             
                  nested_steps.each_value do |nested_step|
         | 
| 132 | 
            -
                    store_rule( | 
| 191 | 
            +
                    store_rule(RULES[:recursive_nested_step]) if nested_step =~ regex
         | 
| 133 192 | 
             
                  end
         | 
| 134 193 | 
             
                end
         | 
| 135 194 |  | 
| 136 195 | 
             
                def rule_commented_code
         | 
| 137 196 | 
             
                  code.each do |line|
         | 
| 138 | 
            -
                    store_rule( | 
| 197 | 
            +
                    store_rule(RULES[:commented_code]) if is_comment?(line)
         | 
| 139 198 | 
             
                  end
         | 
| 140 199 | 
             
                end
         | 
| 141 200 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: cuke_sniffer
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.3
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -11,10 +11,26 @@ authors: | |
| 11 11 | 
             
            autorequire: 
         | 
| 12 12 | 
             
            bindir: bin
         | 
| 13 13 | 
             
            cert_chain: []
         | 
| 14 | 
            -
            date: 2013- | 
| 15 | 
            -
            dependencies: | 
| 14 | 
            +
            date: 2013-03-15 00:00:00.000000000 Z
         | 
| 15 | 
            +
            dependencies:
         | 
| 16 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 17 | 
            +
              name: roxml
         | 
| 18 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 19 | 
            +
                none: false
         | 
| 20 | 
            +
                requirements:
         | 
| 21 | 
            +
                - - ! '>='
         | 
| 22 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 23 | 
            +
                    version: '0'
         | 
| 24 | 
            +
              type: :runtime
         | 
| 25 | 
            +
              prerelease: false
         | 
| 26 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 27 | 
            +
                none: false
         | 
| 28 | 
            +
                requirements:
         | 
| 29 | 
            +
                - - ! '>='
         | 
| 30 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 31 | 
            +
                    version: '0'
         | 
| 16 32 | 
             
            description: A ruby library used to root out smells in your cukes.
         | 
| 17 | 
            -
            email:  | 
| 33 | 
            +
            email: 
         | 
| 18 34 | 
             
            executables:
         | 
| 19 35 | 
             
            - cuke_sniffer.rb
         | 
| 20 36 | 
             
            extensions: []
         | 
| @@ -43,18 +59,12 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 43 59 | 
             
              - - ! '>='
         | 
| 44 60 | 
             
                - !ruby/object:Gem::Version
         | 
| 45 61 | 
             
                  version: '0'
         | 
| 46 | 
            -
                  segments:
         | 
| 47 | 
            -
                  - 0
         | 
| 48 | 
            -
                  hash: -320967053
         | 
| 49 62 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 50 63 | 
             
              none: false
         | 
| 51 64 | 
             
              requirements:
         | 
| 52 65 | 
             
              - - ! '>='
         | 
| 53 66 | 
             
                - !ruby/object:Gem::Version
         | 
| 54 67 | 
             
                  version: '0'
         | 
| 55 | 
            -
                  segments:
         | 
| 56 | 
            -
                  - 0
         | 
| 57 | 
            -
                  hash: -320967053
         | 
| 58 68 | 
             
            requirements: []
         | 
| 59 69 | 
             
            rubyforge_project: 
         | 
| 60 70 | 
             
            rubygems_version: 1.8.24
         |