有没有办法通过插件对 Rails 测试进行猴子补丁?
我和我的团队一直在为 Rails 2.3 应用程序(Redmine,目前为 1.1 分支)大量制作插件。到目前为止,我们通过将大部分更改编写为 Rails 插件来遏制对 Redmine 基本代码的污染。这有两个主要好处:
- 大多数时候,与新版 Redmine 的集成非常简单。
- 我们可以通过删除/删除插件来启用/禁用某些自定义行为。事实上,这对我们来说是一个关键因素,因为我们的客户有非常不同的要求。
我们的一些插件猴子补丁Redmine的类。例如,我们有一个插件可以向 Issue
模型“注入”更严格的验证:start_date
、due_date
和 estimated_hours
是 leaf?
问题所必需的。
这种猴子修补的东西会导致多个测试失败和/或引发异常。例如,这个插件使 IssueNestedSetTest
类中的 create_issue!
方法创建无效问题(即缺少插件强制执行的必需属性):
# Helper that creates an issue with default attributes
def create_issue!(attributes={})
Issue.create!({:project_id => 1, :tracker_id => 1, :author_id => 1, :subject => 'test'}.merge(attributes))
end
由于插件可能或可能不活跃,我们不想改变测试本身。我们认为最好的插件猴子补丁相应的测试:
module StandardTestPatches
module InstanceMethods
def create_issue_with_gespro_standards!(attributes={})
attributes.merge!(:start_date => 1.day.ago, :due_date => 1.day.from_now, :estimated_hours => 8)
create_issue_without_gespro_standards!(attributes)
end
end
def self.included(base)
base.send :include, InstanceMethods
base.class_eval do
alias_method_chain :create_issue!, :gespro_standards
end
end
end
但是,由于在加载测试类之前需要我们的插件的 init.rb
文件,所以我们无法猴子补丁 IssueNestedSetTest 那里有类。
有没有办法通过插件对 Rails 测试进行猴子补丁?
更新:仍然是一个悬而未决的问题。使其可用 http://www.redmine.org/boards/1/topics/23672
Me and my team have been heavily producing plugins for a Rails 2.3 app (Redmine, currently 1.1 branch). So far, we have contained from polluting Redmine's base code by writing most of our changes as rails plugins. This has two main benefits:
- Most of the time, integration with newer Redmine versions is straightforward.
- We can enable/disable some custom behavior by dropping/removing a plugin. In fact, this is a key factor for us, because our clients have quite disparate requirements.
Some of our plugins monkey-patch Redmine's classes. For instance, we have a plugin that "injects" stricter validations to the Issue
model: start_date
, due_date
and estimated_hours
are required for leaf?
issues.
This monkey-patching stuff makes several tests fail and/or raise exceptions. This very plugin, for instance, makes the create_issue!
method from IssueNestedSetTest
class to create invalid issues (i.e. lacking the required attributes the plugin is enforcing):
# Helper that creates an issue with default attributes
def create_issue!(attributes={})
Issue.create!({:project_id => 1, :tracker_id => 1, :author_id => 1, :subject => 'test'}.merge(attributes))
end
Since the plugin may or may not be active, we would not like to change the test itself. We think it's best the plugin monkey-patch the test accordingly:
module StandardTestPatches
module InstanceMethods
def create_issue_with_gespro_standards!(attributes={})
attributes.merge!(:start_date => 1.day.ago, :due_date => 1.day.from_now, :estimated_hours => 8)
create_issue_without_gespro_standards!(attributes)
end
end
def self.included(base)
base.send :include, InstanceMethods
base.class_eval do
alias_method_chain :create_issue!, :gespro_standards
end
end
end
However since our plugin's init.rb
file is required before the tests classes are loaded we can't monkey-patch the IssueNestedSetTest
class there.
Is there a way to monkey-patch rails tests from plugins?
UPDATE: Still an open question. Making it available at http://www.redmine.org/boards/1/topics/23672
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
每当我编写 Redmine 或 ChiliProject 插件时,我总是假设:
我试图帮助其他人工作通过修补核心测试来解决这个问题,但我们从未找到好的解决方案。要么测试会在核心中发生变化,另一个插件会破坏某些东西,或者其他东西。我什至尝试在测试中模拟接口,但维护它们是一个时间杀手。
我建议(和做)的是:
(如果同时安装了 PluginA 和 PluginB,稍后可能会遇到问题)
抱歉没有更好的解决方案。
Whenever I write Redmine or ChiliProject plugins I always assume that:
I've tried to help others work around this by patching the core tests but we never found a good solution. Either the test would change in the core, another plugin would break something, or something else. I even tried to mock out the interfaces in the tests but maintaining them were a time killer.
What I recommend (and do) is:
(And you might run into problems later on if PluginA and PluginB are both installed)
Sorry there isn't a better solution.