test_runner_test.rb 19.3 KB
Newer Older
1
require 'isolation/abstract_unit'
2
require 'active_support/core_ext/string/strip'
3
require 'env_helpers'
4 5 6

module ApplicationTests
  class TestRunnerTest < ActiveSupport::TestCase
7
    include ActiveSupport::Testing::Isolation, EnvHelpers
8 9 10 11 12 13 14 15 16 17 18 19

    def setup
      build_app
      create_schema
    end

    def teardown
      teardown_app
    end

    def test_run_single_file
      create_test_file :models, 'foo'
20
      create_test_file :models, 'bar'
21
      assert_match "1 runs, 1 assertions, 0 failures", run_test_command("test/models/foo_test.rb")
22 23 24 25 26
    end

    def test_run_multiple_files
      create_test_file :models,  'foo'
      create_test_file :models,  'bar'
27
      assert_match "2 runs, 2 assertions, 0 failures", run_test_command("test/models/foo_test.rb test/models/bar_test.rb")
28 29 30 31 32 33 34 35
    end

    def test_run_file_with_syntax_error
      app_file 'test/models/error_test.rb', <<-RUBY
        require 'test_helper'
        def; end
      RUBY

36 37
      error = capture(:stderr) { run_test_command('test/models/error_test.rb') }
      assert_match "syntax error", error
38 39 40 41 42 43
    end

    def test_run_models
      create_test_file :models, 'foo'
      create_test_file :models, 'bar'
      create_test_file :controllers, 'foobar_controller'
44
      run_test_command("test/models").tap do |output|
45 46
        assert_match "FooTest", output
        assert_match "BarTest", output
47
        assert_match "2 runs, 2 assertions, 0 failures", output
48 49 50 51 52 53 54
      end
    end

    def test_run_helpers
      create_test_file :helpers, 'foo_helper'
      create_test_file :helpers, 'bar_helper'
      create_test_file :controllers, 'foobar_controller'
55
      run_test_command("test/helpers").tap do |output|
56 57
        assert_match "FooHelperTest", output
        assert_match "BarHelperTest", output
58
        assert_match "2 runs, 2 assertions, 0 failures", output
59 60 61 62
      end
    end

    def test_run_units
63
      skip "we no longer have the concept of unit tests. Just different directories..."
64 65 66 67
      create_test_file :models, 'foo'
      create_test_file :helpers, 'bar_helper'
      create_test_file :unit, 'baz_unit'
      create_test_file :controllers, 'foobar_controller'
68
      run_test_units_command.tap do |output|
69 70 71
        assert_match "FooTest", output
        assert_match "BarHelperTest", output
        assert_match "BazUnitTest", output
72
        assert_match "3 runs, 3 assertions, 0 failures", output
73 74 75 76 77 78 79
      end
    end

    def test_run_controllers
      create_test_file :controllers, 'foo_controller'
      create_test_file :controllers, 'bar_controller'
      create_test_file :models, 'foo'
80
      run_test_command("test/controllers").tap do |output|
81 82
        assert_match "FooControllerTest", output
        assert_match "BarControllerTest", output
83
        assert_match "2 runs, 2 assertions, 0 failures", output
84 85 86 87 88 89 90
      end
    end

    def test_run_mailers
      create_test_file :mailers, 'foo_mailer'
      create_test_file :mailers, 'bar_mailer'
      create_test_file :models, 'foo'
91
      run_test_command("test/mailers").tap do |output|
92 93
        assert_match "FooMailerTest", output
        assert_match "BarMailerTest", output
94
        assert_match "2 runs, 2 assertions, 0 failures", output
95 96 97
      end
    end

Y
yuuji.yaginuma 已提交
98 99 100 101
    def test_run_jobs
      create_test_file :jobs, 'foo_job'
      create_test_file :jobs, 'bar_job'
      create_test_file :models, 'foo'
102
      run_test_command("test/jobs").tap do |output|
Y
yuuji.yaginuma 已提交
103 104 105 106 107 108
        assert_match "FooJobTest", output
        assert_match "BarJobTest", output
        assert_match "2 runs, 2 assertions, 0 failures", output
      end
    end

109
    def test_run_functionals
110
      skip "we no longer have the concept of functional tests. Just different directories..."
