Skip to content

Commit

Permalink
Add helper test generators [#1199 state:resolved]
Browse files Browse the repository at this point in the history
Signed-off-by: Joshua Peek <josh@joshpeek.com>
  • Loading branch information
eugenebolshakov authored and josh committed Nov 18, 2008
1 parent d22fe41 commit 3c9beb3
Show file tree
Hide file tree
Showing 18 changed files with 179 additions and 45 deletions.
23 changes: 12 additions & 11 deletions railties/lib/rails_generator/generators/components/controller/USAGE
Expand Up @@ -6,24 +6,25 @@ Description:
path like 'parent_module/controller_name'.

This generates a controller class in app/controllers, view templates in
app/views/controller_name, a helper class in app/helpers, and a functional
test suite in test/functional.
app/views/controller_name, a helper class in app/helpers, a functional
test suite in test/functional and a helper test suite in test/unit/helpers.

Example:
`./script/generate controller CreditCard open debit credit close`

Credit card controller with URLs like /credit_card/debit.
Controller: app/controllers/credit_card_controller.rb
Views: app/views/credit_card/debit.html.erb [...]
Helper: app/helpers/credit_card_helper.rb
Test: test/functional/credit_card_controller_test.rb
Controller: app/controllers/credit_card_controller.rb
Functional Test: test/functional/credit_card_controller_test.rb
Views: app/views/credit_card/debit.html.erb [...]
Helper: app/helpers/credit_card_helper.rb
Helper Test: test/unit/helpers/credit_card_helper_test.rb

Modules Example:
`./script/generate controller 'admin/credit_card' suspend late_fee`

Credit card admin controller with URLs /admin/credit_card/suspend.
Controller: app/controllers/admin/credit_card_controller.rb
Views: app/views/admin/credit_card/debit.html.erb [...]
Helper: app/helpers/admin/credit_card_helper.rb
Test: test/functional/admin/credit_card_controller_test.rb

Controller: app/controllers/admin/credit_card_controller.rb
Functional Test: test/functional/admin/credit_card_controller_test.rb
Views: app/views/admin/credit_card/debit.html.erb [...]
Helper: app/helpers/admin/credit_card_helper.rb
Helper Test: test/unit/helpers/admin/credit_card_helper_test.rb
Expand Up @@ -2,13 +2,14 @@ class ControllerGenerator < Rails::Generator::NamedBase
def manifest
record do |m|
# Check for class naming collisions.
m.class_collisions "#{class_name}Controller", "#{class_name}ControllerTest", "#{class_name}Helper"
m.class_collisions "#{class_name}Controller", "#{class_name}ControllerTest", "#{class_name}Helper", "#{class_name}HelperTest"

# Controller, helper, views, and test directories.
m.directory File.join('app/controllers', class_path)
m.directory File.join('app/helpers', class_path)
m.directory File.join('app/views', class_path, file_name)
m.directory File.join('test/functional', class_path)
m.directory File.join('test/unit/helpers', class_path)

# Controller class, functional test, and helper class.
m.template 'controller.rb',
Expand All @@ -26,6 +27,11 @@ def manifest
class_path,
"#{file_name}_helper.rb")

m.template 'helper_test.rb',
File.join('test/unit/helpers',
class_path,
"#{file_name}_helper_test.rb")

# View template for each action.
actions.each do |action|
path = File.join('app/views', class_path, file_name, "#{action}.html.erb")
Expand Down
@@ -0,0 +1,4 @@
require 'test_helper'

class <%= class_name %>HelperTest < ActionView::TestCase
end
24 changes: 24 additions & 0 deletions railties/lib/rails_generator/generators/components/helper/USAGE
@@ -0,0 +1,24 @@
Description:
Stubs out a new helper. Pass the helper name, either
CamelCased or under_scored.

To create a helper within a module, specify the helper name as a
path like 'parent_module/helper_name'.

This generates a helper class in app/helpers and a helper test
suite in test/unit/helpers.

Example:
`./script/generate helper CreditCard`

Credit card helper.
Helper: app/helpers/credit_card_helper.rb
Test: test/unit/helpers/credit_card_helper_test.rb

Modules Example:
`./script/generate helper 'admin/credit_card'`

Credit card admin helper.
Helper: app/helpers/admin/credit_card_helper.rb
Test: test/unit/helpers/admin/credit_card_helper_test.rb

@@ -0,0 +1,25 @@
class HelperGenerator < Rails::Generator::NamedBase
def manifest
record do |m|
# Check for class naming collisions.
m.class_collisions class_path, "#{class_name}Helper", "#{class_name}HelperTest"

# Helper and helper test directories.
m.directory File.join('app/helpers', class_path)
m.directory File.join('test/unit/helpers', class_path)

# Helper and helper test class.

m.template 'helper.rb',
File.join('app/helpers',
class_path,
"#{file_name}_helper.rb")

m.template 'helper_test.rb',
File.join('test/unit/helpers',
class_path,
"#{file_name}_helper_test.rb")

