Create Rails::Generators::TestCase.
This commit is contained in:
parent
e88ea3255f
commit
441227a10f
|
@ -272,7 +272,7 @@ module Rails
|
|||
# parameters.
|
||||
#
|
||||
def invoked?(args)
|
||||
args.last.is_a?(Hash) && args.last.key?(:invocations)
|
||||
args.last.is_a?(Hash) && (args.last.key?(:invocations) || args.last.key?(:destination_root))
|
||||
end
|
||||
|
||||
# Use Rails default banner.
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
require 'active_support/test_case'
|
||||
require 'active_support/core_ext/class/inheritable_attributes'
|
||||
require 'active_support/core_ext/hash/reverse_merge'
|
||||
require 'rails/generators'
|
||||
require 'fileutils'
|
||||
|
||||
module Rails
|
||||
module Generators
|
||||
# Disable color in output. Easier to debug.
|
||||
no_color!
|
||||
|
||||
# This class provides a TestCase for testing generators. To setup, you need
|
||||
# just to configure the destination and set which generator is being tested:
|
||||
#
|
||||
# class AppGeneratorTest < Rails::Generators::TestCase
|
||||
# tests AppGenerator
|
||||
# destination File.expand_path("../tmp", File.dirname(__FILE__))
|
||||
# end
|
||||
#
|
||||
# If you want to ensure your destination root is clean before running each test,
|
||||
# you can set a setup callback:
|
||||
#
|
||||
# class AppGeneratorTest < Rails::Generators::TestCase
|
||||
# tests AppGenerator
|
||||
# destination File.expand_path("../tmp", File.dirname(__FILE__))
|
||||
# setup :prepare_destination
|
||||
# end
|
||||
#
|
||||
class TestCase < ActiveSupport::TestCase
|
||||
include FileUtils
|
||||
|
||||
extlib_inheritable_accessor :destination_root, :current_path, :instance_writer => false
|
||||
extlib_inheritable_accessor :generator_class
|
||||
|
||||
# Generators frequently change the current path using +FileUtils.cd+.
|
||||
# So we need to store the path at file load and revert back to it after each test.
|
||||
self.current_path = File.expand_path(Dir.pwd)
|
||||
|
||||
setup :destination_root_is_set?, :ensure_current_path
|
||||
teardown :ensure_current_path
|
||||
|
||||
# Sets which generator should be tested:
|
||||
#
|
||||
# tests AppGenerator
|
||||
#
|
||||
def self.tests(klass)
|
||||
self.generator_class = klass
|
||||
end
|
||||
|
||||
# Sets the destination of generator files:
|
||||
#
|
||||
# destination File.expand_path("../tmp", File.dirname(__FILE__))
|
||||
#
|
||||
def self.destination(path)
|
||||
self.destination_root = path
|
||||
end
|
||||
|
||||
# Captures the given stream and returns it:
|
||||
#
|
||||
# stream = capture(:stdout){ puts "Cool" }
|
||||
# stream #=> "Cool\n"
|
||||
#
|
||||
def capture(stream)
|
||||
begin
|
||||
stream = stream.to_s
|
||||
eval "$#{stream} = StringIO.new"
|
||||
yield
|
||||
result = eval("$#{stream}").string
|
||||
ensure
|
||||
eval("$#{stream} = #{stream.upcase}")
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
alias :silence :capture
|
||||
|
||||
# Asserts a given file exists. You need to supply an absolute path or a path relative
|
||||
# to the configured destination:
|
||||
#
|
||||
# assert_file "config/environment.rb"
|
||||
#
|
||||
# You can also give extra arguments. If the argument is a regexp, it will check if the
|
||||
# regular expression matches the given file content. If it's a string, it compares the
|
||||
# file with the given string:
|
||||
#
|
||||
# assert_file "config/environment.rb", /initialize/
|
||||
#
|
||||
# Finally, when a block is given, it yields the file content:
|
||||
#
|
||||
# assert_file "app/controller/products_controller.rb" do |controller|
|
||||
# assert_instance_method :index, content do |index|
|
||||
# assert_match /Product\.all/, index
|
||||
# end
|
||||
# end
|
||||
#
|
||||
def assert_file(relative, *contents)
|
||||
absolute = File.expand_path(relative, destination_root)
|
||||
assert File.exists?(absolute), "Expected file #{relative.inspect} to exist, but does not"
|
||||
|
||||
read = File.read(absolute) if block_given? || !contents.empty?
|
||||
yield read if block_given?
|
||||
|
||||
contents.each do |content|
|
||||
case content
|
||||
when String
|
||||
assert_equal content, read
|
||||
when Regexp
|
||||
assert_match content, read
|
||||
end
|
||||
end
|
||||
end
|
||||
alias :assert_directory :assert_file
|
||||
|
||||
# Asserts a given file does not exist. You need to supply an absolute path or a
|
||||
# path relative to the configured destination:
|
||||
#
|
||||
# assert_no_file "config/random.rb"
|
||||
#
|
||||
def assert_no_file(relative)
|
||||
absolute = File.expand_path(relative, destination_root)
|
||||
assert !File.exists?(absolute), "Expected file #{relative.inspect} to not exist, but does"
|
||||
end
|
||||
alias :assert_no_directory :assert_no_file
|
||||
|
||||
# Asserts a given file does not exist. You need to supply an absolute path or a
|
||||
# path relative to the configured destination:
|
||||
#
|
||||
# assert_migration "db/migrate/create_products.rb"
|
||||
#
|
||||
# This method manipulates the given path and tries to find any migration which
|
||||
# matches the migration name. For example, the call above is converted to:
|
||||
#
|
||||
# assert_file "db/migrate/003_create_products.rb"
|
||||
#
|
||||
# Consequently, assert_migration accepts the same arguments has assert_file.
|
||||
#
|
||||
def assert_migration(relative, *contents, &block)
|
||||
file_name = migration_file_name(relative)
|
||||
assert file_name, "Expected migration #{relative} to exist, but was not found"
|
||||
assert_file file_name, *contents, &block
|
||||
end
|
||||
|
||||
# Asserts a given migration does not exist. You need to supply an absolute path or a
|
||||
# path relative to the configured destination:
|
||||
#
|
||||
# assert_no_file "config/random.rb"
|
||||
#
|
||||
def assert_no_migration(relative)
|
||||
file_name = migration_file_name(relative)
|
||||
assert_nil file_name, "Expected migration #{relative} to not exist, but found #{file_name}"
|
||||
end
|
||||
|
||||
# Asserts the given class method exists in the given content. This method does not detect
|
||||
# class methods inside (class << self), only class methods which starts with "self.".
|
||||
# When a block is given, it yields the content of the method.
|
||||
#
|
||||
# assert_migration "db/migrate/create_products.rb" do |migration|
|
||||
# assert_class_method :up, migration do |up|
|
||||
# assert_match /create_table/, up
|
||||
# end
|
||||
# end
|
||||
#
|
||||
def assert_class_method(method, content, &block)
|
||||
assert_instance_method "self.#{method}", content, &block
|
||||
end
|
||||
|
||||
# Asserts the given method exists in the given content. When a block is given,
|
||||
# it yields the content of the method.
|
||||
#
|
||||
# assert_file "app/controller/products_controller.rb" do |controller|
|
||||
# assert_instance_method :index, content do |index|
|
||||
# assert_match /Product\.all/, index
|
||||
# end
|
||||
# end
|
||||
#
|
||||
def assert_instance_method(method, content)
|
||||
assert content =~ /def #{method}(\(.+\))?(.*?)\n end/m, "Expected to have method #{method}"
|
||||
yield $2.strip if block_given?
|
||||
end
|
||||
alias :assert_method :assert_instance_method
|
||||
|
||||
# Runs the generator configured for this class. The first argument is an array like
|
||||
# command line arguments:
|
||||
#
|
||||
# class AppGeneratorTest < Rails::Generators::TestCase
|
||||
# tests AppGenerator
|
||||
# destination File.expand_path("../tmp", File.dirname(__FILE__))
|
||||
# teardown :cleanup_destination_root
|
||||
#
|
||||
# test "database.yml is not created when skipping activerecord" do
|
||||
# run_generator %w(myapp --skip-activerecord)
|
||||
# assert_no_file "config/database.yml"
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# You can provide a configuration hash as second argument. This method returns the output
|
||||
# printed by the generator.
|
||||
def run_generator(args=[], config={})
|
||||
capture(:stdout) { self.generator_class.start args, config.reverse_merge(:destination_root => destination_root) }
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def destination_root_is_set? #:nodoc:
|
||||
raise "You need to configure your Rails::Generators::TestCase destination root." unless destination_root
|
||||
end
|
||||
|
||||
def ensure_current_path #:nodoc:
|
||||
cd current_path
|
||||
end
|
||||
|
||||
def prepare_destination
|
||||
rm_rf(destination_root)
|
||||
mkdir_p(destination_root)
|
||||
end
|
||||
|
||||
def migration_file_name(relative) #:nodoc:
|
||||
absolute = File.expand_path(relative, destination_root)
|
||||
dirname, file_name = File.dirname(absolute), File.basename(absolute).sub(/\.rb$/, '')
|
||||
Dir.glob("#{dirname}/[0-9]*_*.rb").grep(/\d+_#{file_name}.rb$/).first
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,7 +6,7 @@ class ControllerGeneratorTest < GeneratorsTestCase
|
|||
|
||||
def test_help_does_not_show_invoked_generators_options_if_they_already_exist
|
||||
content = run_generator ["--help"]
|
||||
assert_no_match /Helper options:/, content
|
||||
assert_no_match /Helper options\:/, content
|
||||
end
|
||||
|
||||
def test_controller_skeleton_is_created
|
||||
|
@ -66,8 +66,8 @@ class ControllerGeneratorTest < GeneratorsTestCase
|
|||
run_generator
|
||||
|
||||
assert_file "app/controllers/account_controller.rb" do |controller|
|
||||
assert_instance_method controller, :foo
|
||||
assert_instance_method controller, :bar
|
||||
assert_instance_method :foo, controller
|
||||
assert_instance_method :bar, controller
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -10,93 +10,17 @@ end
|
|||
Rails.application.config.root = Rails.root
|
||||
|
||||
require 'rails/generators'
|
||||
require 'rails/generators/test_case'
|
||||
|
||||
require 'rubygems'
|
||||
require 'active_record'
|
||||
require 'action_dispatch'
|
||||
|
||||
CURRENT_PATH = File.expand_path(Dir.pwd)
|
||||
Rails::Generators.no_color!
|
||||
|
||||
class GeneratorsTestCase < ActiveSupport::TestCase
|
||||
include FileUtils
|
||||
|
||||
def destination_root
|
||||
File.join(Rails.root, "tmp")
|
||||
end
|
||||
|
||||
def setup
|
||||
cd CURRENT_PATH
|
||||
rm_rf(destination_root)
|
||||
mkdir_p(destination_root)
|
||||
end
|
||||
class GeneratorsTestCase < Rails::Generators::TestCase
|
||||
destination File.join(Rails.root, "tmp")
|
||||
setup :prepare_destination
|
||||
|
||||
def test_truth
|
||||
# don't complain, test/unit
|
||||
# Don't cry test unit
|
||||
end
|
||||
|
||||
def capture(stream)
|
||||
begin
|
||||
stream = stream.to_s
|
||||
eval "$#{stream} = StringIO.new"
|
||||
yield
|
||||
result = eval("$#{stream}").string
|
||||
ensure
|
||||
eval("$#{stream} = #{stream.upcase}")
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
alias :silence :capture
|
||||
|
||||
def assert_file(relative, *contents)
|
||||
absolute = File.join(destination_root, relative)
|
||||
assert File.exists?(absolute), "Expected file #{relative.inspect} to exist, but does not"
|
||||
|
||||
read = File.read(absolute) if block_given? || !contents.empty?
|
||||
yield read if block_given?
|
||||
|
||||
contents.each do |content|
|
||||
case content
|
||||
when String
|
||||
assert_equal content, read
|
||||
when Regexp
|
||||
assert_match content, read
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def assert_no_file(relative)
|
||||
absolute = File.join(destination_root, relative)
|
||||
assert !File.exists?(absolute), "Expected file #{relative.inspect} to not exist, but does"
|
||||
end
|
||||
|
||||
def assert_migration(relative, *contents, &block)
|
||||
file_name = migration_file_name(relative)
|
||||
assert file_name, "Expected migration #{relative} to exist, but was not found"
|
||||
assert_file File.join(File.dirname(relative), file_name), *contents, &block
|
||||
end
|
||||
|
||||
def assert_no_migration(relative)
|
||||
file_name = migration_file_name(relative)
|
||||
assert_nil file_name, "Expected migration #{relative} to not exist, but found #{file_name}"
|
||||
end
|
||||
|
||||
def assert_class_method(content, method, &block)
|
||||
assert_instance_method content, "self.#{method}", &block
|
||||
end
|
||||
|
||||
def assert_instance_method(content, method)
|
||||
assert content =~ /def #{method}(\(.+\))?(.*?)\n end/m, "Expected to have method #{method}"
|
||||
yield $2.strip if block_given?
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def migration_file_name(relative)
|
||||
absolute = File.join(destination_root, relative)
|
||||
dirname, file_name = File.dirname(absolute), File.basename(absolute).sub(/\.rb$/, '')
|
||||
|
||||
migration = Dir.glob("#{dirname}/[0-9]*_*.rb").grep(/\d+_#{file_name}.rb$/).first
|
||||
File.basename(migration) if migration
|
||||
end
|
||||
end
|
||||
end
|
|
@ -21,12 +21,12 @@ class MigrationGeneratorTest < GeneratorsTestCase
|
|||
run_generator [@migration, "title:string", "body:text"]
|
||||
|
||||
assert_migration "db/migrate/#{@migration}.rb" do |content|
|
||||
assert_class_method content, :up do |up|
|
||||
assert_class_method :up, content do |up|
|
||||
assert_match /add_column :posts, :title, :string/, up
|
||||
assert_match /add_column :posts, :body, :text/, up
|
||||
end
|
||||
|
||||
assert_class_method content, :down do |down|
|
||||
assert_class_method :down, content do |down|
|
||||
assert_match /remove_column :posts, :title/, down
|
||||
assert_match /remove_column :posts, :body/, down
|
||||
end
|
||||
|
@ -38,12 +38,12 @@ class MigrationGeneratorTest < GeneratorsTestCase
|
|||
run_generator [@migration, "title:string", "body:text"]
|
||||
|
||||
assert_migration "db/migrate/#{@migration}.rb" do |content|
|
||||
assert_class_method content, :up do |up|
|
||||
assert_class_method :up, content do |up|
|
||||
assert_match /remove_column :posts, :title/, up
|
||||
assert_match /remove_column :posts, :body/, up
|
||||
end
|
||||
|
||||
assert_class_method content, :down do |down|
|
||||
assert_class_method :down, content do |down|
|
||||
assert_match /add_column :posts, :title, :string/, down
|
||||
assert_match /add_column :posts, :body, :text/, down
|
||||
end
|
||||
|
|
|
@ -84,13 +84,13 @@ class ModelGeneratorTest < GeneratorsTestCase
|
|||
run_generator ["product", "name:string", "supplier_id:integer"]
|
||||
|
||||
assert_migration "db/migrate/create_products.rb" do |m|
|
||||
assert_class_method m, :up do |up|
|
||||
assert_class_method :up, m do |up|
|
||||
assert_match /create_table :products/, up
|
||||
assert_match /t\.string :name/, up
|
||||
assert_match /t\.integer :supplier_id/, up
|
||||
end
|
||||
|
||||
assert_class_method m, :down do |down|
|
||||
assert_class_method :down, m do |down|
|
||||
assert_match /drop_table :products/, down
|
||||
end
|
||||
end
|
||||
|
@ -126,7 +126,7 @@ class ModelGeneratorTest < GeneratorsTestCase
|
|||
run_generator ["account", "--no-timestamps"]
|
||||
|
||||
assert_migration "db/migrate/create_accounts.rb" do |m|
|
||||
assert_class_method m, :up do |up|
|
||||
assert_class_method :up, m do |up|
|
||||
assert_no_match /t.timestamps/, up
|
||||
end
|
||||
end
|
||||
|
|
|
@ -50,8 +50,8 @@ class ResourceGeneratorTest < GeneratorsTestCase
|
|||
run_generator ["account", "--actions", "index", "new"]
|
||||
|
||||
assert_file "app/controllers/accounts_controller.rb" do |controller|
|
||||
assert_instance_method controller, :index
|
||||
assert_instance_method controller, :new
|
||||
assert_instance_method :index, controller
|
||||
assert_instance_method :new, controller
|
||||
end
|
||||
|
||||
assert_file "app/views/accounts/index.html.erb"
|
||||
|
|
|
@ -15,35 +15,35 @@ class ScaffoldControllerGeneratorTest < GeneratorsTestCase
|
|||
assert_file "app/controllers/users_controller.rb" do |content|
|
||||
assert_match /class UsersController < ApplicationController/, content
|
||||
|
||||
assert_instance_method content, :index do |m|
|
||||
assert_instance_method :index, content do |m|
|
||||
assert_match /@users = User\.all/, m
|
||||
end
|
||||
|
||||
assert_instance_method content, :show do |m|
|
||||
assert_instance_method :show, content do |m|
|
||||
assert_match /@user = User\.find\(params\[:id\]\)/, m
|
||||
end
|
||||
|
||||
assert_instance_method content, :new do |m|
|
||||
assert_instance_method :new, content do |m|
|
||||
assert_match /@user = User\.new/, m
|
||||
end
|
||||
|
||||
assert_instance_method content, :edit do |m|
|
||||
assert_instance_method :edit, content do |m|
|
||||
assert_match /@user = User\.find\(params\[:id\]\)/, m
|
||||
end
|
||||
|
||||
assert_instance_method content, :create do |m|
|
||||
assert_instance_method :create, content do |m|
|
||||
assert_match /@user = User\.new\(params\[:user\]\)/, m
|
||||
assert_match /@user\.save/, m
|
||||
assert_match /@user\.errors/, m
|
||||
end
|
||||
|
||||
assert_instance_method content, :update do |m|
|
||||
assert_instance_method :update, content do |m|
|
||||
assert_match /@user = User\.find\(params\[:id\]\)/, m
|
||||
assert_match /@user\.update_attributes\(params\[:user\]\)/, m
|
||||
assert_match /@user\.errors/, m
|
||||
end
|
||||
|
||||
assert_instance_method content, :destroy do |m|
|
||||
assert_instance_method :destroy, content do |m|
|
||||
assert_match /@user = User\.find\(params\[:id\]\)/, m
|
||||
assert_match /@user\.destroy/, m
|
||||
end
|
||||
|
@ -108,7 +108,7 @@ class ScaffoldControllerGeneratorTest < GeneratorsTestCase
|
|||
assert_file "app/controllers/users_controller.rb" do |content|
|
||||
assert_match /class UsersController < ApplicationController/, content
|
||||
|
||||
assert_instance_method content, :index do |m|
|
||||
assert_instance_method :index, content do |m|
|
||||
assert_match /@users = User\.all/, m
|
||||
end
|
||||
end
|
||||
|
@ -127,7 +127,7 @@ class ScaffoldControllerGeneratorTest < GeneratorsTestCase
|
|||
assert_file "app/controllers/users_controller.rb" do |content|
|
||||
assert_match /class UsersController < ApplicationController/, content
|
||||
|
||||
assert_instance_method content, :index do |m|
|
||||
assert_instance_method :index, content do |m|
|
||||
assert_match /@users = User\.find\(:all\)/, m
|
||||
assert_no_match /@users = User\.all/, m
|
||||
end
|
||||
|
|
|
@ -32,35 +32,35 @@ class ScaffoldGeneratorTest < GeneratorsTestCase
|
|||
assert_file "app/controllers/product_lines_controller.rb" do |content|
|
||||
assert_match /class ProductLinesController < ApplicationController/, content
|
||||
|
||||
assert_instance_method content, :index do |m|
|
||||
assert_instance_method :index, content do |m|
|
||||
assert_match /@product_lines = ProductLine\.all/, m
|
||||
end
|
||||
|
||||
assert_instance_method content, :show do |m|
|
||||
assert_instance_method :show, content do |m|
|
||||
assert_match /@product_line = ProductLine\.find\(params\[:id\]\)/, m
|
||||
end
|
||||
|
||||
assert_instance_method content, :new do |m|
|
||||
assert_instance_method :new, content do |m|
|
||||
assert_match /@product_line = ProductLine\.new/, m
|
||||
end
|
||||
|
||||
assert_instance_method content, :edit do |m|
|
||||
assert_instance_method :edit, content do |m|
|
||||
assert_match /@product_line = ProductLine\.find\(params\[:id\]\)/, m
|
||||
end
|
||||
|
||||
assert_instance_method content, :create do |m|
|
||||
assert_instance_method :create, content do |m|
|
||||
assert_match /@product_line = ProductLine\.new\(params\[:product_line\]\)/, m
|
||||
assert_match /@product_line\.save/, m
|
||||
assert_match /@product_line\.errors/, m
|
||||
end
|
||||
|
||||
assert_instance_method content, :update do |m|
|
||||
assert_instance_method :update, content do |m|
|
||||
assert_match /@product_line = ProductLine\.find\(params\[:id\]\)/, m
|
||||
assert_match /@product_line\.update_attributes\(params\[:product_line\]\)/, m
|
||||
assert_match /@product_line\.errors/, m
|
||||
end
|
||||
|
||||
assert_instance_method content, :destroy do |m|
|
||||
assert_instance_method :destroy, content do |m|
|
||||
assert_match /@product_line = ProductLine\.find\(params\[:id\]\)/, m
|
||||
assert_match /@product_line\.destroy/, m
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue