aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/test/isolation_test.rb
blob: a7af5e96f6d8a9d43e063664a10d1756353cb595 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
require 'abstract_unit'
require 'rbconfig'

if defined?(MiniTest) || defined?(Test::Unit::TestResultFailureSupport)
  $stderr.puts "Isolation tests can test test-unit 1 only"

elsif ENV['CHILD']
  class ChildIsolationTest < ActiveSupport::TestCase
    include ActiveSupport::Testing::Isolation

    def self.setup
      File.open(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"), "a") do |f|
        f.puts "hello"
      end
    end

    def setup
      @instance = "HELLO"
    end

    def teardown
      raise if @boom
    end

    test "runs the test" do
      assert true
    end

    test "captures errors" do
      raise
    end

    test "captures failures" do
      assert false
    end

    test "first runs in isolation" do
      assert_nil $x
      $x = 1
    end

    test "second runs in isolation" do
      assert_nil $x
      $x = 2
    end

    test "runs with slow tests" do
      sleep 0.3
      assert true
      sleep 0.2
    end

    test "runs setup" do
      assert "HELLO", @instance
    end

    test "runs teardown" do
      @boom = true
    end

    test "resets requires one" do
      assert !defined?(OmgOmg)
      assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/omgomg/).size
      require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "omgomg"))
    end

    test "resets requires two" do
      assert !defined?(OmgOmg)
      assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/omgomg/).size
      require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "omgomg"))
    end
  end
else
  class ParentIsolationTest < ActiveSupport::TestCase

    File.open(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"), "w") {}

    ENV["CHILD"] = "1"
    OUTPUT = `#{RbConfig::CONFIG["bindir"]}/#{RbConfig::CONFIG["ruby_install_name"]} -I#{File.dirname(__FILE__)} "#{File.expand_path(__FILE__)}" -v`
    ENV.delete("CHILD")

    def setup
      defined?(::MiniTest) ? parse_minitest : parse_testunit
    end

    def parse_testunit
      @results = {}
      OUTPUT[/Started\n\s*(.*)\s*\nFinished/mi, 1].to_s.split(/\s*\n\s*/).each do |result|
        result =~ %r'^(\w+)\(\w+\):\s*(\.|E|F)$'
        @results[$1] = { 'E' => :error, '.' => :success, 'F' => :failure }[$2]
      end

      # Extract the backtraces
      @backtraces = {}
      OUTPUT.scan(/^\s*\d+\).*?\n\n/m).each do |backtrace|
        # \n  1) Error:\ntest_captures_errors(ChildIsolationTest):
        backtrace =~ %r'\s*\d+\)\s*(Error|Failure):\n(\w+)'i
        @backtraces[$2] = { :type => $1, :output => backtrace }
      end
    end

    def parse_minitest
      @results = {}
      OUTPUT[/Started\n\s*(.*)\s*\nFinished/mi, 1].to_s.split(/\s*\n\s*/).each do |result|
        result =~ %r'^\w+#(\w+):.*:\s*(.*Assertion.*|.*RuntimeError.*|\.\s*)$'
        val = :success
        val = :error if $2.include?('RuntimeError')
        val = :failure if $2.include?('Assertion')

        @results[$1] = val
      end

      # Extract the backtraces
      @backtraces = {}
      OUTPUT.scan(/^\s*\d+\).*?\n\n/m).each do |backtrace|
        # \n  1) Error:\ntest_captures_errors(ChildIsolationTest):
        backtrace =~ %r'\s*\d+\)\s*(Error|Failure):\n(\w+)'i
        @backtraces[$2] = { :type => $1, :output => backtrace }
      end
    end

    def assert_failing(name)
      assert_equal :failure, @results[name.to_s], "Test #{name} failed"
    end

    def assert_passing(name)
      assert_equal :success, @results[name.to_s], "Test #{name} passed"
    end

    def assert_erroring(name)
      assert_equal :error, @results[name.to_s], "Test #{name} errored"
    end

    test "has all tests" do
      assert_equal 10, @results.length
    end

    test "passing tests are still reported" do
      assert_passing :test_runs_the_test
      assert_passing :test_runs_with_slow_tests
    end

    test "resets global variables" do
      assert_passing :test_first_runs_in_isolation
      assert_passing :test_second_runs_in_isolation
    end

    test "resets requires" do
      assert_passing :test_resets_requires_one
      assert_passing :test_resets_requires_two
    end

    test "erroring tests are still reported" do
      assert_erroring :test_captures_errors
    end

    test "runs setup and teardown methods" do
      assert_passing :test_runs_setup
      assert_erroring :test_runs_teardown
    end

    test "correct tests fail" do
      assert_failing :test_captures_failures
    end

    test "backtrace is printed for errors" do
      assert_equal 'Error', @backtraces["test_captures_errors"][:type]
      assert_match %r{isolation_test.rb:\d+}, @backtraces["test_captures_errors"][:output]
    end

    test "backtrace is printed for failures" do
      assert_equal 'Failure', @backtraces["test_captures_failures"][:type]
      assert_match %r{isolation_test.rb:\d+}, @backtraces["test_captures_failures"][:output]
    end

    test "self.setup is run only once" do
      text = File.read(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"))
      assert_equal "hello\n", text
    end

  end
end