2015-01-02 4 views
1

저는 현재/after_suite 콜백을 사용하여 Minitest::Runnable.run을 감싸는 Minitest 확장 작업을하고 있습니다. Minitest가 작동하는 방식은 테스트 클래스가 Minitest::Runnable에서 상속된다는 것입니다. 또한, describe 블록은 동적으로이 정의하고있는 테스트 클래스에서 상속 클래스를 만듭니다. 그래서하위 클래스로 올바르게 평가되는 클래스에서 싱글 톤 메서드를 동적으로 정의하십시오.

# Minitest::Spec inherits from Minitest::Runnable 
class TestClass < Minitest::Spec 
    describe 'a describe block' do 
    it 'should say hi' do 
     # test here 
    end 
    end 
end 

누구 name"a describe block"입니다 TestClass에 상속하는 새로운 클래스를 생성합니다. 이것은 Minitest 파이프 라인을 따라 가면서 각 클래스에 Mintest::Runnable.run을 호출합니다 (예 : self"a describe block"을 포함하여 각 클래스가됩니다). 참고로 :

내 확장은 당신이 Minitest :: Runnable.run을 감싸는 before_suite 방법을 할 수 있도록하여 작동하도록 설계
module Minitest::Runnable 
    def self.run reporter, options = {} 
    require 'rubygems'; require 'pry'; binding.pry 
    filter = options[:filter] || '/./' 
    filter = Regexp.new $1 if filter =~ /\/(.*)\// 

    filtered_methods = self.runnable_methods.find_all { |m| 
     filter === m || filter === "#{self}##{m}" 
    } 

    with_info_handler reporter do 
     filtered_methods.each do |method_name| 
     run_one_method self, method_name, reporter 
     end 
    end 
    end 
end 

:

class TestClass < Minitest::Spec 
    before_suite do 
    # do something 
    end 

    describe 'a describe block' do 
    it 'should say hi' do 
     # test here 
    end 
    end 
end 

나는 그것이 대부분은 내가하지만, 일이있어 상속으로 문제가 생겼어. 래퍼 메서드를 재정의하면 새 싱글 톤 메서드의 수신기가 서브 클래스 (예 : descibe 블록)의 경우에도 TestClass이됩니다. 이로 인해 내 검사가 발견되지 않습니다.

module Minitest::SuiteCallbacks 
    def self.extended(base) 
    base.class_eval do 
     class << self 
     def before_suite(&before_suite_proc) 
      @before_suite_proc = before_suite_proc 

      context = self 
      original_singleton_run = method(:run) 
      define_singleton_method :run do |*args, &block| 
      # `self` here winds up being `TestClass` instead of the dynamic class 
      # (e.g. self.name => "TestClass" instead of "a describe block") 

      context.setup_before_suite 
      original_singleton_run.call(*args, &block) 
      end 
     end 
     end 
    end 
    end 
end 

run의 현재 구현을 잡고 그것을 랩 :

다음은 전 제품군의 나의 현재의 구현입니다. 문제는 그것이 동적 클래스 대신 TestClass 인 메서드의 self이 동적 인 "a describe block" 하위 클래스의 컨텍스트에서 호출되었을 때입니다.

문제를 해결하기 위해 내가 할 수있는 것에 대한 의견이 있으십니까? 내 목표는 상속 체인에서 모든 메서드를 동적으로 래핑하고 모든 자식 클래스에서 제대로 작동하도록하는 것입니다.

미리 감사드립니다.

답변

1

버그가 메서드 바인딩에있었습니다. 나는 중 하나는 unbind 방법에 있었다 또는 UnboundMethodinstance_method를 통해 참조를 싱글 톤 클래스를 열고 얻을 : 이것은 내 초기 추측

def before_suite 
    # ... 
    original = instance_method(:run) 
    class << self 
    define_method :run do |*args, &block| 
     # add decorated logic 
     original.bind(self).call(*args, &block) 
    end 
    end 
end 

했지만, 오류가 나는 실행을 래핑 (스택 더 아래에서오고 메소드를 after_suite로 다시 호출하고 해당 구현을 변경하는 것을 잊어 버린 경우). 의심 스러울 때 주석으로 처리하십시오!

관련 문제