From 79a06225ef0e148eb5da541711f74163b5efb18d Mon Sep 17 00:00:00 2001 From: Jamis Buck Date: Wed, 19 Jan 2011 10:08:58 -0700 Subject: [PATCH] scrub instance variables from test cases on teardown this prevents test state from accumulating, resulting in leaked objects and slow tests due to overactive GC. --- activesupport/lib/active_support/test_case.rb | 2 ++ .../testing/garbage_collection.rb | 19 +++++++++++++++++++ activesupport/test/test_case_test.rb | 18 ++++++++++++++++++ activesupport/test/test_test.rb | 4 ++-- 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 activesupport/lib/active_support/testing/garbage_collection.rb diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb index fb52fc708358d..a7053a11347ea 100644 --- a/activesupport/lib/active_support/test_case.rb +++ b/activesupport/lib/active_support/test_case.rb @@ -6,6 +6,7 @@ require 'active_support/testing/pending' require 'active_support/testing/isolation' require 'active_support/core_ext/kernel/reporting' +require 'active_support/testing/garbage_collection' begin silence_warnings { require 'mocha' } @@ -37,5 +38,6 @@ def self.for_tag(tag) include ActiveSupport::Testing::Deprecation include ActiveSupport::Testing::Pending extend ActiveSupport::Testing::Declarative + include ActiveSupport::Testing::GarbageCollection end end diff --git a/activesupport/lib/active_support/testing/garbage_collection.rb b/activesupport/lib/active_support/testing/garbage_collection.rb new file mode 100644 index 0000000000000..7bf9fbafa6826 --- /dev/null +++ b/activesupport/lib/active_support/testing/garbage_collection.rb @@ -0,0 +1,19 @@ +module ActiveSupport + module Testing + module GarbageCollection + def self.included(base) + base.teardown :scrub_leftover_instance_variables + end + + private + + RESERVED_INSTANCE_VARIABLES = %w(@test_passed @passed @method_name @__name__ @_result).map(&:to_sym) + + def scrub_leftover_instance_variables + (instance_variables.map(&:to_sym) - RESERVED_INSTANCE_VARIABLES).each do |var| + remove_instance_variable(var) + end + end + end + end +end diff --git a/activesupport/test/test_case_test.rb b/activesupport/test/test_case_test.rb index b6a96b2ae7c89..740c2351eac23 100644 --- a/activesupport/test/test_case_test.rb +++ b/activesupport/test/test_case_test.rb @@ -74,5 +74,23 @@ def test_true; assert true end assert_match %r{oh noes}, exception.message end + + def test_teardown_should_scrub_instance_variables + tc = Class.new(TestCase) do + def test_true; @alpha = "a"; assert_equal "a", @alpha; end + end + + test_name = 'test_true' + fr = FakeRunner.new + + test = tc.new test_name + test.run(fr) {} + + passed_var = IS_MINITEST ? :@passed : :@test_passed + ivars = test.instance_variables.map(&:to_sym) + + assert ivars.include?(passed_var), "#{passed_var} should not have been scrubbed" + assert !ivars.include?(:@alpha), "@alpha should have been scrubbed" + end end end diff --git a/activesupport/test/test_test.rb b/activesupport/test/test_test.rb index ee5a20c789fd7..ea652844f50ea 100644 --- a/activesupport/test/test_test.rb +++ b/activesupport/test/test_test.rb @@ -137,7 +137,7 @@ class SetupAndTeardownTest < ActiveSupport::TestCase def test_inherited_setup_callbacks assert_equal [:reset_callback_record, :foo], self.class._setup_callbacks.map(&:raw_filter) assert_equal [:foo], @called_back - assert_equal [:foo, :sentinel, :foo], self.class._teardown_callbacks.map(&:raw_filter) + assert_equal [:scrub_leftover_instance_variables, :foo, :sentinel, :foo], self.class._teardown_callbacks.map(&:raw_filter) end def setup @@ -169,7 +169,7 @@ class SubclassSetupAndTeardownTest < SetupAndTeardownTest def test_inherited_setup_callbacks assert_equal [:reset_callback_record, :foo, :bar], self.class._setup_callbacks.map(&:raw_filter) assert_equal [:foo, :bar], @called_back - assert_equal [:foo, :sentinel, :foo, :bar], self.class._teardown_callbacks.map(&:raw_filter) + assert_equal [:scrub_leftover_instance_variables, :foo, :sentinel, :foo, :bar], self.class._teardown_callbacks.map(&:raw_filter) end protected