111 112 113 114
      create_test_file :mailers, 'foo_mailer'
      create_test_file :controllers, 'bar_controller'
      create_test_file :functional, 'baz_functional'
      create_test_file :models, 'foo'
115
      run_test_functionals_command.tap do |output|
116 117 118
        assert_match "FooMailerTest", output
        assert_match "BarControllerTest", output
        assert_match "BazFunctionalTest", output
119
        assert_match "3 runs, 3 assertions, 0 failures", output
120 121 122 123 124 125
      end
    end

    def test_run_integration
      create_test_file :integration, 'foo_integration'
      create_test_file :models, 'foo'
126
      run_test_command("test/integration").tap do |output|
127
        assert_match "FooIntegration", output
128
        assert_match "1 runs, 1 assertions, 0 failures", output
129 130 131
      end
    end

132
    def test_run_all_suites
Y
yuuji.yaginuma 已提交
133
      suites = [:models, :helpers, :unit, :controllers, :mailers, :functional, :integration, :jobs]
134
      suites.each { |suite| create_test_file suite, "foo_#{suite}" }
135
      run_test_command('') .tap do |output|
136
        suites.each { |suite| assert_match "Foo#{suite.to_s.camelize}Test", output }
Y
yuuji.yaginuma 已提交
137
        assert_match "8 runs, 8 assertions, 0 failures", output
138 139 140
      end
    end

141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
    def test_run_named_test
      app_file 'test/unit/chu_2_koi_test.rb', <<-RUBY
        require 'test_helper'

        class Chu2KoiTest < ActiveSupport::TestCase
          def test_rikka
            puts 'Rikka'
          end

          def test_sanae
            puts 'Sanae'
          end
        end
      RUBY

156
      run_test_command('-n test_rikka test/unit/chu_2_koi_test.rb').tap do |output|
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
        assert_match "Rikka", output
        assert_no_match "Sanae", output
      end
    end

    def test_run_matched_test
      app_file 'test/unit/chu_2_koi_test.rb', <<-RUBY
        require 'test_helper'

        class Chu2KoiTest < ActiveSupport::TestCase
          def test_rikka
            puts 'Rikka'
          end

          def test_sanae
            puts 'Sanae'
          end
        end
      RUBY

177
      run_test_command('-n /rikka/ test/unit/chu_2_koi_test.rb').tap do |output|
178 179
        assert_match "Rikka", output
        assert_no_match "Sanae", output
180 181 182
      end
    end

183 184
    def test_load_fixtures_when_running_test_suites
      create_model_with_fixture
185
      suites = [:models, :helpers, :controllers, :mailers, :integration]
186

187 188
      suites.each do |suite, directory|
        directory ||= suite
189
        create_fixture_test directory
190
        assert_match "3 users", run_test_command("test/#{suite}")
191 192 193 194
        Dir.chdir(app_path) { FileUtils.rm_f "test/#{directory}" }
      end
    end

195
    def test_run_with_model
196
      skip "These feel a bit odd. Not sure we should keep supporting them."
197 198 199 200 201 202
      create_model_with_fixture
      create_fixture_test 'models', 'user'
      assert_match "3 users", run_task(["test models/user"])
      assert_match "3 users", run_task(["test app/models/user.rb"])
    end

203
    def test_run_different_environment_using_env_var
204
      skip "no longer possible. Running tests in a different environment should be explicit"
205 206 207 208 209 210 211 212 213 214
      app_file 'test/unit/env_test.rb', <<-RUBY
        require 'test_helper'

        class EnvTest < ActiveSupport::TestCase
          def test_env
            puts Rails.env
          end
        end
      RUBY

215
      ENV['RAILS_ENV'] = 'development'
216
      assert_match "development", run_test_command('test/unit/env_test.rb')
217 218
    end

219 220 221 222 223 224
    def test_run_in_test_environment_by_default
      create_env_test

      assert_match "Current Environment: test", run_test_command('test/unit/env_test.rb')
    end

225
    def test_run_different_environment
226 227 228 229 230 231 232 233 234 235 236
      create_env_test

      assert_match "Current Environment: development",
        run_test_command("-e development test/unit/env_test.rb")
    end

    def test_generated_scaffold_works_with_rails_test
      create_scaffold
      assert_match "0 failures, 0 errors, 0 skips", run_test_command('')
    end

