title: Rails: does minitest use schema.rb to recreate the test schema?
body: <p>I am trying to bring a legacy Rails system up more current standards but having problems getting the test database to reflect the state of <code>schema.rb</code> <em>plus</em> changes made via migrations.</p>
  
  <p><strong>tl;dr</strong> Does running <code>rake minitest:all</code> invoke the same code as <code>rake db:schema:load</code>?</p>
  
  <h3>Environment</h3>
  
  <ul>
  <li>Rails 3.2.20 </li>
  <li>Ruby 1.9.3</li>
  <li>Minitest gem 4.6.2</li>
  <li>minitest-rails 0.5.2</li>
  <li>MySQL 5.1</li>
  <li>Local OS X, Test and Production Linux</li>
  </ul>
  
  <h3>Original System State</h3>
  
  <p>The system was originally set up by people who were not software engineers, didn't know Rails, etc.  Several MySQL-specific types were added (e.g. an <code>unsigned int</code>) that are not specifically supported using Rails' migrations and <code>schema.rb</code>.  So the system used the <code>structure.sql</code> and was very sloppy about how it was kept updated, checked in to git, and so on.</p>
  
  <p>Further, at some point later, someone decided to <em>replace</em> some of the usual numeric, auto-incrementing primary key <code>id</code> fields with a <code>varchar</code> containing a self-generated GUID.  The field name was still <code>id</code> but it was a new datatype.  </p>
  
  <p>But all of the hundreds of tests (they <em>did</em> write a lot of tests) had been written to reference fixture instances based on ids, not fixture names and there were dependencies between fixtures, etc.  Rather than updating the tests, they decided to stick with the old schema (with numeric <code>id</code>) for tests, and use the new one (with varchar GUIDs in <code>id</code>) for production.</p>
  
  <p><em>OP takes a deep breath...</em></p>
  
  <p>Databases for various environments were out of sync, there were hundreds of migrations, but they stopped working because the "development" database was shared and ... well you know, it was a mess.</p>
  
  <p>I am trying to fix all of this, and eventually move to PostgreSQL.</p>
  
  <h3>What I Have Done</h3>
  
  <p>I dumped the schema from the production database locally using <code>RAILS_ENV=production rake db:structure:dump</code> -- this produced an authoritative <code>structure.sql</code>.  I created a fresh development database, and loaded its schema using <code>rake db:structure:load</code> -- I carefully compared production and development schemas and they were the same, even the MySQL-specific unsigned int I mentioned above.</p>
  
  <p>I would like to move to using <code>schema.rb</code> for two reasons.  First, I would like to get to a system that does not depend on MySQL.  Second, when using <code>structure.sql</code> we check in a file that has the auto-increment values, DB settings and other characteristics of whatever machine ran the most recent <code>db:migrate</code>.  This can create issues I would prefer to avoid.</p>
  
  <p>So, I locally changed the configuration setting from <code>:sql</code>to use the <code>:ruby</code> setting to produce <code>schema.rb</code>.  </p>
  
  <p>But <code>schema.rb</code> really doesn't like the idea of the <code>id</code> field being turned into a <code>varchar</code> -- I have made sure all of the models that use this declare <code>self.primary_key = :id</code>, then I created a new migration to replace all of the old ones, a "rollup migration", whose content is this mainly new <code>schema.rb</code>, but modified in several ways.</p>
  
  <p>In particular, where the <code>id</code> field is the GUID <code>varchar</code> I set up the table like this (from within a migration):</p>
  
  <pre><code>class RolledUpStateAsOf20150403 &lt; ActiveRecord::Migration
  
    def up
  
      # ... all other table definitions in the system
  
      create_table "users", :id =&gt; false, :force =&gt; false do |t|
        t.string   "id", :limit =&gt; 36, :default =&gt; "", :null =&gt; false
        t.string   "login"
        # and all the other user fields
      end
      execute("ALTER TABLE users ADD PRIMARY KEY (id);")
  
      #...
    end
  
    def down
      raise ActiveRecord::IrreversibleMigration
    end
  end
  </code></pre>
  
  <p>So:</p>
  
  <ul>
  <li><code>:id =&gt; false</code> to prevent migration from creating the normal id</li>
  <li><code>:force =&gt; false</code> to make sure this migration doesn't nuke the production DB</li>
  <li><code>t.string "id"</code> with size and other primary-key-like settings</li>
  <li><code>execute(ALTER TABLE ...)</code> at the end to declare the id as a primary key</li>
  </ul>
  
  <p>Every time I create a new migration in the future, <code>schema.rb</code> will be updated -- it won't be accurate for now (until we get rid of those wacky <code>id</code> fields later).  Migrations will honor normal Rails practices moving forward.  </p>
  
  <p>Once the production, staging, development and other databases are in sync then all is well.</p>
  
  <p>Except when we test.</p>
  
  <h3>So Why Isn't this Working when I run Minitest?</h3>
  
  <p>I am running tests with minitest as follows:</p>
  
  <pre><code>RAILS_ENV=test rake db:drop
  RAILS_ENV=test rake db:create
  RAILS_ENV=test rake db:migrate
  RAILS_ENV=test rake minitest:all
  </code></pre>
  
  <p>But then I start seeing errors, and the errors are due to the <code>id</code> columns being defined as <code>int</code> rather than <code>varchar</code>.  </p>
  
  <p>If I inspect the schema <em>before running minitest</em> (after <code>drop</code>, <code>create</code>, and my magic migration), it is correct: the funky primary keys are <code>varchar</code> as desired.</p>
  
  <p>But somewhere during the test it looks like the schema is getting changed back to the Rails standard.  I can go back and inspect the schema the ID columns are back to <code>int</code>.  </p>
  
  <p>Presumably the schema is being produced from the actual <code>schema.rb</code>.</p>
  
  <p>Is this normal/expected behavior?  Any suggestions about how to achieve my goals, which are simply:</p>
  
  <ul>
  <li>Migrations work again</li>
  <li>Development, test, staging, production databases are structurally the same</li>
  <li>I need to live with the crazy <code>varchar</code> GUID-based <code>id</code> fields for now</li>
  <li>I <em>prefer</em> not to use <code>structure.sql</code> if possible</li>
  </ul>