You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

usage.rb 5.0 kB

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. # frozen_string_literal: true
  2. require 'cucumber/formatter/progress'
  3. require 'cucumber/step_definition_light'
  4. require 'cucumber/formatter/console'
  5. module Cucumber
  6. module Formatter
  7. class Usage < Progress
  8. include Console
  9. class StepDefKey < StepDefinitionLight
  10. attr_accessor :mean_duration, :status
  11. end
  12. def initialize(config)
  13. super
  14. @stepdef_to_match = Hash.new { |h, stepdef_key| h[stepdef_key] = [] }
  15. @total_duration = 0
  16. @matches = {}
  17. config.on_event :step_activated do |event|
  18. test_step, step_match = *event.attributes
  19. @matches[test_step.to_s] = step_match
  20. end
  21. config.on_event :step_definition_registered, &method(:on_step_definition_registered)
  22. end
  23. def on_step_definition_registered(event)
  24. stepdef_key = StepDefKey.new(event.step_definition.expression.to_s, event.step_definition.location)
  25. @stepdef_to_match[stepdef_key] = []
  26. end
  27. def on_step_match(event)
  28. @matches[event.test_step.to_s] = event.step_match
  29. super
  30. end
  31. def on_test_step_finished(event)
  32. return if event.test_step.hook?
  33. test_step = event.test_step
  34. result = event.result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
  35. step_match = @matches[test_step.to_s]
  36. unless step_match.nil?
  37. step_definition = step_match.step_definition
  38. stepdef_key = StepDefKey.new(step_definition.expression.to_s, step_definition.location)
  39. unless @stepdef_to_match[stepdef_key].map { |key| key[:location] }.include? test_step.location
  40. duration = DurationExtractor.new(result).result_duration
  41. keyword = @ast_lookup.step_source(test_step).step.keyword
  42. @stepdef_to_match[stepdef_key] << {
  43. keyword: keyword,
  44. step_match: step_match,
  45. status: result.to_sym,
  46. location: test_step.location,
  47. duration: duration
  48. }
  49. end
  50. end
  51. super
  52. end
  53. private
  54. def print_summary
  55. aggregate_info
  56. keys = if config.dry_run?
  57. @stepdef_to_match.keys.sort_by(&:regexp_source)
  58. else
  59. @stepdef_to_match.keys.sort_by(&:mean_duration).reverse
  60. end
  61. keys.each do |stepdef_key|
  62. print_step_definition(stepdef_key)
  63. if @stepdef_to_match[stepdef_key].any?
  64. print_steps(stepdef_key)
  65. else
  66. @io.puts(" #{format_string('NOT MATCHED BY ANY STEPS', :failed)}")
  67. end
  68. end
  69. @io.puts
  70. super
  71. end
  72. def print_step_definition(stepdef_key)
  73. @io.print "#{format_string(format('%<duration>.7f', duration: stepdef_key.mean_duration), :skipped)} " unless config.dry_run?
  74. @io.print format_string(stepdef_key.regexp_source, stepdef_key.status)
  75. if config.source?
  76. indent_amount = max_length - stepdef_key.regexp_source.unpack('U*').length
  77. line_comment = indent(" # #{stepdef_key.location}", indent_amount)
  78. @io.print(format_string(line_comment, :comment))
  79. end
  80. @io.puts
  81. end
  82. def print_steps(stepdef_key)
  83. @stepdef_to_match[stepdef_key].each do |step|
  84. @io.print ' '
  85. @io.print "#{format_string(format('%<duration>.7f', duration: step[:duration]), :skipped)} " unless config.dry_run?
  86. @io.print format_step(step[:keyword], step[:step_match], step[:status], nil)
  87. if config.source?
  88. indent_amount = max_length - (step[:keyword].unpack('U*').length + step[:step_match].format_args.unpack('U*').length)
  89. line_comment = indent(" # #{step[:location]}", indent_amount)
  90. @io.print(format_string(line_comment, :comment))
  91. end
  92. @io.puts
  93. end
  94. end
  95. def max_length
  96. [max_stepdef_length, max_step_length].compact.max
  97. end
  98. def max_stepdef_length
  99. @stepdef_to_match.keys.flatten.map { |key| key.regexp_source.unpack('U*').length }.max
  100. end
  101. def max_step_length
  102. @stepdef_to_match.values.to_a.flatten.map do |step|
  103. step[:keyword].unpack('U*').length + step[:step_match].format_args.unpack('U*').length
  104. end.max
  105. end
  106. def aggregate_info
  107. @stepdef_to_match.each do |key, steps|
  108. if steps.empty?
  109. key.status = :skipped
  110. key.mean_duration = 0
  111. else
  112. key.status = worst_status(steps.map { |step| step[:status] })
  113. total_duration = steps.inject(0) { |sum, step| step[:duration] + sum }
  114. key.mean_duration = total_duration / steps.length
  115. end
  116. end
  117. end
  118. def worst_status(statuses)
  119. %i[passed undefined pending skipped failed].find do |status|
  120. statuses.include?(status)
  121. end
  122. end
  123. end
  124. end
  125. end

No Description

Contributors (1)