test_test.rb 10.2 KB
Newer Older
1
require "isolation/abstract_unit"
J
Joshua Peek 已提交
2 3

module ApplicationTests
4
  class TestTest < ActiveSupport::TestCase
J
Joshua Peek 已提交
5 6 7 8 9 10
    include ActiveSupport::Testing::Isolation

    def setup
      build_app
    end

11 12 13 14
    def teardown
      teardown_app
    end

M
Michael Grosser 已提交
15
    test "simple successful test" do
16
      app_file "test/unit/foo_test.rb", <<-RUBY
J
Joshua Peek 已提交
17 18 19 20 21 22 23 24 25
        require 'test_helper'

        class FooTest < ActiveSupport::TestCase
          def test_truth
            assert true
          end
        end
      RUBY

26
      assert_successful_test_run "unit/foo_test.rb"
J
Joshua Peek 已提交
27 28
    end

29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
    test "after_run" do
      app_file "test/unit/foo_test.rb", <<-RUBY
        require 'test_helper'

        Minitest.after_run { puts "WORLD" }
        Minitest.after_run { puts "HELLO" }

        class FooTest < ActiveSupport::TestCase
          def test_truth
            assert true
          end
        end
      RUBY

      result = assert_successful_test_run "unit/foo_test.rb"
      assert_equal ["HELLO", "WORLD"], result.scan(/HELLO|WORLD/) # only once and in correct order
    end

M
Michael Grosser 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59 60
    test "simple failed test" do
      app_file "test/unit/foo_test.rb", <<-RUBY
        require 'test_helper'

        class FooTest < ActiveSupport::TestCase
          def test_truth
            assert false
          end
        end
      RUBY

      assert_unsuccessful_run "unit/foo_test.rb", "Failed assertion"
    end

61
    test "integration test" do
62
      controller "posts", <<-RUBY
63 64 65 66
        class PostsController < ActionController::Base
        end
      RUBY

67
      app_file "app/views/posts/index.html.erb", <<-HTML
68 69 70
        Posts#index
      HTML

71
      app_file "test/integration/posts_test.rb", <<-RUBY
72 73
        require 'test_helper'

74
        class PostsTest < ActionDispatch::IntegrationTest
75 76 77
          def test_index
            get '/posts'
            assert_response :success
78
            assert_includes @response.body, 'Posts#index'
79 80 81 82
          end
        end
      RUBY

83
      assert_successful_test_run "integration/posts_test.rb"
84 85 86
    end

    test "enable full backtraces on test failures" do
87
      app_file "test/unit/failing_test.rb", <<-RUBY
88 89 90 91 92 93 94 95 96
        require 'test_helper'

        class FailingTest < ActiveSupport::TestCase
          def test_failure
            raise "fail"
          end
        end
      RUBY

97
      output = run_test_file("unit/failing_test.rb", env: { "BACKTRACE" => "1" })
98 99
      assert_match %r{test/unit/failing_test\.rb}, output
      assert_match %r{test/unit/failing_test\.rb:4}, output
100 101
    end

102
    test "ruby schema migrations" do
103
      output  = script("generate model user name:string")
104 105
      version = output.match(/(\d+)_create_users\.rb/)[1]

106
      app_file "test/models/user_test.rb", <<-RUBY
107 108 109 110 111 112 113 114
        require 'test_helper'

        class UserTest < ActiveSupport::TestCase
          test "user" do
            User.create! name: "Jon"
          end
        end
      RUBY
115
      app_file "db/schema.rb", ""
116 117 118

      assert_unsuccessful_run "models/user_test.rb", "Migrations are pending"

119
      app_file "db/schema.rb", <<-RUBY
120 121 122 123 124 125 126
        ActiveRecord::Schema.define(version: #{version}) do
          create_table :users do |t|
            t.string :name
          end
        end
      RUBY

127
      app_file "config/initializers/disable_maintain_test_schema.rb", <<-RUBY
128 129 130 131 132 133 134
        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"

135
      result = assert_successful_test_run("models/user_test.rb")
136 137 138
      assert !result.include?("create_table(:users)")
    end

139
    test "sql structure migrations" do
140
      output  = script("generate model user name:string")
141 142
      version = output.match(/(\d+)_create_users\.rb/)[1]

143
      app_file "test/models/user_test.rb", <<-RUBY
144 145 146 147 148 149 150 151 152
        require 'test_helper'

        class UserTest < ActiveSupport::TestCase
          test "user" do
            User.create! name: "Jon"
          end
        end
      RUBY

153 154
      app_file "db/structure.sql", ""
      app_file "config/initializers/enable_sql_schema_format.rb", <<-RUBY
155 156 157 158 159
        Rails.application.config.active_record.schema_format = :sql
      RUBY

      assert_unsuccessful_run "models/user_test.rb", "Migrations are pending"

160
      app_file "db/structure.sql", <<-SQL
161 162 163 164 165 166
        CREATE TABLE "schema_migrations" ("version" varchar(255) NOT NULL);
        CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version");
        CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255));
        INSERT INTO schema_migrations (version) VALUES ('#{version}');
      SQL

167
      app_file "config/initializers/disable_maintain_test_schema.rb", <<-RUBY
168 169 170 171 172 173 174
        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"

175
      assert_successful_test_run("models/user_test.rb")
176 177 178
    end

    test "sql structure migrations when adding column to existing table" do
179
      output_1  = script("generate model user name:string")
180 181
      version_1 = output_1.match(/(\d+)_create_users\.rb/)[1]

182
      app_file "test/models/user_test.rb", <<-RUBY
183 184 185 186 187 188 189 190
        require 'test_helper'
        class UserTest < ActiveSupport::TestCase
          test "user" do
            User.create! name: "Jon"
          end
        end
      RUBY

