在Ruby中协调类合同

时间:2012-02-10 10:03:04

标签: ruby-on-rails ruby testing

我的应用程序的核心是一个引擎,它采用问题规范,编码为数据结构,并生成我们需要的结果。有两种方法可以实例化规范数据结构:通过解析脚本或通过Rails UI。在Rails的情况下,数据结构是DB中的模型对象,在脚本情况下,它是模型类的内存中实例。引擎位于一个单独的gem中,因此脚本驱动的进程可以独立运行而无需Rails。

我的问题是如何确保两个数据结构,即Rails DB模型和内存模型,实现相同的合同。如果这是Java,我会写一个两个模型类都会实现的接口,但在Ruby中我依赖于duck-typing。我将为每个模型进行测试,但只有一个测试套件会更加干燥。但是,我无法看到如何在gem项目和rails项目之间共享测试。

关键的挑战是:假设我对Rails模型添加了一个责任,我如何保证相应的责任被添加到脚本内存模型中,反之亦然?

1 个答案:

答案 0 :(得分:1)

我想你应该创建一个模块,负责检查接收器类是否包含所需的方法。

这样的事情:

module Contract
  STATIC_METHODS   = [ :class_foo ]
  INSTANCE_METHODS = [ :instance_foo ]

  def self.included(receiver)
    STATIC_METHODS.each do |method|
      raise("missing class method #{method}") unless receiver.respond_to? method
    end
    INSTANCE_METHODS.each do |method|
      raise("missing instance method #{method}") unless receiver.instance_methods.include? method.to_s
    end
  end
end

class YourClass
  def self.class_foo
  end

  def instance_foo

  end

  include Contract
end

请注意在文件末尾包含Contract否则,它将在逻辑上失败(不会定义方法)。

关于您的测试,您应该创建一些常见测试并在类中运行它们,例如:it_should_behave_like