end
end
end
@@ -0,0 +1,2 @@
module <%= class_name %>Helper
end
@@ -0,0 +1,4 @@
require 'test_helper'

class <%= class_name %>HelperTest < ActionView::TestCase
end
Expand Up @@ -11,8 +11,8 @@ Description:
You don't have to think up every attribute up front, but it helps to
sketch out a few so you can start working with the resource immediately.

This creates a model, controller, tests and fixtures for both, and the
corresponding map.resources declaration in config/routes.rb
This creates a model, controller, helper, tests and fixtures for all of them,
and the corresponding map.resources declaration in config/routes.rb

Unlike the scaffold generator, the resource generator does not create
views or add any methods to the generated controller.
Expand Down
Expand Up @@ -40,6 +40,7 @@ def manifest
m.directory(File.join('app/views', controller_class_path, controller_file_name))
m.directory(File.join('test/functional', controller_class_path))
m.directory(File.join('test/unit', class_path))
m.directory(File.join('test/unit/helpers', class_path))

m.dependency 'model', [name] + @args, :collision => :skip

Expand All @@ -49,6 +50,7 @@ def manifest

m.template('functional_test.rb', File.join('test/functional', controller_class_path, "#{controller_file_name}_controller_test.rb"))
m.template('helper.rb', File.join('app/helpers', controller_class_path, "#{controller_file_name}_helper.rb"))
m.template('helper_test.rb', File.join('test/unit/helpers', controller_class_path, "#{controller_file_name}_helper_test.rb"))

m.route_resources controller_file_name
end
Expand Down
@@ -0,0 +1,4 @@
require 'test_helper'

class <%= controller_class_name %>HelperTest < ActionView::TestCase
end
Expand Up @@ -47,6 +47,7 @@ def manifest
m.directory(File.join('app/views/layouts', controller_class_path))
m.directory(File.join('test/functional', controller_class_path))
m.directory(File.join('test/unit', class_path))
m.directory(File.join('test/unit/helpers', class_path))
m.directory(File.join('public/stylesheets', class_path))

for action in scaffold_views
Expand All @@ -66,6 +67,7 @@ def manifest

m.template('functional_test.rb', File.join('test/functional', controller_class_path, "#{controller_file_name}_controller_test.rb"))
m.template('helper.rb', File.join('app/helpers', controller_class_path, "#{controller_file_name}_helper.rb"))
m.template('helper_test.rb', File.join('test/unit/helpers', controller_class_path, "#{controller_file_name}_helper_test.rb"))

m.route_resources controller_file_name

Expand Down
@@ -0,0 +1,4 @@
require 'test_helper'

class <%= controller_class_name %>HelperTest < ActionView::TestCase
end
8 changes: 4 additions & 4 deletions railties/lib/tasks/testing.rake
Expand Up @@ -7,7 +7,7 @@ def recent_tests(source_pattern, test_path, touched_since = 10.minutes.ago)
tests = []
source_dir = File.dirname(path).split("/")
source_file = File.basename(path, '.rb')

# Support subdirs in app/models and app/controllers
modified_test_path = source_dir.length > 2 ? "#{test_path}/" << source_dir[1..source_dir.length].join('/') : test_path

Expand All @@ -18,7 +18,7 @@ def recent_tests(source_pattern, test_path, touched_since = 10.minutes.ago)
# For modified files in app, run tests in subdirs too. ex. /test/functional/account/*_test.rb
test = "#{modified_test_path}/#{File.basename(path, '.rb').sub("_controller","")}"
FileList["#{test}/*_test.rb"].each { |f| tests.push f } if File.exist?(test)

return tests

end
Expand Down Expand Up @@ -63,7 +63,7 @@ namespace :test do
t.test_files = touched.uniq
end
Rake::Task['test:recent'].comment = "Test recent changes"

Rake::TestTask.new(:uncommitted => "db:test:prepare") do |t|
def t.file_list
if File.directory?(".svn")
Expand All @@ -82,7 +82,7 @@ namespace :test do

unit_tests.uniq + functional_tests.uniq
end

