Я встраиваю некоторую абстракцию в свои тесты Rails (5.2), поскольку хочу запускать одни и те же тесты несколько раз с разными наборами параметров.
Я могу успешно создать помощника для генерации тестовых классов на лету. В моем файле test_helper.rb это выглядит следующим образом:
class << self
def test_configs(configs: DEFAULT_CONFIGS, &block)
configs.each do |c|
Class.new(ActiveSupport::TestCase) { yield(c) }
end
end
end
Я могу использовать этого помощника в любом файле теста следующим образом:
require 'test_helper'
class SampleTest < ActiveSupport::TestCase
test_configs do |c|
test "#{c[:name]} - something is true" do
puts "#{c[:name]}" => # Correctly outputs c[:name]
end
end
end
"#{c[:name]}"
корректно интерполируется для каждой итерации в соответствии с тем, что «config» передается от помощника. Пока все хорошо.
У меня возникла проблема при создании некоторых вспомогательных методов, которые также используют переменную c
, либо в самом методе test_configs
, либо в отдельных тестовых файлах.
Ни одно из следующих действий не дает согласованного соответствия между переменной c
, передаваемой заголовкам тестов, и тем, что происходит внутри самих тестов:
# Approach 1
class SampleTest < ActiveSupport::TestCase
test_configs do |c|
def config_name
"#{c[:name]}" # => undefined local variable or method `c'
end
test "#{c[:name]} - something is true" do
puts "#{config_name}"
end
end
end
# Approach 2
class SampleTest < ActiveSupport::TestCase
test_configs do |c|
define_method("config_name") {
"#{c[:name]}"
}
test "#{c[:name]} - something is true" do
puts "#{config_name}" # => Uses only the last definition
end
end
end
# Approach 3
class << self
def test_configs(configs: DEFAULT_CONFIGS, &block)
configs.each do |c|
define_method "config_name" do # (same with def config_name)
"#{c[:name]}"
end
Class.new(ActiveSupport::TestCase) { yield(c) }
end
end
end
# => undefined local variable or method `config_name'
Как мне правильно "внедрить" методы, которые используют переданную переменную?