237 238 239 240 241
    def test_generated_controller_works_with_rails_test
      create_controller
      assert_match "0 failures, 0 errors, 0 skips", run_test_command('')
    end

242 243 244 245 246 247 248 249 250 251 252 253 254
    def test_run_multiple_folders
      create_test_file :models, 'account'
      create_test_file :controllers, 'accounts_controller'

      run_test_command('test/models test/controllers').tap do |output|
        assert_match 'AccountTest', output
        assert_match 'AccountsControllerTest', output
        assert_match '2 runs, 2 assertions, 0 failures, 0 errors, 0 skips', output
      end
    end

    def test_run_with_ruby_command
      app_file 'test/models/post_test.rb', <<-RUBY
255 256
        require 'test_helper'

257 258 259 260
        class PostTest < ActiveSupport::TestCase
          test 'declarative syntax works' do
            puts 'PostTest'
            assert true
261 262 263 264
          end
        end
      RUBY

265 266 267 268 269 270
      Dir.chdir(app_path) do
        `ruby -Itest test/models/post_test.rb`.tap do |output|
          assert_match 'PostTest', output
          assert_no_match 'is already defined in', output
        end
      end
271 272
    end

273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
    def test_mix_files_and_line_filters
      create_test_file :models, 'account'
      app_file 'test/models/post_test.rb', <<-RUBY
        require 'test_helper'

        class PostTest < ActiveSupport::TestCase
          def test_post
            puts 'PostTest'
            assert true
          end

          def test_line_filter_does_not_run_this
            assert true
          end
        end
      RUBY

      run_test_command('test/models/account_test.rb test/models/post_test.rb:4').tap do |output|
        assert_match 'AccountTest', output
        assert_match 'PostTest', output
        assert_match '2 runs, 2 assertions', output
      end
    end

297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
    def test_more_than_one_line_filter
      app_file 'test/models/post_test.rb', <<-RUBY
        require 'test_helper'

        class PostTest < ActiveSupport::TestCase
          test "first filter" do
            puts 'PostTest:FirstFilter'
            assert true
          end

          test "second filter" do
            puts 'PostTest:SecondFilter'
            assert true
          end

          test "test line filter does not run this" do
            assert true
          end
        end
      RUBY

      run_test_command('test/models/post_test.rb:4:9').tap do |output|
        assert_match 'PostTest:FirstFilter', output
        assert_match 'PostTest:SecondFilter', output
        assert_match '2 runs, 2 assertions', output
      end
    end

    def test_more_than_one_line_filter_with_multiple_files
      app_file 'test/models/account_test.rb', <<-RUBY
        require 'test_helper'

        class AccountTest < ActiveSupport::TestCase
          test "first filter" do
            puts 'AccountTest:FirstFilter'
            assert true
          end

          test "second filter" do
            puts 'AccountTest:SecondFilter'
            assert true
          end

          test "line filter does not run this" do
            assert true
          end
        end
      RUBY

      app_file 'test/models/post_test.rb', <<-RUBY
        require 'test_helper'

        class PostTest < ActiveSupport::TestCase
          test "first filter" do
            puts 'PostTest:FirstFilter'
            assert true
          end

          test "second filter" do
            puts 'PostTest:SecondFilter'
            assert true
          end

          test "line filter does not run this" do
            assert true
          end
        end
      RUBY

366
      run_test_command('test/models/account_test.rb:4:9 test/models/post_test.rb:4:9').tap do |output|
367 368 369 370 371 372 373 374
        assert_match 'AccountTest:FirstFilter', output
        assert_match 'AccountTest:SecondFilter', output
        assert_match 'PostTest:FirstFilter', output
        assert_match 'PostTest:SecondFilter', output
        assert_match '4 runs, 4 assertions', output
      end
    end

375 376 377 378 379 380 381 382 383 384
    def test_multiple_line_filters
      create_test_file :models, 'account'
      create_test_file :models, 'post'

      run_test_command('test/models/account_test.rb:4 test/models/post_test.rb:4').tap do |output|
        assert_match 'AccountTest', output
        assert_match 'PostTest', output
      end
    end

385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
    def test_line_filters_trigger_only_one_runnable
      app_file 'test/models/post_test.rb', <<-RUBY
        require 'test_helper'

        class PostTest < ActiveSupport::TestCase
          test 'truth' do
            assert true
          end
        end

        class SecondPostTest < ActiveSupport::TestCase
          test 'truth' do
            assert false, 'ran second runnable'
          end
        end
      RUBY

      # Pass seed guaranteeing failure.
      run_test_command('test/models/post_test.rb:4 --seed 30410').tap do |output|
        assert_no_match 'ran second runnable', output
        assert_match '1 runs, 1 assertions', output
      end
    end

409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
    def test_line_filter_with_minitest_string_filter
      app_file 'test/models/post_test.rb', <<-RUBY
        require 'test_helper'

        class PostTest < ActiveSupport::TestCase
          test 'by line' do
            puts 'by line'
            assert true
          end

          test 'by name' do
            puts 'by name'
            assert true
          end
        end
      RUBY

      run_test_command('test/models/post_test.rb:4 -n test_by_name').tap do |output|
        assert_match 'by line', output
        assert_match 'by name', output
        assert_match '2 runs, 2 assertions', output
      end
    end

433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
    def test_shows_filtered_backtrace_by_default
      create_backtrace_test

      assert_match 'Rails::BacktraceCleaner', run_test_command('test/unit/backtrace_test.rb')
    end

    def test_backtrace_option
      create_backtrace_test

      assert_match 'Minitest::BacktraceFilter', run_test_command('test/unit/backtrace_test.rb -b')
      assert_match 'Minitest::BacktraceFilter',
        run_test_command('test/unit/backtrace_test.rb --backtrace')
    end

    def test_show_full_backtrace_using_backtrace_environment_variable
      create_backtrace_test

      switch_env 'BACKTRACE', 'true' do
        assert_match 'Minitest::BacktraceFilter', run_test_command('test/unit/backtrace_test.rb')
      end
    end

    def test_run_app_without_rails_loaded
      # Simulate a real Rails app boot.
      app_file 'config/boot.rb', <<-RUBY
        ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)

        require 'bundler/setup' # Set up gems listed in the Gemfile.
      RUBY

      assert_match '0 runs, 0 assertions', run_test_command('')
464 465
    end

466
    def test_output_inline_by_default
467
      create_test_file :models, 'post', pass: false
468 469

      output = run_test_command('test/models/post_test.rb')
