Skip to content

Instantly share code, notes, and snippets.

@YusukeIwaki
Created January 24, 2020 14:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YusukeIwaki/b4fd745f9275ec440423f158480a7d72 to your computer and use it in GitHub Desktop.
Save YusukeIwaki/b4fd745f9275ec440423f158480a7d72 to your computer and use it in GitHub Desktop.
Turnipのstepで未使用のものや未定義のものなどを抽出するスクリプト
feature_files = Dir.glob('features/**/*.feature')
step_files = Dir.glob('steps/**/*_steps.rb')
Usage = Struct.new(:feature, :scenario, :step)
StepUsageItem = Struct.new(:step_description, :usages)
require 'turnip'
# 全Featureを読み、それぞれのstepがどのfeature/scenario で使われているかを調べる。
step_usage = {}
feature_files.each do |feature_file|
feature = Turnip::Builder.build(feature_file)
feature.backgrounds.each do |background|
background.steps.each do |step|
step_usage[step.description] ||= []
step_usage[step.description] << Usage.new(feature, background, step)
end
end
feature.scenarios.each do |scenario|
scenario.steps.each do |step|
step_usage[step.description] ||= []
step_usage[step.description] << Usage.new(feature, scenario, step)
end
end
end
# << 全Featureを読み、それぞれのstepがどのfeature/scenario で使われているかを調べる。
# 全step definitionを読み、それぞれのstep definitionがどこで使われているかを調べる
step_files.each do |step_file|
load step_file
end
include Turnip::Steps
# ref: https://github.com/jnicklas/turnip/blob/master/lib/turnip/execute.rb
match_methods = methods.select{|m| m.to_s.start_with?("match: ")}
match_method_usage = {}
match_methods.each do |method_name_sym|
match_method_usage[method_name_sym.to_s] = []
end
undefined_step_usages = []
ambiguous_step_usages = []
step_usage.each do |step_description, usages|
step_definitions = match_methods.map{|m| method(m).call(step_description) }.compact
if step_definitions.empty?
undefined_step_usages << StepUsageItem.new(step_description, usages)
elsif step_definitions.size >= 2
ambiguous_step_usages << StepUsageItem.new(step_description, usages)
end
step_definitions.each do |step_definition|
match_method_usage["match: #{step_definition.expression}"] << StepUsageItem.new(step_description, usages)
end
end
# << 全step definitionを読み、それぞれのstep definitionがどこで使われているかを調べる
error = false
undefined_step_usages.each do |step_usage_item|
error = true
STDERR.puts "-" * 50
STDERR.puts "No step definition for: '#{step_usage_item.step_description}'"
step_usage_item.usages.each do |usage|
STDERR.puts " used in #{usage.feature.name} -> #{usage.scenario.name}"
end
end
ambiguous_step_usages.each do |step_usage_item|
error = true
STDERR.puts "-" * 50
STDERR.puts "Ambiguous step: '#{step_usage_item.step_description}'"
match_methods.map{|m| method(m).call(step_usage_item.step_description) }.compact.each do |step_definition|
STDERR.puts " - '#{step_definition.expression}' : #{step_definition.block.source_location.join(":")}"
end
end
unused_step_descriptions = match_method_usage.select{ |k,v| v.empty? }.keys.map{|sym| sym.to_s[7..] }
unless unused_step_descriptions.empty?
error = true
STDERR.puts "-" * 50
STDERR.puts "Unused step definitions detected"
STDERR.puts " #{"-" * 48}"
STDERR.puts " Used in step? --> Use it explicitly in Scenario, and remove from step. 'Calling steps in other steps' is not recommended in this project."
STDERR.puts " Otherwise --> Remove it!!"
STDERR.puts " #{"-" * 48}"
unused_step_descriptions.each do |description|
STDERR.puts " - '#{description}'"
end
end
exit(!error)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment