Rails: How do I write tests for a ruby module?

前端 未结 6 891
春和景丽
春和景丽 2021-01-31 02:22

I would like to know how to write unit tests for a module that is mixed into a couple of classes but don\'t quite know how to go about it:

  1. Do I test the instanc

6条回答
  •  被撕碎了的回忆
    2021-01-31 02:39

    I try to keep my tests focused only on the contract for that particular class/module. If I've proven the module's behavior in a test class for that module (usually by including that module in a test class declared in the spec for that module) then I won't duplicate that test for a production class that uses that module. But if there's additional behavior that I want to test for the production class, or integration concerns, I'll write tests for the production class.

    For instance I have a module called AttributeValidator that performs lightweight validations kind of similar to ActiveRecord. I write tests for the module's behavior in the module spec:

    before(:each) do
      @attribute_validator = TestAttributeValidator.new
    end
    
    describe "after set callbacks" do
      it "should be invoked when an attribute is set" do
        def @attribute_validator.after_set_attribute_one; end
        @attribute_validator.should_receive(:after_set_attribute_one).once
        @attribute_validator.attribute_one = "asdf"
      end
    end
    
    class TestAttributeValidator 
        include AttributeValidator
        validating_str_accessor [:attribute_one, /\d{2,5}/]      
    end
    

    Now in a production class that includes the module, I won't re-assert that the callbacks are made, but I may assert that the included class has a certain validation set with a certain regular expression, something particular to that class, but not reproducing the tests I wrote for the module. In the spec for the production class, I want to guarantee that particular validations are set, but not that validations work in general. This is a kind of integration test, but one that doesn't repeat the same assertions I made for the module:

    describe "ProductionClass validation" do
      it "should return true if the attribute is valid" do
        @production_class.attribute = @valid_attribute 
        @production_class.is_valid?.should be_true
      end
      it "should return false if the attribute is invalid" do
        @production_class.attribute = @invalid_attribute
        @production_class.is valid?.should be_false
      end
    end
    

    There is some duplication here (as most integration tests will have), but the tests prove two different things to me. One set of tests prove the general behavior of the module, the other proves particular implementation concerns of a production class that uses that module. From these tests I know that the module will validate attributes and perform callbacks, and I know that my production class has a specific set of validations for specific criteria unique to the production class.

    Hope that helps.

提交回复
热议问题