2016-09-24 38 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

很高興答案幫助! –