Reorganize unit tests, part II

* Change 'spec' Rake task to 'spec:unit'
* Require unit_spec_helper.rb in unit tests, not spec_helper.rb
* Re-namespace files in spec/support/unit under UnitTests
* Files in spec/support/unit/helpers no longer automatically add
  themselves to RSpec - this happens in unit_spec_helper.rb
* Extract RecordWithDifferentErrorAttributeBuilder and
  RecordValidatingConfirmationBuilder to separate files
This commit is contained in:
Elliot Winkler 2014-10-26 18:51:42 -06:00
parent bbdf8a807e
commit f922613386
69 changed files with 719 additions and 662 deletions

View File

@ -8,9 +8,9 @@ require_relative 'lib/shoulda/matchers/version'
CURRENT_VERSION = Shoulda::Matchers::VERSION
RSpec::Core::RakeTask.new do |t|
RSpec::Core::RakeTask.new('spec:unit') do |t|
t.ruby_opts = '-w -r ./spec/report_warnings'
t.pattern = "spec/**/*_spec.rb"
t.pattern = "spec/unit/**/*_spec.rb"
t.rspec_opts = '--color --format progress'
t.verbose = false
end
@ -30,7 +30,7 @@ end
task :default do
if ENV['BUNDLE_GEMFILE'] =~ /gemfiles/
Rake::Task['spec'].invoke
sh 'rake spec:unit'
Rake::Task['cucumber'].invoke
else
Rake::Task['appraise'].invoke

View File

@ -1,23 +1,25 @@
module ActiveModelHelpers
def custom_validation(options = {}, &block)
attribute_name = options.fetch(:attribute_name, :attr)
attribute_type = options.fetch(:attribute_type, :integer)
module UnitTests
module ActiveModelHelpers
def self.configure_example_group(example_group)
example_group.include(self)
end
define_model(:example, attribute_name => attribute_type) do
validate :custom_validation
def custom_validation(options = {}, &block)
attribute_name = options.fetch(:attribute_name, :attr)
attribute_type = options.fetch(:attribute_type, :integer)
define_method(:custom_validation, &block)
end.new
end
alias record_with_custom_validation custom_validation
define_model(:example, attribute_name => attribute_type) do
validate :custom_validation
def validating_format(options)
define_model :example, attr: :string do
validates_format_of :attr, options
end.new
define_method(:custom_validation, &block)
end.new
end
alias record_with_custom_validation custom_validation
def validating_format(options)
define_model :example, attr: :string do
validates_format_of :attr, options
end.new
end
end
end
RSpec.configure do |c|
c.include ActiveModelHelpers
end

View File

@ -1,13 +1,20 @@
RSpec.configure do |c|
def active_model_3_1?
(::ActiveModel::VERSION::MAJOR == 3 && ::ActiveModel::VERSION::MINOR >= 1) || active_model_4_0?
end
module UnitTests
module ActiveModelVersions
def self.configure_example_group(example_group)
example_group.include(self)
example_group.extend(self)
end
def active_model_3_2?
(::ActiveModel::VERSION::MAJOR == 3 && ::ActiveModel::VERSION::MINOR >= 2) || active_model_4_0?
end
def active_model_3_1?
(::ActiveModel::VERSION::MAJOR == 3 && ::ActiveModel::VERSION::MINOR >= 1) || active_model_4_0?
end
def active_model_4_0?
::ActiveModel::VERSION::MAJOR == 4
def active_model_3_2?
(::ActiveModel::VERSION::MAJOR == 3 && ::ActiveModel::VERSION::MINOR >= 2) || active_model_4_0?
end
def active_model_4_0?
::ActiveModel::VERSION::MAJOR == 4
end
end
end

View File

@ -1,29 +1,27 @@
require 'active_resource'
module ActiveResourceBuilder
def self.included(example_group)
example_group.class_eval do
after do
module UnitTests
module ActiveResourceBuilder
def self.configure_example_group(example_group)
example_group.include ActiveResourceBuilder
example_group.after do
ActiveSupport::Dependencies.clear
end
end
end
def define_active_resource_class(class_name, attributes = {}, &block)
define_class(class_name, ActiveResource::Base) do
schema do
attributes.each do |attr, type|
attribute attr, type
def define_active_resource_class(class_name, attributes = {}, &block)
define_class(class_name, ActiveResource::Base) do
schema do
attributes.each do |attr, type|
attribute attr, type
end
end
end
if block_given?
class_eval(&block)
if block_given?
class_eval(&block)
end
end
end
end
end
RSpec.configure do |config|
config.include ActiveResourceBuilder
end

View File

@ -1,6 +1,7 @@
require_relative '../model_builder'
require_relative '../record_with_different_error_attribute_builder'
require_relative '../record_builder_with_i18n_validation_message'
module Helpers
module UnitTests
module AllowValueMatcherHelpers
def builder_for_record_with_different_error_attribute(options = {})
RecordWithDifferentErrorAttributeBuilder.new(options)
@ -10,94 +11,5 @@ module Helpers
builder = builder_for_record_with_different_error_attribute(options)
RecordBuilderWithI18nValidationMessage.new(builder)
end
class RecordWithDifferentErrorAttributeBuilder
include ModelBuilder
def initialize(options)
@options = options.reverse_merge(default_options)
end
def attribute_that_receives_error
options[:attribute_that_receives_error]
end
def attribute_to_validate
options[:attribute_to_validate]
end
def message
options[:message]
end
def message=(message)
options[:message] = message
end
def model
@_model ||= create_model
end
def model_name
'Example'
end
def record
model.new
end
def valid_value
'some value'
end
protected
attr_reader :options
private
def context
{
validation_method_name: validation_method_name,
valid_value: valid_value,
attribute_to_validate: attribute_to_validate,
attribute_that_receives_error: attribute_that_receives_error,
message: message
}
end
def create_model
_context = context
define_model model_name, model_columns do
validate _context[:validation_method_name]
define_method(_context[:validation_method_name]) do
if self[_context[:attribute_to_validate]] != _context[:valid_value]
self.errors.add(_context[:attribute_that_receives_error], _context[:message])
end
end
end
end
def validation_method_name
:custom_validation
end
def model_columns
{
attribute_to_validate => :string,
attribute_that_receives_error => :string
}
end
def default_options
{
attribute_that_receives_error: :attribute_that_receives_error,
attribute_to_validate: :attribute_to_validate,
message: 'some message'
}
end
end
end
end

View File

@ -1,69 +1,80 @@
module ClassBuilder
def self.parse_constant_name(name)
namespace = Shoulda::Matchers::Util.deconstantize(name)
qualified_namespace = (namespace.presence || 'Object').constantize
name_without_namespace = name.to_s.demodulize
[qualified_namespace, name_without_namespace]
end
def self.teardown_defined_constants
ActiveSupport::Dependencies.clear
end
def define_module(module_name, &block)
module_name = module_name.to_s.camelize
namespace, name_without_namespace =
ClassBuilder.parse_constant_name(module_name)
if namespace.const_defined?(name_without_namespace, false)
namespace.__send__(:remove_const, name_without_namespace)
module UnitTests
module ClassBuilder
def self.parse_constant_name(name)
namespace = Shoulda::Matchers::Util.deconstantize(name)
qualified_namespace = (namespace.presence || 'Object').constantize
name_without_namespace = name.to_s.demodulize
[qualified_namespace, name_without_namespace]
end
eval <<-RUBY
module #{namespace}::#{name_without_namespace}
end
RUBY
def self.configure_example_group(example_group)
example_group.include(self)
namespace.const_get(name_without_namespace).tap do |constant|
constant.unloadable
if block
constant.module_eval(&block)
example_group.after do
teardown_defined_constants
end
end
end
def define_class(class_name, parent_class = Object, &block)
class_name = class_name.to_s.camelize
def define_module(module_name, &block)
module_name = module_name.to_s.camelize
namespace, name_without_namespace =
ClassBuilder.parse_constant_name(class_name)
namespace, name_without_namespace =
ClassBuilder.parse_constant_name(module_name)
if namespace.const_defined?(name_without_namespace, false)
namespace.__send__(:remove_const, name_without_namespace)
if namespace.const_defined?(name_without_namespace, false)
namespace.__send__(:remove_const, name_without_namespace)
end
eval <<-RUBY
module #{namespace}::#{name_without_namespace}
end
RUBY
namespace.const_get(name_without_namespace).tap do |constant|
constant.unloadable
if block
constant.module_eval(&block)
end
end
end
eval <<-RUBY
class #{namespace}::#{name_without_namespace} < #{parent_class}
end
RUBY
def define_class(class_name, parent_class = Object, &block)
class_name = class_name.to_s.camelize
namespace.const_get(name_without_namespace).tap do |constant|
constant.unloadable
namespace, name_without_namespace =
ClassBuilder.parse_constant_name(class_name)
if block_given?
constant.class_eval(&block)
if namespace.const_defined?(name_without_namespace, false)
namespace.__send__(:remove_const, name_without_namespace)
end
if constant.respond_to?(:reset_column_information)
constant.reset_column_information
eval <<-RUBY
class #{namespace}::#{name_without_namespace} < #{parent_class}
end
RUBY
namespace.const_get(name_without_namespace).tap do |constant|
constant.unloadable
if block_given?
constant.class_eval(&block)
end
if constant.respond_to?(:reset_column_information)
constant.reset_column_information
end
end
end
private
def teardown_defined_constants
ActiveSupport::Dependencies.clear
end
def teardown_defined_constants
ActiveSupport::Dependencies.clear
end
end
end
RSpec.configure do |config|
config.include ClassBuilder
config.after { ClassBuilder.teardown_defined_constants }
end

