Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails:如何为ruby模块编写测试?_Ruby On Rails_Ruby_Unit Testing_Testing_Module - Fatal编程技术网

Ruby on rails Rails:如何为ruby模块编写测试?

Ruby on rails Rails:如何为ruby模块编写测试?,ruby-on-rails,ruby,unit-testing,testing,module,Ruby On Rails,Ruby,Unit Testing,Testing,Module,我想知道如何为混合到几个类中的模块编写单元测试,但不太知道如何进行: 我是通过在包含实例方法的类的某个测试文件中编写测试来测试实例方法的(似乎不正确),还是可以将包含方法的测试保存在特定于模块的单独文件中 同样的问题也适用于类方法 我是否应该像普通rails模型那样为模块中的每个类都有一个单独的测试文件,或者它们是否存在于通用模块测试文件中(如果存在的话) 我通常会尽可能地隔离测试模块,基本上测试方法,使用足够的代码、模拟和存根使其工作 然后,我可能还会对包含模块的类进行测试。我可能不会测试每一

我想知道如何为混合到几个类中的模块编写单元测试,但不太知道如何进行:

  • 我是通过在包含实例方法的类的某个测试文件中编写测试来测试实例方法的(似乎不正确),还是可以将包含方法的测试保存在特定于模块的单独文件中

  • 同样的问题也适用于类方法

  • 我是否应该像普通rails模型那样为模块中的每个类都有一个单独的测试文件,或者它们是否存在于通用模块测试文件中(如果存在的话)


  • 我通常会尽可能地隔离测试模块,基本上测试方法,使用足够的代码、模拟和存根使其工作

    然后,我可能还会对包含模块的类进行测试。我可能不会测试每一个类,但会测试足够多的类,以获得良好的覆盖率并洞察出现的任何问题。这些测试不需要显式地测试模块,但肯定会测试它在特定场景中的使用情况


    每组测试都有自己的文件

    IMHO,您应该进行功能测试覆盖,覆盖模块的所有用途,然后在单元测试中单独测试它:

    setup do
      @object = Object.new
      @object.extend(Greeter)
    end
    
    should "greet person" do
      @object.stubs(:format).returns("Hello {{NAME}}")
      assert_equal "Hello World", @object.greet("World")
    end
    
    should "greet person in pirate" do
      @object.stubs(:format).returns("Avast {{NAME}} lad!")
      assert_equal "Avast Jim lad!", @object.greet("Jim")
    end
    
    如果您的单元测试很好,您应该能够在它混合到的模块中对功能进行冒烟测试

    或者… 编写一个测试助手,它断言正确的行为,然后对它所混合的每个类使用它。用法如下:

    setup do
      @object = FooClass.new
    end
    
    should_act_as_greeter
    

    如果您的单元测试很好,那么这可以是对预期行为的简单冒烟测试,检查调用了正确的委托等。

    我尝试将测试的重点放在特定类/模块的契约上。如果我已经在该模块的测试类中证明了该模块的行为(通常是通过将该模块包含在该模块规范中声明的测试类中),那么我不会对使用该模块的生产类重复该测试。但是,如果我想为生产类测试其他行为,或者考虑集成问题,我将为生产类编写测试

    例如,我有一个名为
    AttributeValidator
    的模块,它执行类似于
    ActiveRecord
    的轻量级验证。我在模块规范中为模块的行为编写测试:

    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
    
    现在,在一个包含模块的生产类中,我不会重新断言回调是生成的,但我可以断言包含的类有一个带有特定正则表达式的特定验证集,这是该类特有的,但不会重现我为该模块编写的测试。在production类的规范中,我想保证设置了特定的验证,但不能保证验证在一般情况下正常工作。这是一种集成测试,但不会重复我为模块所做的相同断言:

    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
    
    这里有一些重复(大多数集成测试都会有),但是测试对我来说证明了两件不同的事情。一组测试证明了模块的一般行为,另一组测试证明了使用该模块的生产类的特定实现问题。从这些测试中,我知道模块将验证属性并执行回调,并且我知道我的生产类对于生产类特有的特定条件有一组特定的验证

    希望能有所帮助。

    使用内联类(我并不是为了说明这一点而使用flexmock或stubba/mocha)

    任何模拟/存根库都应该为您提供一种更干净的方法。也可以使用结构:

     instance = Struct.new(:foo).new
     class<<instance
         include ModuleUnderTest
     end
     instance.foo = 4
    
    instance=Struct.new(:foo).new
    
    类在
    minitest
    中,因为每个测试都是显式的类,所以您可以将模块包括到测试中,并测试方法:

    类MyModuleTest
    我喜欢做的是创建一个新的host类并将模块混合到其中,如下所示:

    description MyModule do
    
    让(:host_class){class.new{include MyModule} let(:instance){host_class.new} 描述“#实例_方法”做什么 它“做某事”做什么 期望(instance.instance\u方法)。做某事 结束 结束 结束
    谢谢,我同意你所说的在它包含的类中测试功能的说法。那么,您是为模块中的每个附加类准备一个测试文件,还是为整个模块准备一个测试文件?我想我更关心实际的测试文件(文件名、位置等),而不是测试什么。当你说“功能测试覆盖率”时,我想你指的是模型获得的功能,而不是控制器测试存储的测试/功能?谢谢你的回答,我喜欢在隔离状态下测试这个模块,并编写一个其他类可以调用的帮助程序来使用这个模块。这通常是控制器测试,但并不总是如此。无论哪种方式,功能覆盖都应该覆盖(或至少覆盖)系统的所有区域。如果你的单元测试很强大,那么功能测试通常足以让你蒙混过关。编写太多低级测试可能是一项糟糕的投资。如果它永远不会单独失败,那么它是否会捕获bug?是否“可能节省的调试时间”*“出现错误的可能性”>“编写测试的时间”?如果一个bug可能会杀死人或者你的生意,请忽略这一点。不。控制器测试(几乎)总是坏主意(黄瓜故事做同样的事情更好),而且它们与手头的问题无关。就像第一个代码示例中的单元测试一样。我对Ruby这样的测试相当陌生,所以请纠正我的无知。看起来您的测试是重复的-您正在删除该方法,并检查对该方法的响应
     instance = Struct.new(:foo).new
     class<<instance
         include ModuleUnderTest
     end
     instance.foo = 4