Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Automatically maintain test database schema #13528

Merged
merged 1 commit into from
@jonleighton
Collaborator
  • Move check from generated helper to test_help.rb, so that all applications can benefit
  • Rather than just raising when the test schema has pending migrations, try to load in the schema and only raise if there are pending migrations afterwards

TODO:

  • We no longer need db:test:prepare and friends. Deprecate them.
  • Update docs/changelog
  • Add config option to allow users to opt-out of this behaviour
@josevalim
Owner

Great work. If we are going to allow people to manually opt-out of this behaviour we should probably not remove db:test:prepare for the users that would prefer to do it manually. Or would they rather call load_schema_if_pending?

@jonleighton
Collaborator

@josevalim I'm basically proposing we deprecate these: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/railties/databases.rake#L301-L364

I don't see what purpose they serve any more. People who want to do these things manually can do stuff like

rake db:schema:load RAILS_ENV=test

So I don't think we need these test-specific rake tasks at all?

@josevalim
Owner

Sounds good!

@jonleighton
Collaborator

@josevalim I consider this finished now, let me know if you have any more comments

@rafaelfranca
Owner

Seems good to me

@jonleighton jonleighton Automatically maintain test database schema
* Move check from generated helper to test_help.rb, so that all
  applications can benefit
* Rather than just raising when the test schema has pending migrations,
  try to load in the schema and only raise if there are pending
  migrations afterwards
* Opt out of the check by setting
  config.active_record.maintain_test_schema = false
* Deprecate db:test:* tasks. The test helper is now fully responsible
  for maintaining the test schema, so we don't need rake tasks for this.
  This is also a speed improvement since we're no longer reloading the
  test database on every call to "rake test".
ff7ab3b
@jonleighton jonleighton merged commit d740438 into from
@jonleighton
Collaborator

cc @alindeman in case you want to add this to rspec-rails

@schneems
Collaborator

:heart: great work here.

@jasontorres

Great job!

@tamouse

this makes me weep with joy

@joshuaflanagan joshuaflanagan referenced this pull request in rspec/rspec-rails
Closed

Rails 4.1.0.rc1 no longer defines db:test:prepare #936

@jaredbeck

Should rspec users add require 'rails/test_help' to their spec_helper? Thanks, looking forward to trying this out!

@jaredbeck jaredbeck referenced this pull request from a commit in usgo/gocongress
@jaredbeck jaredbeck Updates rails to 4.1.0.rc2
- [release notes][1]
- [release announcement][2]
- [deprecation of db:test:* tasks][3]
- Had to update `sass-rails` to 4.0.2 because of
an [issue with sprockets 2.12][4]

[1]: http://edgeguides.rubyonrails.org/4_1_release_notes.html
[2]: http://weblog.rubyonrails.org/2014/3/25/Rails-4-1-rc2/
[3]: rails/rails#13528
[4]: sstephenson/sprockets#540
fa41b86
@jaredbeck jaredbeck referenced this pull request in usgo/gocongress
Merged

Updates rails to 4.1.0.rc2 #17

@jonleighton
Collaborator

@jaredbeck yep could do, but I think ideally the rspec-rails gem would integrate support for this

@swebb

@jaredbeck I found adding require 'rails/test_help' caused rspec and minitest to run. Instead I added ActiveRecord::Migration.maintain_test_schema! to my spec_helper.

@jaredbeck

I think ideally the rspec-rails gem would integrate support for this

If I'm understanding rspec/rspec-rails#946 correctly, newly-generated spec_helper files will include a call to maintain_test_schema!. Is that what you were thinking, Jon?

@kevintyll

The only problem with removing the test load tasks, is that they purge the db before loading it, so now deleted tables will never be removed from the test db.

A separate issue is we are constantly branching and merging our app, so using the latest schema info to determine if we need to load the schema does not work for us. I may be switching to a branch that has a later migration than the one I just came from, but it won't load because the test db has a more recent migration. I'm solving the problem by comparing the structure.sql mtime to the test.log mtime.

Here is the patch file I created for our use. I don't think this is a global solution, but it works for us and may give you ideas if you agree that using the schema_migrations table is limited. The path file also includes patches for parallel_test, which adds additional issues:

# As of rails 4.1, the schema is loaded automatically if needed based on the schema_migrations table, the problem with this is
# with migrations created in different branches, that not very accurate.  This file overrides the classes necessary
# to load it based on comparing the structure.sql modified time and the test.log modified time.  It will load if the structure
# was modified since the last test run.

# This file also overrides the structure load task to do a purge before loading.


# This file gets loaded in the test and development environments from application.rb

if Rails.env.test?
  module ActiveRecord
    module Tasks # :nodoc:
      module DatabaseTasks
        # structure_load does not purge the db first, so deleted tables do not get deleted.
        # this gets called automatically from tests as of rails 4.1.0
        def structure_load_with_purge(*arguments)
          puts "Loading structure.sql"
          purge(current_config)
          structure_load_without_purge(*arguments)
          ActiveRecord::Migrator.last_test_run = Time.now
        end

        alias_method_chain :structure_load, :purge
      end
    end
  end

  module ActiveRecord
    class Migrator #:nodoc:
      class << self

        cattr_accessor :last_test_run

        def needs_migration?(connection = Base.connection)
          structure_updated = File.mtime('db/structure.sql')
          puts "Structure.sql modified: #{structure_updated}"
          puts "Last test run: #{last_test_run}"
          last_test_run < structure_updated
        end
      end
    end
  end


  Rails.application.config.before_configuration do
    # If running parallel tests, one process may get ahead of the others and write to the test.log file before another process can
    # check it to see if the structure should be loaded.  So some instances may load the structure, but not others.
    # Have all processes wait here until all have started so they can check the log file at the same time.
    if ENV['PARALLEL_TEST_GROUPS'].present?
      loop do
        break if ParallelTests.number_of_running_processes.to_s == ENV['PARALLEL_TEST_GROUPS'].to_s
        sleep 1
      end
    end
    ActiveRecord::Migrator.last_test_run = File.mtime('log/test.log') rescue Time.parse('2009-01-01')
  end
end

if Rails.env.development?
  require 'parallel_tests/tasks'
  module ParallelTests
    module Tasks
      class << self
        def check_for_pending_migrations
          # no op
          # we just want to load the structure file, we don't care if the dev db has not run all the migrations yet.
          # if the structure file is missing migrations, it will still error as of rails 4.1
        end
      end
    end
  end
end
@derekprior derekprior referenced this pull request in thoughtbot/dotfiles
Closed

Remove test:prepare from migrate alias #260

@JuanitoFatas

How to remove the WARNING?

WARNING: db:test:prepare is deprecated. The Rails test helper now maintains your test schema automatically, see the release notes for details.

Do not use rake db:test:prepare ? Thanks.

@rafaelfranca

Yes. it should not be used anymore.

@mehlah mehlah referenced this pull request in craftsmen/roll
Merged

Maintain ActiveRecord test schema for rspec #11

@mediafinger

Thx for deprecating rake db:test:prepare! :heart:

@AlexVPopov AlexVPopov referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
@talsafran

If I create a migration and migrate it:

class CreateCookPhotos < ActiveRecord::Migration
  def change
    create_table :cook_photos do |t|
      t.integer :cook_id
      t.string :url

      t.timestamps
    end
  end
end

And then roll it back because I want to add or change something in the migration (say change the name of the url column to filename)

Then the test database doesn't seem to catch the change.

To alleviate this, I have to:

rake db:rollback RAILS_ENV=test
rake db:migrate RAILS_ENV=test

This is more work than just copying the schema over with something like rake db:test:prepare. Anything I could do to simplify this?

@spastorino spastorino commented on the diff
activerecord/lib/active_record/migration.rb
@@ -389,6 +389,19 @@ def check_pending!
raise ActiveRecord::PendingMigrationError if ActiveRecord::Migrator.needs_migration?
end
+ def load_schema_if_pending!
+ if ActiveRecord::Migrator.needs_migration?
@spastorino Owner

seems like a ActiveRecord::Tasks::DatabaseTasks.purge is missing here. /cc @jonleighton. See #15787 Is what we were doing under test namespace

@spastorino Owner

So seems like it's already fixed #15394

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@dblandin dblandin referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
@GeekOnCoffee

Any suggestions on how to hook into this behavior? I've read through it a few times looking for a good integration point but haven't found anywhere... looking to reseed when the test database is rebuilt, as we have seed data that's required for tests to pass

@senny senny referenced this pull request from a commit
@senny senny bring back `db:test:prepare`.
This reverts deprecations added in #13528.
The task is brought back for two reasons:
  1. Give plugins a way to hook into the test database initialization process
  2. Give the user a way to force a test database synchronization