470
      expect = %r{Running:\n\nPostTest\nF\n\nFailure:\nPostTest#test_truth \[[^\]]+test/models/post_test.rb:6\]:\nwups!\n\nbin/rails test test/models/post_test.rb:4\n\n\n\n}
471
      assert_match expect, output
472 473
    end

474 475
    def test_only_inline_failure_output
      create_test_file :models, 'post', pass: false
476 477 478 479 480

      output = run_test_command('test/models/post_test.rb')
      assert_match %r{Finished in.*\n\n1 runs, 1 assertions}, output
    end

481
    def test_fail_fast
482
      create_test_file :models, 'post', pass: false
483 484 485 486 487

      assert_match(/Interrupt/,
        capture(:stderr) { run_test_command('test/models/post_test.rb --fail-fast') })
    end

488 489 490 491 492
    def test_raise_error_when_specified_file_does_not_exist
      error = capture(:stderr) { run_test_command('test/not_exists.rb') }
      assert_match(%r{cannot load such file.+test/not_exists\.rb}, error)
    end

493 494 495
    def test_pass_TEST_env_on_rake_test
      create_test_file :models, 'account'
      create_test_file :models, 'post', pass: false
496 497
      # This specifically verifies TEST for backwards compatibility with rake test
      # as bin/rails test already supports running tests from a single file more cleanly.
498 499 500 501 502 503 504
      output =  Dir.chdir(app_path) { `bin/rake test TEST=test/models/post_test.rb` }

      assert_match "PostTest", output, "passing TEST= should run selected test"
      assert_no_match "AccountTest", output, "passing TEST= should only run selected test"
      assert_match '1 runs, 1 assertions', output
    end

505 506 507 508 509 510 511 512
    def test_pass_rake_options
      create_test_file :models, 'account'
      output =  Dir.chdir(app_path) { `bin/rake --rakefile Rakefile --trace=stdout test` }

      assert_match '1 runs, 1 assertions', output
      assert_match 'Execute test', output
    end

513 514 515 516 517 518 519 520 521 522 523 524 525
    def test_rails_db_create_all_restores_db_connection
      create_test_file :models, 'account'
      output =  Dir.chdir(app_path) { `bin/rails db:create:all db:migrate && echo ".tables" | rails dbconsole` }
      assert_match "ar_internal_metadata", output, "tables should be dumped"
    end

    def test_rails_db_create_all_restores_db_connection_after_drop
      create_test_file :models, 'account'
      Dir.chdir(app_path) { `bin/rails db:create:all` } # create all to avoid warnings
      output =  Dir.chdir(app_path) { `bin/rails db:drop:all db:create:all db:migrate && echo ".tables" | rails dbconsole` }
      assert_match "ar_internal_metadata", output, "tables should be dumped"
    end

526 527 528 529 530 531 532 533 534 535 536 537 538
    def test_rake_passes_TESTOPTS_to_minitest
      create_test_file :models, 'account'
      output =  Dir.chdir(app_path) { `bin/rake test TESTOPTS=-v` }
      assert_match "AccountTest#test_truth", output, "passing TEST= should run selected test"
    end

    def test_rake_passes_multiple_TESTOPTS_to_minitest
      create_test_file :models, 'account'
      output =  Dir.chdir(app_path) { `bin/rake test TESTOPTS='-v --seed=1234'` }
      assert_match "AccountTest#test_truth", output, "passing TEST= should run selected test"
      assert_match "seed=1234", output, "passing TEST= should run selected test"
    end

539 540
    private
      def run_test_command(arguments = 'test/unit/test_test.rb')
541
        Dir.chdir(app_path) { `bin/rails t #{arguments}` }
542 543
      end

544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
      def create_model_with_fixture
        script 'generate model user name:string'

        app_file 'test/fixtures/users.yml', <<-YAML.strip_heredoc
          vampire:
            id: 1
            name: Koyomi Araragi
          crab:
            id: 2
            name: Senjougahara Hitagi
          cat:
            id: 3
            name: Tsubasa Hanekawa
        YAML

559
        run_migration
560 561 562 563 564 565 566 567 568 569 570 571 572 573
      end

      def create_fixture_test(path = :unit, name = 'test')
        app_file "test/#{path}/#{name}_test.rb", <<-RUBY
          require 'test_helper'

          class #{name.camelize}Test < ActiveSupport::TestCase
            def test_fixture
              puts "\#{User.count} users (\#{__FILE__})"
            end
          end
        RUBY
      end

574 575 576 577 578 579 580 581 582 583 584 585
      def create_backtrace_test
        app_file 'test/unit/backtrace_test.rb', <<-RUBY
          require 'test_helper'

          class BacktraceTest < ActiveSupport::TestCase
            def test_backtrace
              puts Minitest.backtrace_filter
            end
          end
        RUBY
      end

586 587 588 589
      def create_schema
        app_file 'db/schema.rb', ''
      end

590
      def create_test_file(path = :unit, name = 'test', pass: true)
591 592 593 594 595 596
        app_file "test/#{path}/#{name}_test.rb", <<-RUBY
          require 'test_helper'

          class #{name.camelize}Test < ActiveSupport::TestCase
            def test_truth
              puts "#{name.camelize}Test"
597
              assert #{pass}, 'wups!'
598 599 600 601
            end
          end
        RUBY
      end
602

603 604 605 606 607 608 609 610 611 612 613 614
      def create_env_test
        app_file 'test/unit/env_test.rb', <<-RUBY
          require 'test_helper'

          class EnvTest < ActiveSupport::TestCase
            def test_env
              puts "Current Environment: \#{Rails.env}"
            end
          end
        RUBY
      end

615 616 617 618 619 620
      def create_scaffold
        script 'generate scaffold user name:string'
        Dir.chdir(app_path) { File.exist?('app/models/user.rb') }
        run_migration
      end

621 622 623 624
      def create_controller
        script 'generate controller admin/dashboard index'
      end

625
      def run_migration
626
        Dir.chdir(app_path) { `bin/rails db:migrate` }
627
      end
628 629
  end
end