2016-09-24 24 views
0

功能既然我有提供继承功能,子类的抽象类:测试Ruby超类继承的使用RSpec

class Superclass 
    class_attribute :_configuration_parameter 

    def self.configuration_parameter config 
    self._configuration_parameter = config 
    end 

    def results 
    unless @queried 
     execute 
     @queried = true 
    end 

    @results 
    end 

    private 

    # Execute uses the class instance config 
    def execute 
    @rows = DataSource.fetch self.class._configuration_parameter 
    @results = Results.new @rows, count 
    post_process 
    end 

    def post_process 
    @results.each do |row| 
     # mutate results 
    end 
    end 
end 

这可能是由一个子类可以使用这样的:

class Subclass < Superclass 
    configuration_parameter :foo 

    def subclass_method 
    end 
end 

我m难以写RSpec来测试继承和配置的功能而不滥用全局命名空间:

RSpec.describe Superclass do 
    let(:config_parameter) { :bar } 

    let(:test_subclass) do 
    # this feels like an anti-pattern, but the Class.new block scope 
    # doesn't contain config_parameter from the Rspec describe 

    $config_parameter = config_parameter 

    Class.new(Superclass) do 
     configuration_parameter $config_parameter 
    end 
    end 

    let(:test_instance) do 
    test_subclass.new 
    end 

    describe 'config parameter' do 
    it 'sets the class attribute' do 
     expect(test_subclass._configuration_parameter).to be(config_parameter) 
    end 
    end 

    describe 'execute' do 
    it 'fetches the data from the right place' do 
     expect(DataSource).to receive(:fetch).with(config_parameter) 
     instance.results 
    end 
    end 
end 

我在这里嘲笑的真实世界超类有几个配置参数和几个其他功能,这些功能测试合理与这种模式。

我是否错过了关于类或测试设计的一些显而易见的错误?

感谢

+0

你问是否在代码中评论的部分是不好的?就我个人而言,我认为它看起来很丑,我只会使用之前的(:每个)块,但问题并不清楚。如果您要求提供整个测试文件,我认为您必须阅读rspec上的aboutr shared_examples,我认为测试这件事情会更好。 – arieljuod

回答

1

我只是要跳你的问题,如何避免使用全局变量传递局部参数在你规范实例化的虚拟类的最具体的部分。

这是你的规范代码:

let(:test_subclass) do 
    # this feels like an anti-pattern, but the Class.new block scope 
    # doesn't contain config_parameter from the Rspec describe 

    $config_parameter = config_parameter 

    Class.new(Superclass) do 
    configuration_parameter $config_parameter 
    end 
end 

如果你从Class.new返回的值,你可以调用该configuration_parameter与当地的价值,避免全球性的。使用tap做到这一点,只有一个小的改动,以现有的代码:

let(:test_subclass) do 
    Class.new(SuperClass).tap do |klass| 
    klass.configuration_parameter config_parameter 
    end 
end 

至于如何测试从超类继承的功能更普遍的问题,我想创建一个存根子类和写作规范的一般方法对于这个子类来说很好。我个人认为你的_configuration_parameter类属性是私有的,而不是测试configuration_parameter方法实际设置的值,而是专注于检查值是与超类值的不同。但我不确定这个问题的范围。

+0

这是我寻找的理智建议。我很欣赏理智检查和模式上的更多一般建议 – voxobscuro

+0

很高兴答案帮助! –