While `test:prepare` is still a dependency of every test task, `db:test:prepare`
no longer hooks into it. This means that `test:prepare` runs before the schema
is synchronized. Plugins, which insert data can now hook into `db:test:prepare`.

The automatic schema maintenance can't detect when a migration is rolled-back,
modified and reapplied. In this case the user has to fall back to `db:test:prepare`
to force the synchronization to happen.
55ded32
@senny senny referenced this pull request
Merged

bring back `db:test:prepare`. #17739

3 of 3 tasks complete
@senny senny referenced this pull request from a commit
@senny senny bring back `db:test:prepare`.
This reverts deprecations added in #13528.
The task is brought back for two reasons:
  1. Give plugins a way to hook into the test database initialization process
  2. Give the user a way to force a test database synchronization

While `test:prepare` is still a dependency of every test task, `db:test:prepare`
no longer hooks into it. This means that `test:prepare` runs before the schema
is synchronized. Plugins, which insert data can now hook into `db:test:prepare`.

The automatic schema maintenance can't detect when a migration is rolled-back,
modified and reapplied. In this case the user has to fall back to `db:test:prepare`
to force the synchronization to happen.
c0f8218
@senny senny referenced this pull request from a commit
@senny senny bring back `db:test:prepare`.
This reverts deprecations added in #13528.
The task is brought back for two reasons:
  1. Give plugins a way to hook into the test database initialization process
  2. Give the user a way to force a test database synchronization

While `test:prepare` is still a dependency of every test task, `db:test:prepare`
no longer hooks into it. This means that `test:prepare` runs before the schema
is synchronized. Plugins, which insert data can now hook into `db:test:prepare`.

The automatic schema maintenance can't detect when a migration is rolled-back,
modified and reapplied. In this case the user has to fall back to `db:test:prepare`
to force the synchronization to happen.
5c44955
@sachin004 sachin004 referenced this pull request from a commit in sachin004/rails
@senny senny bring back `db:test:prepare`.
This reverts deprecations added in #13528.
The task is brought back for two reasons:
  1. Give plugins a way to hook into the test database initialization process
  2. Give the user a way to force a test database synchronization

While `test:prepare` is still a dependency of every test task, `db:test:prepare`
no longer hooks into it. This means that `test:prepare` runs before the schema
is synchronized. Plugins, which insert data can now hook into `db:test:prepare`.

The automatic schema maintenance can't detect when a migration is rolled-back,
modified and reapplied. In this case the user has to fall back to `db:test:prepare`
to force the synchronization to happen.
f9deecb
@curtislinden

I'm wondering on the status of this? I'm looking for a way to maintain a test rails env that isn't called 'test'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 2, 2014
  1. @jonleighton

    Automatically maintain test database schema

    jonleighton authored
    * Move check from generated helper to test_help.rb, so that all
      applications can benefit
    * Rather than just raising when the test schema has pending migrations,
      try to load in the schema and only raise if there are pending
      migrations afterwards
    * Opt out of the check by setting
      config.active_record.maintain_test_schema = false
    * Deprecate db:test:* tasks. The test helper is now fully responsible
      for maintaining the test schema, so we don't need rake tasks for this.
      This is also a speed improvement since we're no longer reloading the
      test database on every call to "rake test".
This page is out of date. Refresh to see the latest.
View
11 activerecord/CHANGELOG.md
@@ -1,3 +1,12 @@
+* Since the `test_help.rb` in Railties now automatically maintains
+ your test schema, the `rake db:test:*` tasks are deprecated. This
+ doesn't stop you manually running other tasks on your test database
+ if needed:
+
+ rake db:schema:load RAILS_ENV=test
+
+ *Jon Leighton*
+
* Fix presence validator for association when the associated record responds to `to_a`.
*gmarik*
@@ -54,6 +63,8 @@
* Deprecated use of string argument as a configuration lookup in
`ActiveRecord::Base.establish_connection`. Instead, a symbol must be given.
+* Deprecated use of string argument as a configuration lookup in `ActiveRecord::Base.establish_connection`. Instead, a symbol must be given.
+
*José Valim*
* Fixed `update_column`, `update_columns`, and `update_all` to correctly serialize
View
3  activerecord/lib/active_record/core.rb
@@ -69,6 +69,9 @@ module Core
mattr_accessor :timestamped_migrations, instance_writer: false
self.timestamped_migrations = true
+ # :nodoc:
+ mattr_accessor :maintain_test_schema, instance_accessor: false
+
def self.disable_implicit_join_references=(value)
ActiveSupport::Deprecation.warn("Implicit join references were removed with Rails 4.1." \
"Make sure to remove this configuration because it does nothing.")
View
13 activerecord/lib/active_record/migration.rb
@@ -389,6 +389,19 @@ def check_pending!
raise ActiveRecord::PendingMigrationError if ActiveRecord::Migrator.needs_migration?
end
+ def load_schema_if_pending!
+ if ActiveRecord::Migrator.needs_migration?
@spastorino Owner