191
      app_file "config/initializers/enable_sql_schema_format.rb", <<-RUBY
192 193 194
        Rails.application.config.active_record.schema_format = :sql
      RUBY

195
      app_file "db/structure.sql", <<-SQL
196 197 198 199 200 201
        CREATE TABLE "schema_migrations" ("version" varchar(255) NOT NULL);
        CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version");
        CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255));
        INSERT INTO schema_migrations (version) VALUES ('#{version_1}');
      SQL

202
      assert_successful_test_run("models/user_test.rb")
203

204
      output_2  = script("generate migration add_email_to_users")
205 206
      version_2 = output_2.match(/(\d+)_add_email_to_users\.rb/)[1]

207
      app_file "test/models/user_test.rb", <<-RUBY
208 209 210 211 212 213 214 215 216
        require 'test_helper'

        class UserTest < ActiveSupport::TestCase
          test "user" do
            User.create! name: "Jon", email: "jon@doe.com"
          end
        end
      RUBY

217
      app_file "db/structure.sql", <<-SQL
218 219 220 221 222 223 224
        CREATE TABLE "schema_migrations" ("version" varchar(255) NOT NULL);
        CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version");
        CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255), "email" varchar(255));
        INSERT INTO schema_migrations (version) VALUES ('#{version_1}');
        INSERT INTO schema_migrations (version) VALUES ('#{version_2}');
      SQL

225
      assert_successful_test_run("models/user_test.rb")
226 227
    end

Y
Yves Senn 已提交
228 229 230 231
    # TODO: would be nice if we could detect the schema change automatically.
    # For now, the user has to synchronize the schema manually.
    # This test-case serves as a reminder for this use-case.
    test "manually synchronize test schema after rollback" do
232
      output  = script("generate model user name:string")
Y
Yves Senn 已提交
233 234
      version = output.match(/(\d+)_create_users\.rb/)[1]

235
      app_file "test/models/user_test.rb", <<-RUBY
Y
Yves Senn 已提交
236 237 238 239 240 241 242 243
        require 'test_helper'

        class UserTest < ActiveSupport::TestCase
          test "user" do
            assert_equal ["id", "name"], User.columns_hash.keys
          end
        end
      RUBY
244
      app_file "db/schema.rb", <<-RUBY
Y
Yves Senn 已提交
245 246 247 248 249 250 251 252 253 254
        ActiveRecord::Schema.define(version: #{version}) do
          create_table :users do |t|
            t.string :name
          end
        end
      RUBY

      assert_successful_test_run "models/user_test.rb"

      # Simulate `db:rollback` + edit of the migration file + `db:migrate`
255
      app_file "db/schema.rb", <<-RUBY
Y
Yves Senn 已提交
256 257 258 259 260 261 262 263 264 265
        ActiveRecord::Schema.define(version: #{version}) do
          create_table :users do |t|
            t.string :name
            t.integer :age
          end
        end
      RUBY

      assert_successful_test_run "models/user_test.rb"

266
      Dir.chdir(app_path) { `bin/rails db:test:prepare` }
Y
Yves Senn 已提交
267 268 269 270 271 272 273 274

      assert_unsuccessful_run "models/user_test.rb", <<-ASSERTION
Expected: ["id", "name"]
  Actual: ["id", "name", "age"]
      ASSERTION
    end

    test "hooks for plugins" do
275
      output  = script("generate model user name:string")
Y
Yves Senn 已提交
276 277
      version = output.match(/(\d+)_create_users\.rb/)[1]

278
      app_file "lib/tasks/hooks.rake", <<-RUBY
Y
Yves Senn 已提交
279 280 281 282 283 284 285 286 287 288 289 290 291 292
        task :before_hook do
          has_user_table = ActiveRecord::Base.connection.table_exists?('users')
          puts "before: " + has_user_table.to_s
        end

        task :after_hook do
          has_user_table = ActiveRecord::Base.connection.table_exists?('users')
          puts "after: " + has_user_table.to_s
        end

        Rake::Task["db:test:prepare"].enhance [:before_hook] do
          Rake::Task[:after_hook].invoke
        end
      RUBY
293
      app_file "test/models/user_test.rb", <<-RUBY
Y
Yves Senn 已提交
294 295 296 297 298 299 300 301 302
        require 'test_helper'
        class UserTest < ActiveSupport::TestCase
          test "user" do
            User.create! name: "Jon"
          end
        end
      RUBY

      # Simulate `db:migrate`
303
      app_file "db/schema.rb", <<-RUBY
Y
Yves Senn 已提交
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
        ActiveRecord::Schema.define(version: #{version}) do
          create_table :users do |t|
            t.string :name
          end
        end
      RUBY

      output = assert_successful_test_run "models/user_test.rb"
      assert_includes output, "before: false\nafter: true"

      # running tests again won't trigger a schema update
      output = assert_successful_test_run "models/user_test.rb"
      assert_not_includes output, "before:"
      assert_not_includes output, "after:"
    end

J
Joshua Peek 已提交
320
    private
321 322 323
      def assert_unsuccessful_run(name, message)
        result = run_test_file(name)
        assert_not_equal 0, $?.to_i
M
Michael Grosser 已提交
324
        assert_includes result, message
325 326 327
        result
      end

328 329
      def assert_successful_test_run(name)
        result = run_test_file(name)
J
Joshua Peek 已提交
330
        assert_equal 0, $?.to_i, result
331
        result
J
Joshua Peek 已提交
332 333
      end

334
      def run_test_file(name, options = {})
335
        Dir.chdir(app_path) { `bin/rails test "#{app_path}/test/#{name}" 2>&1` }
336
      end
J
Joshua Peek 已提交
337 338
  end
end