jeudi 3 mai 2018

ActiveSupport::TestCase - dynamic test classes generation and define_method

I am building some abstraction into my Rails (5.2) tests as I want to run the same tests multiple times with different parameter sets.

I can successfully create a helper to generate test classes on the fly. This looks like the following, within my 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

I can use this helper in any given test file as follows:

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]}" is correctly interpolated for each iteration according to what "config" is passed from the helper. So far so good.

I am having though a problem creating some helper methods that also make use of the variable c, either within the test_configs method itself or within single test files.

None of the following works in giving a consistent match between the c variable that is passed to the test titles and what happens within the tests themselves:

# 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'

How do I get to correctly "inject" methods which make use of the passed variable?

Aucun commentaire:

Enregistrer un commentaire