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:
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
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.