seems like a ActiveRecord::Tasks::DatabaseTasks.purge is missing here. /cc @jonleighton. See #15787 Is what we were doing under test namespace

@spastorino Owner

So seems like it's already fixed #15394

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ ActiveRecord::Tasks::DatabaseTasks.load_schema
+ check_pending!
+ end
+ end
+
+ def maintain_test_schema! # :nodoc:
+ if ActiveRecord::Base.maintain_test_schema
+ suppress_messages { load_schema_if_pending! }
+ end
+ end
+
def method_missing(name, *args, &block) # :nodoc:
(delegate || superclass.delegate).send(name, *args, &block)
end
View
9 activerecord/lib/active_record/railtie.rb
@@ -31,22 +31,15 @@ class Railtie < Rails::Railtie # :nodoc:
config.active_record.use_schema_cache_dump = true
+ config.active_record.maintain_test_schema = true
config.eager_load_namespaces << ActiveRecord
rake_tasks do
require "active_record/base"
- ActiveRecord::Tasks::DatabaseTasks.seed_loader = Rails.application
- ActiveRecord::Tasks::DatabaseTasks.env = Rails.env
-
namespace :db do
task :load_config do
- ActiveRecord::Tasks::DatabaseTasks.db_dir = Rails.application.config.paths["db"].first
- ActiveRecord::Tasks::DatabaseTasks.migrations_paths = Rails.application.paths['db/migrate'].to_a
- ActiveRecord::Tasks::DatabaseTasks.fixtures_path = File.join Rails.root, 'test', 'fixtures'
- ActiveRecord::Tasks::DatabaseTasks.root = Rails.root
-
configuration = if ENV["DATABASE_URL"]
{ Rails.env => ENV["DATABASE_URL"] }
else
View
34 activerecord/lib/active_record/railties/databases.rake
@@ -234,9 +234,7 @@ db_namespace = namespace :db do
desc 'Load a schema.rb file into the database'
task :load => [:environment, :load_config] do
- file = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'schema.rb')
- ActiveRecord::Tasks::DatabaseTasks.check_schema_file(file)
- load(file)
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(:ruby, ENV['SCHEMA'])
end
task :load_if_ruby => ['db:create', :environment] do
@@ -281,10 +279,7 @@ db_namespace = namespace :db do
# desc "Recreate the databases from the structure.sql file"
task :load => [:environment, :load_config] do
- filename = ENV['DB_STRUCTURE'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
- ActiveRecord::Tasks::DatabaseTasks.check_schema_file(filename)
- current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
- ActiveRecord::Tasks::DatabaseTasks.structure_load(current_config, filename)
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(:sql, ENV['DB_STRUCTURE'])
end
task :load_if_sql => ['db:create', :environment] do
@@ -294,8 +289,15 @@ db_namespace = namespace :db do
namespace :test do
+ task :deprecated do
+ Rake.application.top_level_tasks.grep(/^db:test:/).each do |task|
+ $stderr.puts "WARNING: #{task} is deprecated. The Rails test helper now maintains " \
+ "your test schema automatically, see the release notes for details."
+ end
+ end
+
# desc "Recreate the test database from the current schema"
- task :load => 'db:test:purge' do
+ task :load => %w(db:test:deprecated db:test:purge) do
case ActiveRecord::Base.schema_format
when :ruby
db_namespace["test:load_schema"].invoke
@@ -305,7 +307,7 @@ db_namespace = namespace :db do
end
# desc "Recreate the test database from an existent schema.rb file"
- task :load_schema => 'db:test:purge' do
+ task :load_schema => %w(db:test:deprecated db:test:purge) do
begin
should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
@@ -319,7 +321,7 @@ db_namespace = namespace :db do
end
# desc "Recreate the test database from an existent structure.sql file"
- task :load_structure => 'db:test:purge' do
+ task :load_structure => %w(db:test:deprecated db:test:purge) do
begin
ActiveRecord::Tasks::DatabaseTasks.current_config(:config => ActiveRecord::Base.configurations['test'])
db_namespace["structure:load"].invoke
@@ -329,7 +331,7 @@ db_namespace = namespace :db do
end
# desc "Recreate the test database from a fresh schema"
- task :clone => :environment do
+ task :clone => %w(db:test:deprecated environment) do
case ActiveRecord::Base.schema_format
when :ruby
db_namespace["test:clone_schema"].invoke
@@ -339,18 +341,18 @@ db_namespace = namespace :db do
end
# desc "Recreate the test database from a fresh schema.rb file"
- task :clone_schema => ["db:schema:dump", "db:test:load_schema"]
+ task :clone_schema => %w(db:test:deprecated db:schema:dump db:test:load_schema)
# desc "Recreate the test database from a fresh structure.sql file"
- task :clone_structure => [ "db:structure:dump", "db:test:load_structure" ]
+ task :clone_structure => %w(db:structure:dump db:test:load_structure)
# desc "Empty the test database"
- task :purge => [:environment, :load_config] do
+ task :purge => %w(db:test:deprecated environment load_config) do
ActiveRecord::Tasks::DatabaseTasks.purge ActiveRecord::Base.configurations['test']
end
# desc 'Check for pending migrations and load the test schema'
- task :prepare => [:environment, :load_config] do
+ task :prepare => %w(db:test:deprecated environment load_config) do
unless ActiveRecord::Base.configurations.blank?
db_namespace['test:load'].invoke
end
@@ -385,5 +387,3 @@ namespace :railties do
end
end
end
-
-task 'test:prepare' => ['db:test:prepare', 'db:test:load', 'db:abort_if_pending_migrations']
View
44 activerecord/lib/active_record/tasks/database_tasks.rb
@@ -36,9 +36,8 @@ class DatabaseNotSupported < StandardError; end # :nodoc:
module DatabaseTasks
extend self
- attr_writer :current_config
- attr_accessor :database_configuration, :migrations_paths, :seed_loader, :db_dir,
- :fixtures_path, :env, :root
+ attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
+ attr_accessor :database_configuration
LOCAL_HOSTS = ['127.0.0.1', 'localhost']
@@ -51,6 +50,30 @@ def register_task(pattern, task)
register_task(/postgresql/, ActiveRecord::Tasks::PostgreSQLDatabaseTasks)
register_task(/sqlite/, ActiveRecord::Tasks::SQLiteDatabaseTasks)
+ def db_dir
+ @db_dir ||= Rails.application.config.paths["db"].first
+ end
+
+ def migrations_paths
+ @migrations_paths ||= Rails.application.paths['db/migrate'].to_a
+ end
+
+ def fixtures_path
+ @fixtures_path ||= File.join(root, 'test', 'fixtures')
+ end
+
+ def root
+ @root ||= Rails.root
+ end
+
+ def env
+ @env ||= Rails.env
+ end
+
+ def seed_loader
+ @seed_loader ||= Rails.application
+ end
+
def current_config(options = {})
options.reverse_merge! :env => env
if options.has_key?(:config)
@@ -133,6 +156,21 @@ def structure_load(*arguments)
class_for_adapter(configuration['adapter']).new(*arguments).structure_load(filename)
end
+ def load_schema(format = ActiveRecord::Base.schema_format, file = nil)
+ case format
+ when :ruby
+ file ||= File.join(db_dir, "schema.rb")
+ check_schema_file(file)
+ load(file)
+ when :sql
+ file ||= File.join(db_dir, "structure.sql")
+ check_schema_file(file)
+ structure_load(current_config, file)
+ else
+ raise ArgumentError, "unknown format #{format.inspect}"
+ end
+ end
+
def check_schema_file(filename)
unless File.exist?(filename)
message = %{#{filename} doesn't exist yet. Run `rake db:migrate` to create it, then try again.}
View
11 guides/source/4_1_release_notes.md
@@ -281,6 +281,13 @@ for detailed changes.
* Add `Application#message_verifier` method to return a message
verifier. ([Pull Request](https://github.com/rails/rails/pull/12995))
+* The `test_help.rb` file which is required by the default generated test
+ helper will automatically keep your test database up-to-date with
+ `db/schema.rb` (or `db/structure.sql`). It raises an error if
+ reloading the schema does not resolve all pending migrations. Opt out
+ with `config.active_record.maintain_test_schema = false`. ([Pull
+ Request](https://github.com/rails/rails/pull/13528))
+
Action Pack
-----------
@@ -421,6 +428,10 @@ for detailed changes.
* Deprecated `ConnectionAdapters::SchemaStatements#distinct`,
as it is no longer used by internals. ([Pull Request](https://github.com/rails/rails/pull/10556))
+* Deprecated `rake db:test:*` tasks as the test database is now
+ automatically maintained. See railties release notes. ([Pull
+ Request](https://github.com/rails/rails/pull/13528))
+
### Notable changes
* Added `ActiveRecord::Base.to_param` for convenient "pretty" URLs derived from
View
2  guides/source/configuring.md
@@ -290,6 +290,8 @@ All these configuration options are delegated to the `I18n` library.
* `config.active_record.attribute_types_cached_by_default` sets the attribute types that `ActiveRecord::AttributeMethods` will cache by default on reads. The default is `[:datetime, :timestamp, :time, :date]`.
+* `config.active_record.maintain_test_schema` is a boolean value which controls whether Active Record should try to keep your test database schema up-to-date with `db/schema.rb` (or `db/structure.sql`) when you run your tests. The default is true.
+
The MySQL adapter adds one additional configuration option:
* `ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans` controls whether Active Record will consider all `tinyint(1)` columns in a MySQL database to be booleans and is true by default.
View
1  guides/source/plugins.md
@@ -224,7 +224,6 @@ and migrating the database. First, run:
```bash
$ cd test/dummy
$ rake db:migrate
-$ rake db:test:prepare
```
While you are here, change the Hickwall and Wickwall models so that they know that they are supposed to act
View
26 guides/source/testing.md
@@ -211,31 +211,9 @@ This line of code is called an _assertion_. An assertion is a line of code that
Every test contains one or more assertions. Only when all the assertions are successful will the test pass.
-### Preparing your Application for Testing
+### Maintaining the test database schema
-Before you can run your tests, you need to ensure that the test database structure is current. For this you can use the following rake commands:
-
-```bash
-$ rake db:migrate
-...
-$ rake db:test:load
-```
-
-The `rake db:migrate` above runs any pending migrations on the _development_ environment and updates `db/schema.rb`. The `rake db:test:load` recreates the test database from the current `db/schema.rb`. On subsequent attempts, it is a good idea to first run `db:test:prepare`, as it first checks for pending migrations and warns you appropriately.
-
-NOTE: `db:test:prepare` will fail with an error if `db/schema.rb` doesn't exist.
-
-#### Rake Tasks for Preparing your Application for Testing
-
-| Tasks | Description |
-| ------------------------------ | ------------------------------------------------------------------------- |
-| `rake db:test:clone` | Recreate the test database from the current environment's database schema |
-| `rake db:test:clone_structure` | Recreate the test database from the development structure |
-| `rake db:test:load` | Recreate the test database from the current `schema.rb` |
-| `rake db:test:prepare` | Check for pending migrations and load the test schema |
-| `rake db:test:purge` | Empty the test database. |
-
-TIP: You can see all these rake tasks and their descriptions by running `rake --tasks --describe`
+In order to run your tests, your test database will need to have the current structure. The test helper checks whether your test database has any pending migrations. If so, it will try to load your `db/schema.rb` or `db/structure.sql` into the test database. If migrations are still pending, an error will be raised.
### Running Tests
View
7 guides/source/upgrading_ruby_on_rails.md
@@ -91,6 +91,13 @@ secrets, you need to:
5. Restart your server.
+### Changes to test helper
+
+If your test helper contains a call to
+`ActiveRecord::Migration.check_pending!` this can be removed. The check
+is now done automatically when you `require 'test_help'`, although
+leaving this line in your helper is not harmful in any way.
+
### Changes in JSON handling
There are a few major changes related to JSON handling in Rails 4.1.
View
6 railties/CHANGELOG.md
@@ -1,3 +1,9 @@
+* `test_help.rb` now automatically checks/maintains your test datbase
+ schema. (Use `config.active_record.maintain_test_schema = false` to
+ disable.)
+
+ *Jon Leighton*
+
* Configure `secrets.yml` and `database.yml` to read configuration
from the system environment by default for production.
View
2  railties/lib/rails/generators/rails/app/templates/test/test_helper.rb
@@ -4,8 +4,6 @@
class ActiveSupport::TestCase
<% unless options[:skip_active_record] -%>
- ActiveRecord::Migration.check_pending!
-
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
#
# Note: You'll currently still have to declare fixtures explicitly in integration tests
View
2  railties/lib/rails/test_help.rb
@@ -15,6 +15,8 @@
end
if defined?(ActiveRecord::Base)
+ ActiveRecord::Migration.maintain_test_schema!
+
class ActiveSupport::TestCase
include ActiveRecord::TestFixtures
self.fixture_path = "#{Rails.root}/test/fixtures/"
View
9 railties/test/application/rake/dbs_test.rb
@@ -174,6 +174,15 @@ def db_test_load_structure
require "#{app_path}/config/environment"
db_test_load_structure
end
+
+ test 'db:test deprecation' do
+ require "#{app_path}/config/environment"
+ Dir.chdir(app_path) do
+ output = `bundle exec rake db:migrate db:test:prepare 2>&1`
+ assert_equal "WARNING: db:test:prepare is deprecated. The Rails test helper now maintains " \
+ "your test schema automatically, see the release notes for details.\n", output
+ end
+ end
end
end
end
View
4 railties/test/application/rake_test.rb
@@ -187,7 +187,7 @@ def test_loading_only_yml_fixtures
def test_scaffold_tests_pass_by_default
output = Dir.chdir(app_path) do
`rails generate scaffold user username:string password:string;
- bundle exec rake db:migrate db:test:clone test`
+ bundle exec rake db:migrate test`
end
assert_match(/7 runs, 13 assertions, 0 failures, 0 errors/, output)
@@ -197,7 +197,7 @@ def test_scaffold_tests_pass_by_default
def test_scaffold_with_references_columns_tests_pass_by_default
output = Dir.chdir(app_path) do
`rails generate scaffold LineItems product:references cart:belongs_to;
- bundle exec rake db:migrate db:test:clone test`
+ bundle exec rake db:migrate test`
end
assert_match(/7 runs, 13 assertions, 0 failures, 0 errors/, output)
View
47 railties/test/application/test_test.rb
@@ -67,10 +67,55 @@ def test_failure
assert_match %r{/app/test/unit/failing_test\.rb}, output
end
+ test "migrations" do
+ output = script('generate model user name:string')
+ version = output.match(/(\d+)_create_users\.rb/)[1]
+
+ app_file 'test/models/user_test.rb', <<-RUBY
+ require 'test_helper'
+
+ class UserTest < ActiveSupport::TestCase
+ test "user" do
+ User.create! name: "Jon"
+ end
+ end
+ RUBY
+ app_file 'db/schema.rb', ''
+
+ assert_unsuccessful_run "models/user_test.rb", "Migrations are pending"
+
+ app_file 'db/schema.rb', <<-RUBY
+ ActiveRecord::Schema.define(version: #{version}) do
+ create_table :users do |t|
+ t.string :name
+ end
+ end
+ RUBY
+
+ app_file 'config/initializers/disable_maintain_test_schema.rb', <<-RUBY
+ Rails.application.config.active_record.maintain_test_schema = false
+ RUBY
+
+ assert_unsuccessful_run "models/user_test.rb", "Could not find table 'users'"
+
+ File.delete "#{app_path}/config/initializers/disable_maintain_test_schema.rb"
+
+ result = assert_successful_test_run('models/user_test.rb')
+ assert !result.include?("create_table(:users)")
+ end
+
private
+ def assert_unsuccessful_run(name, message)
+ result = run_test_file(name)
+ assert_not_equal 0, $?.to_i
+ assert result.include?(message)
+ result
+ end
+
def assert_successful_test_run(name)
result = run_test_file(name)
assert_equal 0, $?.to_i, result
+ result
end
def run_test_file(name, options = {})
@@ -83,7 +128,7 @@ def ruby(*args)
env["RUBYLIB"] = $:.join(':')
Dir.chdir(app_path) do
- `#{env_string(env)} #{Gem.ruby} #{args.join(' ')}`
+ `#{env_string(env)} #{Gem.ruby} #{args.join(' ')} 2>&1`
end
end
Something went wrong with that request. Please try again.