Created
January 24, 2020 14:35
-
-
Save YusukeIwaki/b4fd745f9275ec440423f158480a7d72 to your computer and use it in GitHub Desktop.
Turnipのstepで未使用のものや未定義のものなどを抽出するスクリプト
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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