t.libs << 'test'
t.verbose = true
end
Expand Down
31 changes: 23 additions & 8 deletions railties/test/generators/generator_test_helper.rb
Expand Up @@ -145,6 +145,19 @@ def assert_generated_functional_test_for(name, parent = "ActionController::TestC
end
end

# Asserts that the given helper test test was generated.
# It takes a name or symbol without the <tt>_helper_test</tt> part and an optional super class.
# The contents of the class source file is passed to a block.
def assert_generated_helper_test_for(name, parent = "ActionView::TestCase")
path = "test/unit/helpers/#{name.to_s.underscore}_helper_test"
# Have to pass the path without the "test/" part so that class_name_from_path will return a correct result
class_name = class_name_from_path(path.gsub(/^test\//, ''))

assert_generated_class path,parent,class_name do |body|
yield body if block_given?
end
end

# Asserts that the given unit test was generated.
# It takes a name or symbol without the <tt>_test</tt> part and an optional super class.
# The contents of the class source file is passed to a block.
Expand Down Expand Up @@ -172,19 +185,21 @@ def assert_file_exists(path)
# Asserts that the given class source file was generated.
# It takes a path without the <tt>.rb</tt> part and an optional super class.
# The contents of the class source file is passed to a block.
def assert_generated_class(path, parent = nil)
def assert_generated_class(path, parent = nil, class_name = class_name_from_path(path))
assert_generated_file("#{path}.rb") do |body|
assert_match /class #{class_name}#{parent.nil? ? '':" < #{parent}"}/, body, "the file '#{path}.rb' should be a class"
yield body if block_given?
end
end

def class_name_from_path(path)
# FIXME: Sucky way to detect namespaced classes
if path.split('/').size > 3
path =~ /\/?(\d+_)?(\w+)\/(\w+)$/
class_name = "#{$2.camelize}::#{$3.camelize}"
"#{$2.camelize}::#{$3.camelize}"
else
path =~ /\/?(\d+_)?(\w+)$/
class_name = $2.camelize
end

assert_generated_file("#{path}.rb") do |body|
assert_match /class #{class_name}#{parent.nil? ? '':" < #{parent}"}/, body, "the file '#{path}.rb' should be a class"
yield body if block_given?
$2.camelize
end
end

Expand Down
32 changes: 17 additions & 15 deletions railties/test/generators/rails_controller_generator_test.rb
Expand Up @@ -11,6 +11,7 @@ def test_controller_generates_controller
assert_generated_controller_for :products
assert_generated_functional_test_for :products
assert_generated_helper_for :products
assert_generated_helper_test_for :products
end

def test_controller_generates_namespaced_controller
Expand All @@ -19,24 +20,25 @@ def test_controller_generates_namespaced_controller
assert_generated_controller_for "admin::products"
assert_generated_functional_test_for "admin::products"
assert_generated_helper_for "admin::products"
assert_generated_helper_test_for "admin::products"
end

def test_controller_generates_namespaced_and_not_namespaced_controllers
run_generator('controller', %w(products))

# We have to require the generated helper to show the problem because
# the test helpers just check for generated files and contents but
# do not actually load them. But they have to be loaded (as in a real environment)
# to make the second generator run fail
require "#{RAILS_ROOT}/app/helpers/products_helper"

assert_nothing_raised do
begin
run_generator('controller', %w(admin::products))
ensure
# cleanup
Object.send(:remove_const, :ProductsHelper)
end
run_generator('controller', %w(products))

# We have to require the generated helper to show the problem because
# the test helpers just check for generated files and contents but
# do not actually load them. But they have to be loaded (as in a real environment)
# to make the second generator run fail
require "#{RAILS_ROOT}/app/helpers/products_helper"

assert_nothing_raised do
begin
run_generator('controller', %w(admin::products))
ensure
# cleanup
Object.send(:remove_const, :ProductsHelper)
end
end
end
end
36 changes: 36 additions & 0 deletions railties/test/generators/rails_helper_generator_test.rb
@@ -0,0 +1,36 @@
require File.dirname(__FILE__) + '/generator_test_helper'

class RailsHelperGeneratorTest < GeneratorTestCase
def test_helper_generates_helper
run_generator('helper', %w(products))

assert_generated_helper_for :products
assert_generated_helper_test_for :products
end

def test_helper_generates_namespaced_helper
run_generator('helper', %w(admin::products))

assert_generated_helper_for "admin::products"
assert_generated_helper_test_for "admin::products"
end

def test_helper_generates_namespaced_and_not_namespaced_helpers
run_generator('helper', %w(products))

# We have to require the generated helper to show the problem because
# the test helpers just check for generated files and contents but
# do not actually load them. But they have to be loaded (as in a real environment)
# to make the second generator run fail
require "#{RAILS_ROOT}/app/helpers/products_helper"

assert_nothing_raised do
begin
run_generator('helper', %w(admin::products))
ensure
# cleanup
Object.send(:remove_const, :ProductsHelper)
end
end
end
end
4 changes: 2 additions & 2 deletions railties/test/generators/rails_resource_generator_test.rb
@@ -1,7 +1,6 @@
require 'generators/generator_test_helper'

class RailsResourceGeneratorTest < GeneratorTestCase

def test_resource_generates_resources
run_generator('resource', %w(Product name:string))

Expand All @@ -10,6 +9,7 @@ def test_resource_generates_resources
assert_generated_fixtures_for :products
assert_generated_functional_test_for :products
assert_generated_helper_for :products
assert_generated_helper_test_for :products
assert_generated_migration :create_products
assert_added_route_for :products
end
Expand All @@ -22,8 +22,8 @@ def test_resource_skip_migration_skips_migration
assert_generated_fixtures_for :products
assert_generated_functional_test_for :products
assert_generated_helper_for :products
assert_generated_helper_test_for :products
assert_skipped_migration :create_products
assert_added_route_for :products
end

end

0 comments on commit 3c9beb3

Please sign in to comment.