View File

@ -1,6 +1,7 @@
require_relative '../model_builder'
require_relative '../record_validating_confirmation_builder'
require_relative '../record_builder_with_i18n_validation_message'
module Helpers
module UnitTests
module ConfirmationMatcherHelpers
def builder_for_record_validating_confirmation(options = {})
RecordValidatingConfirmationBuilder.new(options)
@ -12,58 +13,5 @@ module Helpers
validation_message_key: :confirmation
)
end
class RecordValidatingConfirmationBuilder
include ModelBuilder
def initialize(options)
@options = options
end
def model
@_model ||= create_model
end
def model_name
'Example'
end
def record
model.new
end
def message=(message)
options[:message] = message
end
def attribute_to_confirm
:attribute_to_confirm
end
alias_method :attribute, :attribute_to_confirm
def confirmation_attribute
:"#{attribute_to_confirm}_confirmation"
end
def attribute_that_receives_error
Shoulda::Matchers::RailsShim.
validates_confirmation_of_error_attribute(self)
end
protected
attr_reader :options
private
def create_model
_attribute = attribute_to_confirm
_options = options
define_model(model_name, _attribute => :string) do
validates_confirmation_of(_attribute, _options)
end
end
end
end
end

View File

@ -1,102 +1,98 @@
module ControllerBuilder
def self.included(example_group)
example_group.class_eval do
after do
module UnitTests
module ControllerBuilder
def self.configure_example_group(example_group)
example_group.include(self)
example_group.after do
delete_temporary_views
restore_original_routes
end
end
end
def define_controller(class_name, &block)
class_name = class_name.to_s
class_name << 'Controller' unless class_name =~ /Controller$/
define_class(class_name, ActionController::Base, &block)
end
def define_routes(&block)
@routes = $test_app.draw_routes(&block)
class << self
include ActionDispatch::Assertions
end
end
def build_fake_response(opts = {}, &block)
action = opts[:action] || 'example'
partial = opts[:partial] || '_partial'
block ||= lambda { render nothing: true }
controller_class = define_controller('Examples') do
layout false
define_method(action, &block)
end
controller_class.view_paths = [ $test_app.temp_views_dir_path ]
define_routes do
get 'examples', to: "examples##{action}"
def define_controller(class_name, &block)
class_name = class_name.to_s
class_name << 'Controller' unless class_name =~ /Controller$/
define_class(class_name, ActionController::Base, &block)
end
create_view("examples/#{action}.html.erb", 'action')
create_view("examples/#{partial}.html.erb", 'partial')
setup_rails_controller_test(controller_class)
get action
@controller
end
def setup_rails_controller_test(controller_class)
@controller = controller_class.new
@request = ::ActionController::TestRequest.new
@response = ::ActionController::TestResponse.new
class << self
include ActionController::TestCase::Behavior
end
end
def create_view(path, contents)
$test_app.create_temp_view(path, contents)
end
def controller_for_resource_with_strong_parameters(options = {}, &action_body)
model_name = options.fetch(:model_name, 'User')
controller_name = options.fetch(:controller_name, 'UsersController')
collection_name = controller_name.
to_s.sub(/Controller$/, '').underscore.
to_sym
action_name = options.fetch(:action, :some_action)
routes ||= options.fetch(:routes, -> { resources collection_name })
define_model(model_name)
controller_class = define_controller(controller_name) do
define_method action_name do
if action_body
instance_eval(&action_body)
end
render nothing: true
def define_routes(&block)
@routes = $test_app.draw_routes(&block)
class << self
include ActionDispatch::Assertions
end
end
setup_rails_controller_test(controller_class)
def build_fake_response(opts = {}, &block)
action = opts[:action] || 'example'
partial = opts[:partial] || '_partial'
block ||= lambda { render nothing: true }
controller_class = define_controller('Examples') do
layout false
define_method(action, &block)
end
controller_class.view_paths = [ $test_app.temp_views_directory.to_s ]
define_routes(&routes)
define_routes do
get 'examples', to: "examples##{action}"
end
controller_class
end
create_view("examples/#{action}.html.erb", 'action')
create_view("examples/#{partial}.html.erb", 'partial')
private
setup_rails_controller_test(controller_class)
get action
def delete_temporary_views
$test_app.delete_temp_views
end
@controller
end
def restore_original_routes
Rails.application.reload_routes!
def setup_rails_controller_test(controller_class)
@controller = controller_class.new
@request = ::ActionController::TestRequest.new
@response = ::ActionController::TestResponse.new
class << self
include ActionController::TestCase::Behavior
end
end
def create_view(path, contents)
$test_app.create_temp_view(path, contents)
end
def controller_for_resource_with_strong_parameters(options = {}, &action_body)
model_name = options.fetch(:model_name, 'User')
controller_name = options.fetch(:controller_name, 'UsersController')
collection_name = controller_name.
to_s.sub(/Controller$/, '').underscore.
to_sym
action_name = options.fetch(:action, :some_action)
routes ||= options.fetch(:routes, -> { resources collection_name })
define_model(model_name)
controller_class = define_controller(controller_name) do
define_method action_name do
if action_body
instance_eval(&action_body)
end
render nothing: true
end
end
setup_rails_controller_test(controller_class)
define_routes(&routes)
controller_class
end
def delete_temporary_views
$test_app.delete_temp_views
end
def restore_original_routes
Rails.application.reload_routes!
end
end
end
RSpec.configure do |config|
config.include ControllerBuilder
end

View File

@ -1,13 +1,15 @@
module I18nFaker
extend self
module UnitTests
module I18nFaker
extend self
def stub_translation(key_or_keys, message)
keys = [key_or_keys].flatten.join('.').split('.')
tree = keys.reverse.inject(message) { |data, key| { key => data } }
I18n.backend.store_translations(:en, tree)
def self.configure_example_group(example_group)
example_group.include(self)
end
def stub_translation(key_or_keys, message)
keys = [key_or_keys].flatten.join('.').split('.')
tree = keys.reverse.inject(message) { |data, key| { key => data } }
I18n.backend.store_translations(:en, tree)
end
end
end
RSpec.configure do |config|
config.include I18nFaker
end

View File

@ -1,10 +1,12 @@
module MailerBuilder
def define_mailer(name, paths, &block)
class_name = name.to_s.pluralize.classify
define_class(class_name, ActionMailer::Base, &block)
module UnitTests
module MailerBuilder
def self.configure_example_group(example_group)
example_group.include(self)
end
def define_mailer(name, paths, &block)
class_name = name.to_s.pluralize.classify
define_class(class_name, ActionMailer::Base, &block)
end
end
end
RSpec.configure do |config|
config.include MailerBuilder
end

View File

@ -1,91 +1,91 @@
require_relative 'class_builder'
module ModelBuilder
include ClassBuilder
module UnitTests
module ModelBuilder
include ClassBuilder
def self.drop_created_tables
connection = ActiveRecord::Base.connection
def self.configure_example_group(example_group)
example_group.include(self)
created_tables.each do |table_name|
connection.execute("DROP TABLE IF EXISTS #{table_name}")
end
end
def self.created_tables
@_created_tables ||= []
end
def create_table(table_name, options = {}, &block)
connection = ActiveRecord::Base.connection
begin
connection.execute("DROP TABLE IF EXISTS #{table_name}")
connection.create_table(table_name, options, &block)
ModelBuilder.created_tables << table_name
connection
rescue Exception => e
connection.execute("DROP TABLE IF EXISTS #{table_name}")
raise e
end
end
def define_model_class(class_name, &block)
define_class(class_name, ActiveRecord::Base, &block)
end
def define_active_model_class(class_name, options = {}, &block)
define_class(class_name) do
include ActiveModel::Validations
options[:accessors].each do |column|
attr_accessor column.to_sym
end
if block_given?
class_eval(&block)
example_group.after do
drop_created_tables
end
end
end
def define_model(name, columns = {}, &block)
class_name = name.to_s.pluralize.classify
table_name = class_name.tableize.gsub('/', '_')
def create_table(table_name, options = {}, &block)
connection = ActiveRecord::Base.connection
table_block = lambda do |table|
columns.each do |name, specification|
if specification.is_a?(Hash)
table.column name, specification[:type], specification[:options]
else
table.column name, specification
begin
connection.execute("DROP TABLE IF EXISTS #{table_name}")
connection.create_table(table_name, options, &block)
created_tables << table_name
connection
rescue Exception => e
connection.execute("DROP TABLE IF EXISTS #{table_name}")
raise e
end
end
def define_model_class(class_name, &block)
define_class(class_name, ActiveRecord::Base, &block)
end
def define_active_model_class(class_name, options = {}, &block)
define_class(class_name) do
include ActiveModel::Validations
options[:accessors].each do |column|
attr_accessor column.to_sym
end
if block_given?
class_eval(&block)
end
end
end
if columns.key?(:id) && columns[:id] == false
columns.delete(:id)
create_table(table_name, id: false, &table_block)
else
create_table(table_name, &table_block)
end
def define_model(name, columns = {}, &block)
class_name = name.to_s.pluralize.classify
table_name = class_name.tableize.gsub('/', '_')
define_model_class(class_name).tap do |model|
if block
model.class_eval(&block)
table_block = lambda do |table|
columns.each do |name, specification|
if specification.is_a?(Hash)
table.column name, specification[:type], specification[:options]
else
table.column name, specification
end
end
end
model.table_name = table_name
if columns.key?(:id) && columns[:id] == false
columns.delete(:id)
create_table(table_name, id: false, &table_block)
else
create_table(table_name, &table_block)
end
define_model_class(class_name).tap do |model|
if block
model.class_eval(&block)
end
model.table_name = table_name
end
end
private
def drop_created_tables
connection = ActiveRecord::Base.connection
created_tables.each do |table_name|
connection.execute("DROP TABLE IF EXISTS #{table_name}")
end
end
def created_tables
@_created_tables ||= []
end
end
end
RSpec.configure do |config|
config.include ModelBuilder
config.before do
ModelBuilder.created_tables.clear
end
config.after do
ModelBuilder.drop_created_tables
end
end

View File

@ -1,26 +1,28 @@
module RailsVersions
def rails_version
Gem::Version.new(Rails::VERSION::STRING)
end
module UnitTests
module RailsVersions
def self.configure_example_group(example_group)
example_group.include(self)
example_group.extend(self)
end
def rails_3_x?
Gem::Requirement.new('~> 3.0').satisfied_by?(rails_version)
end
def rails_version
Gem::Version.new(Rails::VERSION::STRING)
end
def rails_4_x?
Gem::Requirement.new('~> 4.0').satisfied_by?(rails_version)
end
def rails_3_x?
Gem::Requirement.new('~> 3.0').satisfied_by?(rails_version)
end
def rails_gte_4_1?
Gem::Requirement.new('>= 4.1').satisfied_by?(rails_version)
end
def rails_4_x?
Gem::Requirement.new('~> 4.0').satisfied_by?(rails_version)
end
def active_record_supports_enum?
defined?(::ActiveRecord::Enum)
def rails_gte_4_1?
Gem::Requirement.new('>= 4.1').satisfied_by?(rails_version)
end
def active_record_supports_enum?
defined?(::ActiveRecord::Enum)
end
end
end
RSpec.configure do |config|
config.include(RailsVersions)
config.extend(RailsVersions)
end

View File

@ -1,44 +1,50 @@
RSpec::Matchers.define :fail_with_message_including do |expected|
def supports_block_expectations?
true
end
module UnitTests
module Matchers
extend RSpec::Matchers::DSL
match do |block|
@actual = nil
matcher :fail_with_message_including do |expected|
def supports_block_expectations?
true
end
begin
block.call
rescue RSpec::Expectations::ExpectationNotMetError => ex
@actual = ex.message
match do |block|
@actual = nil
begin
block.call
rescue RSpec::Expectations::ExpectationNotMetError => ex
@actual = ex.message
end
@actual && @actual.include?(expected)
end
def failure_message
msg = "Expectation should have failed with message including '#{expected}'"
if @actual
msg << ", actually failed with '#{@actual}'"
else
msg << ", but did not fail."
end
msg
end
def failure_message_for_should
failure_message
end
def failure_message_when_negated
msg = "Expectation should not have failed with message including '#{expected}'"
msg << ", but did."
msg
end
def failure_message_for_should_not
failure_message_when_negated
end
end
@actual && @actual.include?(expected)
end
def failure_message
msg = "Expectation should have failed with message including '#{expected}'"
if @actual
msg << ", actually failed with '#{@actual}'"
else
msg << ", but did not fail."
end
msg
end
def failure_message_for_should
failure_message
end
def failure_message_when_negated
msg = "Expectation should not have failed with message including '#{expected}'"
msg << ", but did."
msg
end
def failure_message_for_should_not
failure_message_when_negated
end
end

View File

@ -1,44 +1,50 @@
RSpec::Matchers.define :fail_with_message do |expected|
def supports_block_expectations?
true
end
module UnitTests
module Matchers
extend RSpec::Matchers::DSL
match do |block|
@actual = nil
matcher :fail_with_message do |expected|
def supports_block_expectations?
true
end
begin
block.call
rescue RSpec::Expectations::ExpectationNotMetError => ex
@actual = ex.message
match do |block|
@actual = nil
begin
block.call
rescue RSpec::Expectations::ExpectationNotMetError => ex
@actual = ex.message
end
@actual && @actual == expected
end
def failure_message
msg = "Expectation should have failed with message '#{expected}'"
if @actual
msg << ", actually failed with '#{@actual}'"
else
msg << ", but did not fail."
end
msg
end
def failure_message_for_should
failure_message
end
def failure_message_when_negated
msg = "Expectation should not have failed with message '#{expected}'"
msg << ", but did."
msg
end
def failure_message_for_should_not
failure_message_when_negated
end
end
@actual && @actual == expected
end
def failure_message
msg = "Expectation should have failed with message '#{expected}'"
if @actual
msg << ", actually failed with '#{@actual}'"
else
msg << ", but did not fail."
end
msg
end
def failure_message_for_should
failure_message
end
def failure_message_when_negated
msg = "Expectation should not have failed with message '#{expected}'"
msg << ", but did."
msg
end
def failure_message_for_should_not
failure_message_when_negated
end
end

View File

@ -1,118 +1,120 @@
require 'fileutils'
class TestApplication
ROOT_DIR = File.expand_path('../../../tmp/aruba/testapp', __FILE__)
module UnitTests
class TestApplication
ROOT_DIR = File.expand_path('../../../tmp/aruba/testapp', __FILE__)
def create
clean
generate
within_app { install_gems }
end
def create
clean
generate
within_app { install_gems }
end
def load
load_environment
run_migrations
end
def load
load_environment
run_migrations
end
def gemfile_path
File.join(ROOT_DIR, 'Gemfile')
end
def gemfile_path
File.join(ROOT_DIR, 'Gemfile')
end
def environment_file_path
File.join(ROOT_DIR, 'config/environment')
end
def environment_file_path
File.join(ROOT_DIR, 'config/environment')
end
def temp_views_dir_path
File.join(ROOT_DIR, 'tmp/views')
end
def temp_views_dir_path
File.join(ROOT_DIR, 'tmp/views')
end
def create_temp_view(path, contents)
full_path = temp_view_path_for(path)
FileUtils.mkdir_p(File.dirname(full_path))
File.open(full_path, 'w') { |file| file.write(contents) }
end
def create_temp_view(path, contents)
full_path = temp_view_path_for(path)
FileUtils.mkdir_p(File.dirname(full_path))
File.open(full_path, 'w') { |file| file.write(contents) }
end
def delete_temp_views
FileUtils.rm_rf(temp_views_dir_path)
end
def delete_temp_views
FileUtils.rm_rf(temp_views_dir_path)
end
def draw_routes(&block)
Rails.application.routes.draw(&block)
Rails.application.routes
end
def draw_routes(&block)
Rails.application.routes.draw(&block)
Rails.application.routes
end
private
private
def migrations_dir_path
File.join(ROOT_DIR, 'db/migrate')
end
def migrations_dir_path
File.join(ROOT_DIR, 'db/migrate')
end
def temp_view_path_for(path)
File.join(temp_views_dir_path, path)
end
def temp_view_path_for(path)
File.join(temp_views_dir_path, path)
end
def clean
FileUtils.rm_rf(ROOT_DIR)
end
def clean
FileUtils.rm_rf(ROOT_DIR)
end
def generate
rails_new
fix_available_locales_warning
end
def generate
rails_new
fix_available_locales_warning
end
def rails_new
`rails new #{ROOT_DIR} --skip-bundle`
end
def rails_new
`rails new #{ROOT_DIR} --skip-bundle`
end
def fix_available_locales_warning
# See here for more on this:
# http://stackoverflow.com/questions/20361428/rails-i18n-validation-deprecation-warning
def fix_available_locales_warning
# See here for more on this:
# http://stackoverflow.com/questions/20361428/rails-i18n-validation-deprecation-warning
filename = File.join(ROOT_DIR, 'config/application.rb')
filename = File.join(ROOT_DIR, 'config/application.rb')
lines = File.read(filename).split("\n")
lines.insert(-3, <<EOT)
lines = File.read(filename).split("\n")
lines.insert(-3, <<EOT)
if I18n.respond_to?(:enforce_available_locales=)
I18n.enforce_available_locales = false
end
EOT
File.open(filename, 'w') do |f|
f.write(lines.join("\n"))
File.open(filename, 'w') do |f|
f.write(lines.join("\n"))
end
end
end
def load_environment
require environment_file_path
end
def run_migrations
ActiveRecord::Migration.verbose = false
ActiveRecord::Migrator.migrate(migrations_dir_path)
end
def install_gems
retrying('bundle install --local') do |command|
Bundler.with_clean_env { `#{command}` }
def load_environment
require environment_file_path
end
end
def within_app(&block)
Dir.chdir(ROOT_DIR, &block)
end
def run_migrations
ActiveRecord::Migration.verbose = false
ActiveRecord::Migrator.migrate(migrations_dir_path)
end
def retrying(command, &runner)
runner ||= -> { `#{command}` }
def install_gems
retrying('bundle install --local') do |command|
Bundler.with_clean_env { `#{command}` }
end
end
retry_count = 0
loop do
output = runner.call("#{command} 2>&1")
if $? == 0
break
else
retry_count += 1
if retry_count == 3
raise "Command '#{command}' failed:\n#{output}"
def within_app(&block)
Dir.chdir(ROOT_DIR, &block)
end
def retrying(command, &runner)
runner ||= -> { `#{command}` }
retry_count = 0
loop do
output = runner.call("#{command} 2>&1")
if $? == 0
break
else
retry_count += 1
if retry_count == 3
raise "Command '#{command}' failed:\n#{output}"
end
end
end
end

