Chris@909: # Contains the enhancements to assist in testing plugins. See Engines::Testing Chris@909: # for more details. Chris@909: Chris@909: require 'test/unit' Chris@909: Chris@909: require 'tmpdir' Chris@909: require 'fileutils' Chris@909: Chris@909: # In most cases, Rails' own plugin testing mechanisms are sufficient. However, there Chris@909: # are cases where plugins can be given a helping hand in the testing arena. This module Chris@909: # contains some methods to assist when testing plugins that contain fixtures. Chris@909: # Chris@909: # == Fixtures and plugins Chris@909: # Chris@909: # Since Rails' own fixtures method is fairly strict about where files can be loaded from, Chris@909: # the simplest approach when running plugin tests with fixtures is to simply copy all Chris@909: # fixtures into a single temporary location and inform the standard Rails mechanism to Chris@909: # use this directory, rather than RAILS_ROOT/test/fixtures. Chris@909: # Chris@909: # The Engines::Testing#setup_plugin_fixtures method does this, copying all plugin fixtures Chris@909: # into the temporary location before and tests are performed. This behaviour is invoked Chris@909: # the the rake tasks provided by the Engines plugin, in the "test:plugins" namespace. If Chris@909: # necessary, you can invoke the task manually. Chris@909: # Chris@909: # If you wish to take advantage of this, add a call to the Engines::Testing.set_fixture_path Chris@909: # method somewhere before your tests (in a test_helper file, or above the TestCase itself). Chris@909: # Chris@909: # = Testing plugins Chris@909: # Chris@909: # Normally testing a plugin will require that Rails is loaded, unless you are including Chris@909: # a skeleton Rails environment or set of mocks within your plugin tests. If you require Chris@909: # the Rails environment to be started, you must ensure that this actually happens; while Chris@909: # it's not obvious, your tests do not automatically run with Rails loaded. Chris@909: # Chris@909: # The simplest way to setup plugin tests is to include a test helper with the following Chris@909: # contents: Chris@909: # Chris@909: # # Load the normal Rails helper. This ensures the environment is loaded Chris@909: # require File.expand_path(File.dirname(__FILE__) + '/../../../../test/test_helper') Chris@909: # # Ensure that we are using the temporary fixture path Chris@909: # Engines::Testing.set_fixture_path Chris@909: # Chris@909: # Then run tests using the provided tasks (test:plugins, or the tasks that the engines Chris@909: # plugin provides - test:plugins:units, etc.). Chris@909: # Chris@909: # Alternatively, you can explicitly load the environment by adpating the contents of the Chris@909: # default test_helper: Chris@909: # Chris@909: # ENV["RAILS_ENV"] = "test" Chris@909: # # Note that we are requiring config/environment from the root of the enclosing application. Chris@909: # require File.expand_path(File.dirname(__FILE__) + "/../../../../config/environment") Chris@909: # require 'test_help' Chris@909: # Chris@909: module Engines::Testing Chris@909: mattr_accessor :temporary_fixtures_directory Chris@909: self.temporary_fixtures_directory = FileUtils.mkdir_p(File.join(Dir.tmpdir, "rails_fixtures")) Chris@909: Chris@909: # Copies fixtures from plugins and the application into a temporary directory Chris@909: # (Engines::Testing.temporary_fixtures_directory). Chris@909: # Chris@909: # If a set of plugins is not given, fixtures are copied from all plugins in order Chris@909: # of precedence, meaning that plugins can 'overwrite' the fixtures of others if they are Chris@909: # loaded later; the application's fixtures are copied last, allowing any custom fixtures Chris@909: # to override those in the plugins. If no argument is given, plugins are loaded via Chris@909: # PluginList#by_precedence. Chris@909: # Chris@909: # This method is called by the engines-supplied plugin testing rake tasks Chris@909: def self.setup_plugin_fixtures(plugins = Engines.plugins.by_precedence) Chris@909: Chris@909: # First, clear the directory Chris@909: Dir.glob("#{self.temporary_fixtures_directory}/*.yml").each{|fixture| File.delete(fixture)} Chris@909: Chris@909: # Copy all plugin fixtures, and then the application fixtures, into this directory Chris@909: plugins.each do |plugin| Chris@909: plugin_fixtures_directory = File.join(plugin.directory, "test", "fixtures") Chris@909: plugin_app_directory = File.join(plugin.directory, "app") Chris@909: if File.directory?(plugin_app_directory) && File.directory?(plugin_fixtures_directory) Chris@909: Engines.mirror_files_from(plugin_fixtures_directory, self.temporary_fixtures_directory) Chris@909: end Chris@909: end Chris@909: Engines.mirror_files_from(File.join(RAILS_ROOT, "test", "fixtures"), Chris@909: self.temporary_fixtures_directory) Chris@909: end Chris@909: Chris@909: # Sets the fixture path used by Test::Unit::TestCase to the temporary Chris@909: # directory which contains all plugin fixtures. Chris@909: def self.set_fixture_path Chris@909: ActiveSupport::TestCase.fixture_path = self.temporary_fixtures_directory Chris@909: $LOAD_PATH.unshift self.temporary_fixtures_directory Chris@909: end Chris@909: Chris@909: # overridden test should be in test/{unit,functional,integration}/{plugin_name}/{test_name} Chris@909: def self.override_tests_from_app Chris@909: filename = caller.first.split(":").first Chris@909: plugin_name = filename.split("/")[-4] Chris@909: test_kind = filename.split("/")[-2] Chris@909: override_file = File.expand_path(File.join(File.dirname(filename), "..", "..", "..", "..", "..", "test", Chris@909: test_kind, plugin_name, File.basename(filename))) Chris@909: load(override_file) if File.exist?(override_file) Chris@909: end Chris@909: end