Class: Puppet::Test::TestHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet/test/test_helper.rb

Overview

This class is intended to provide an API to be used by external projects

when they are running tests that depend on puppet core.  This should
allow us to vary the implementation details of managing puppet's state
for testing, from one version of puppet to the next--without forcing
the external projects to do any of that state management or be aware of
the implementation details.

For now, this consists of a few very simple signatures. The plan is

that it should be the responsibility of the puppetlabs_spec_helper
to broker between external projects and this API; thus, if any
hacks are required (e.g. to determine whether or not a particular)
version of puppet supports this API, those hacks will be consolidated in
one place and won't need to be duplicated in every external project.

This should also alleviate the anti-pattern that we’ve been following,

wherein each external project starts off with a copy of puppet core's
test_helper.rb and is exposed to risk of that code getting out of
sync with core.

Since this class will be “library code” that ships with puppet, it does

not use API from any existing test framework such as rspec.  This should
theoretically allow it to be used with other unit test frameworks in the
future, if desired.

Note that in the future this API could potentially be expanded to handle

other features such as "around_test", but we didn't see a compelling
reason to deal with that right now.

Class Method Summary collapse

Class Method Details

.after_all_testsObject

Call this method once, at the end of a test run, when no more tests

will be run.

Returns:

  • nil



49
50
51
# File 'lib/puppet/test/test_helper.rb', line 49

def self.after_all_tests()

end

.after_each_testObject

Call this method once per test, after execution of each individual test.

Returns:

  • nil



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
# File 'lib/puppet/test/test_helper.rb', line 98

def self.after_each_test()
  Puppet.settings.send(:clear_everything_for_tests)

  Puppet::Util::Storage.clear
  Puppet::Util::ExecutionStub.reset

  Puppet.clear_deprecation_warnings

  # uncommenting and manipulating this can be useful when tracking down calls to deprecated code
  #Puppet.log_deprecations_to_file("deprecations.txt", /^Puppet::Util.exec/)

  # Restore the indirector configuration.  See before hook.
  indirections = Puppet::Indirector::Indirection.send(:class_variable_get, :@@indirections)
  indirections.each do |indirector|
    $saved_indirection_state.fetch(indirector.name, {}).each do |variable, value|
      indirector.instance_variable_set(variable, value)
    end
  end
  $saved_indirection_state = nil

  # Restore the global process environment.  Can't just assign because this
  # is a magic variable, sadly, and doesn't do that™.  It is sufficiently
  # faster to use the compare-then-set model to avoid excessive work that it
  # justifies the complexity.  --daniel 2012-03-15
  unless ENV.to_hash == $old_env
    ENV.clear
    $old_env.each {|k, v| ENV[k] = v }
  end


  # Some tests can cause us to connect, in which case the lingering
  # connection is a resource that can cause unexpected failure in later
  # tests, as well as sharing state accidentally.
  # We're testing if ActiveRecord::Base is defined because some test cases
  # may stub Puppet.features.rails? which is how we should normally
  # introspect for this functionality.
  ActiveRecord::Base.remove_connection if defined?(ActiveRecord::Base)

  # Restore the load_path late, to avoid messing with stubs from the test.
  $LOAD_PATH.clear
  $old_load_path.each {|x| $LOAD_PATH << x }

end

.before_all_testsObject

Call this method once, when beginning a test run–prior to running

any individual tests.

Returns:

  • nil



42
43
44
# File 'lib/puppet/test/test_helper.rb', line 42

def self.before_all_tests()

end

.before_each_testObject

Call this method once per test, prior to execution of each invididual test.

Returns:

  • nil



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
# File 'lib/puppet/test/test_helper.rb', line 55

def self.before_each_test()
  # We need to preserve the current state of all our indirection cache and
  # terminus classes.  This is pretty important, because changes to these
  # are global and lead to order dependencies in our testing.
  #
  # We go direct to the implementation because there is no safe, sane public
  # API to manage restoration of these to their default values.  This
  # should, once the value is proved, be moved to a standard API on the
  # indirector.
  #
  # To make things worse, a number of the tests stub parts of the
  # indirector.  These stubs have very specific expectations that what
  # little of the public API we could use is, well, likely to explode
  # randomly in some tests.  So, direct access.  --daniel 2011-08-30
  $saved_indirection_state = {}
  indirections = Puppet::Indirector::Indirection.send(:class_variable_get, :@@indirections)
  indirections.each do |indirector|
    $saved_indirection_state[indirector.name] = {
        :@terminus_class => indirector.instance_variable_get(:@terminus_class),
        :@cache_class    => indirector.instance_variable_get(:@cache_class)
    }
  end

  # The process environment is a shared, persistent resource.
  $old_env = ENV.to_hash

  # So is the load_path
  $old_load_path = $LOAD_PATH.dup

  initialize_settings_before_each()

  Puppet::Node::Environment.clear
  Puppet::Parser::Functions.reset
  Puppet::Application.clear!
  Puppet::Util::Profiler.clear

  Puppet.clear_deprecation_warnings

  Puppet::DataBinding::Hiera.instance_variable_set("@hiera", nil)
end

.initializeObject

Call this method once, as early as possible, such as before loading tests that call Puppet.

Returns:

  • nil



35
36
37
# File 'lib/puppet/test/test_helper.rb', line 35

def self.initialize()
  initialize_settings_before_each
end