View File

@ -1,6 +1,6 @@
require 'delegate'
module Helpers
module UnitTests
class RecordBuilderWithI18nValidationMessage < SimpleDelegator
def initialize(builder, options = {})
super(builder)

View File

@ -0,0 +1,56 @@
require_relative 'helpers/model_builder'
module UnitTests
class RecordValidatingConfirmationBuilder
include ModelBuilder
def initialize(options)
@options = options
end
def model
@_model ||= create_model
end
def model_name
'Example'
end
def record
model.new
end
def message=(message)
options[:message] = message
end
def attribute_to_confirm
:attribute_to_confirm
end
alias_method :attribute, :attribute_to_confirm
def confirmation_attribute
:"#{attribute_to_confirm}_confirmation"
end
def attribute_that_receives_error
Shoulda::Matchers::RailsShim.
validates_confirmation_of_error_attribute(self)
end
protected
attr_reader :options
private
def create_model
_attribute = attribute_to_confirm
_options = options
define_model(model_name, _attribute => :string) do
validates_confirmation_of(_attribute, _options)
end
end
end
end

View File

@ -0,0 +1,92 @@
require_relative 'helpers/model_builder'
module UnitTests
class RecordWithDifferentErrorAttributeBuilder
include ModelBuilder
def initialize(options)
@options = options.reverse_merge(default_options)
end
def attribute_that_receives_error
options[:attribute_that_receives_error]
end
def attribute_to_validate
options[:attribute_to_validate]
end
def message
options[:message]
end
def message=(message)
options[:message] = message
end
def model
@_model ||= create_model
end
def model_name
'Example'
end
def record
model.new
end
def valid_value
'some value'
end
protected
attr_reader :options
private
def context
{
validation_method_name: validation_method_name,
valid_value: valid_value,
attribute_to_validate: attribute_to_validate,
attribute_that_receives_error: attribute_that_receives_error,
message: message
}
end
def create_model
_context = context
define_model model_name, model_columns do
validate _context[:validation_method_name]
define_method(_context[:validation_method_name]) do
if self[_context[:attribute_to_validate]] != _context[:valid_value]
self.errors.add(_context[:attribute_that_receives_error], _context[:message])
end
end
end
end
def validation_method_name
:custom_validation
end
def model_columns
{
attribute_to_validate => :string,
attribute_that_receives_error => :string
}
end
def default_options
{
attribute_that_receives_error: :attribute_that_receives_error,
attribute_to_validate: :attribute_to_validate,
message: 'some message'
}
end
end
end

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActionController::CallbackMatcher do
shared_examples 'CallbackMatcher' do |kind, callback_type|

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActionController::FilterParamMatcher do
it 'accepts filtering a filtered parameter' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActionController::RedirectToMatcher do
context 'a controller that redirects' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActionController::RenderTemplateMatcher do
include ActionController::TemplateAssertions

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActionController::RenderWithLayoutMatcher do
include ActionController::TemplateAssertions

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActionController::RescueFromMatcher do
context 'a controller that rescues from RuntimeError' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActionController::RespondWithMatcher do
statuses = { success: 200, redirect: 301, missing: 404, error: 500,

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe 'Shoulda::Matchers::ActionController::RouteMatcher', type: :controller do
context 'given a controller with a defined glob url' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActionController::RouteParams do
describe "#normalize" do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActionController::SetSessionMatcher do
context 'a controller that sets a session variable' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActionController::SetTheFlashMatcher do
it 'fails with unmatchable #to' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActionController do
describe '#permit' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::AllowMassAssignmentOfMatcher do
context '#description' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::AllowValueMatcher do
context "#description" do
@ -89,7 +89,7 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher do
end
context 'when the attribute being validated is different than the attribute that receives the validation error' do
include Helpers::AllowValueMatcherHelpers
include UnitTests::AllowValueMatcherHelpers
context 'when the validation error message was provided directly' do
it 'passes given a valid value' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher do
context 'an attribute with a format validation' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::EnsureLengthOfMatcher do
context 'an attribute with a non-zero minimum length validation' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::ExceptionMessageFinder do
if active_model_3_2?

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::HaveSecurePasswordMatcher do
if active_model_3_1?

View File

@ -1,5 +1,5 @@
# encoding: UTF-8
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::Helpers do
include Shoulda::Matchers::ActiveModel

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher do
subject { described_class.new(matcher, 0, :>) }

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::EvenNumberMatcher do
subject { described_class.new(:attr) }

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::OddNumberMatcher do
subject { described_class.new(:attr) }

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::OnlyIntegerMatcher do
subject { described_class.new(:attr) }

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidateAbsenceOfMatcher do
if active_model_4_0?

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidateAcceptanceOfMatcher do
context 'a model with an acceptance validation' do

View File

@ -1,7 +1,7 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidateConfirmationOfMatcher do
include Helpers::ConfirmationMatcherHelpers
include UnitTests::ConfirmationMatcherHelpers
context '#description' do
it 'states that the confirmation must match its base attribute' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel do
describe '#ensure_exclusion_of' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel do
describe '#ensure_inclusion_of' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidateNumericalityOfMatcher do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidatePresenceOfMatcher do
context 'a model with a presence validation' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
context 'a model without a a uniqueness validation' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidationMessageFinder do
context '#allow_description' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveRecord::AcceptNestedAttributesForMatcher do
it 'accepts an existing declaration' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
context 'belong_to' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveRecord::AssociationMatchers::ModelReflection do
it 'delegates other methods to the given Reflection object' do

View File

@ -1,4 +1,4 @@
require "spec_helper"
require "unit_spec_helper"
describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher do
if active_record_supports_enum?

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveRecord::HaveDbColumnMatcher do
it 'accepts an existing database column' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveRecord::HaveDbIndexMatcher do
context 'have_db_index' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveRecord::HaveReadonlyAttributeMatcher do
context 'a read-only attribute' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveRecord::SerializeMatcher do
it 'accepts when the attribute is serialized' do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
module Shoulda::Matchers::Doublespeak
describe DoubleCollection do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
module Shoulda::Matchers::Doublespeak
describe DoubleImplementationRegistry do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
module Shoulda::Matchers::Doublespeak
describe Double do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
module Shoulda::Matchers::Doublespeak
describe ObjectDouble do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
module Shoulda::Matchers::Doublespeak
describe ProxyImplementation do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
module Shoulda::Matchers::Doublespeak
describe StubImplementation do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
module Shoulda::Matchers::Doublespeak
describe World do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
module Shoulda::Matchers
describe Doublespeak do

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::Independent::DelegateMethodMatcher::StubbedTarget do
subject(:target) { described_class.new(:stubbed_method) }

View File

@ -1,4 +1,4 @@
require 'spec_helper'
require 'unit_spec_helper'
describe Shoulda::Matchers::Independent::DelegateMethodMatcher do
describe '#description' do

View File

@ -1,4 +1,4 @@
require File.expand_path('../support/test_application', __FILE__)
require File.expand_path('../support/unit/rails_application', __FILE__)
def monkey_patch_minitest_to_do_nothing
# Rails 3.1's test_help file requires Turn, which loads Minitest in autorun
@ -13,7 +13,7 @@ def monkey_patch_minitest_to_do_nothing
end
end
$test_app = TestApplication.new
$test_app = UnitTests::RailsApplication.new
$test_app.create
$test_app.load
@ -29,18 +29,33 @@ require 'rspec/rails'
PROJECT_ROOT = File.expand_path('../..', __FILE__)
$LOAD_PATH << File.join(PROJECT_ROOT, 'lib')
Dir[ File.join(PROJECT_ROOT, 'spec/support/**/*.rb') ].each { |file| require file }
Dir[ File.join(File.expand_path('../support/unit/**/*.rb', __FILE__)) ].each do |file|
require file
end
RSpec.configure do |config|
config.expect_with :rspec do |c|
c.syntax = :expect
end
config.mock_with :mocha
config.include Shoulda::Matchers::ActionController, type: :controller
if config.respond_to?(:infer_spec_type_from_file_location!)
config.infer_spec_type_from_file_location!
end
config.mock_with :mocha
config.include Shoulda::Matchers::ActionController, type: :controller
UnitTests::ActiveModelHelpers.configure_example_group(config)
UnitTests::ActiveModelVersions.configure_example_group(config)
UnitTests::ActiveResourceBuilder.configure_example_group(config)
UnitTests::ClassBuilder.configure_example_group(config)
UnitTests::ControllerBuilder.configure_example_group(config)
UnitTests::I18nFaker.configure_example_group(config)
UnitTests::MailerBuilder.configure_example_group(config)
UnitTests::ModelBuilder.configure_example_group(config)
UnitTests::RailsVersions.configure_example_group(config)
config.include UnitTests::Matchers
end
$VERBOSE = true