module Beaker::DSL::Structure

def confine(type, criteria, host_array = nil, &block)

Raises:
  • (SkipTest) - Raises skip test if there are no valid hosts for

Returns:
  • (Array) - Returns an array of hosts that are still valid

Other tags:
    Example: Confining to any non-windows agents + all non-agents -
    Example: Confining to all ubuntu agents + all non-agents -
    Example: Confining from an already defined subset of hosts -
    Example: Confining to an already defined subset of hosts -
    Example: Using additional block to confine to Solaris global zone. -
    Example: Confining to anything but Windows and Solaris -
    Example: Basic usage to confine to debian OSes. -

Parameters:
  • block (Proc) -- Addition checks to determine suitability of hosts
  • host_array (Array) -- This creatively named parameter is
  • (Hash{Symbol,String=>String,Regexp,Array}) --
  • type (Symbol) -- The type of confinement to do. Valid parameters

Other tags:
    Note: - This will modify the {Beaker::TestCase#hosts} member
def confine(type, criteria, host_array = nil, &block)
  hosts_to_modify = Array(host_array || hosts)
  hosts_not_modified = hosts - hosts_to_modify # we aren't examining these hosts
  case type
  when :except
    hosts_to_modify = if criteria and (not criteria.empty?)
                        hosts_to_modify - select_hosts(criteria, hosts_to_modify, &block) + hosts_not_modified
                      else
                        # confining to all hosts *except* provided array of hosts
                        hosts_not_modified
                      end
    if hosts_to_modify.empty?
      logger.warn "No suitable hosts without: #{criteria.inspect}"
      skip_test "No suitable hosts found without #{criteria.inspect}"
    end
  when :to
    if criteria and (not criteria.empty?)
      hosts_to_modify = select_hosts(criteria, hosts_to_modify, &block) + hosts_not_modified
    else
      # confining to only hosts in provided array of hosts
    end
    if hosts_to_modify.empty?
      logger.warn "No suitable hosts with: #{criteria.inspect}"
      skip_test "No suitable hosts found with #{criteria.inspect}"
    end
  else
    raise "Unknown option #{type}"
  end
  self.hosts = hosts_to_modify
  hosts_to_modify
end

def confine_block(type, criteria, host_array = nil)

Other tags:
    See: #confine -
def confine_block(type, criteria, host_array = nil)
  host_array = Array(host_array || hosts)
  original_hosts = self.hosts.dup
  confine(type, criteria, host_array)
  yield
rescue Beaker::DSL::Outcomes::SkipTest => e
  # I don't like this much, but adding options to confine is a breaking change
  # to the DSL that would involve a major version bump
  if !e.message.include?('No suitable hosts found')
    # a skip generated from the provided block, pass it up the chain
    raise e
  end
ensure
  self.hosts = original_hosts
end

def expect_failure(explanation)

Other tags:
    Author: - Chris Cowell-Shah (ccs@puppetlabs.com)

Raises:
  • (RuntimeError) - if the code block passed to this method does not raise

Parameters:
  • block (Proc) -- block of code is expected to either raise an
  • explanation (String) -- A description of why this assert is expected to

Other tags:
    Example: Output when the product bug has been fixed -
    Example: Output when a product bug would normally cause the assert to fail -
    Example: Typical usage -
def expect_failure(explanation)
  begin
    yield if block_given? # code block should contain an assert that you expect to fail
  rescue Beaker::DSL::Assertions, Minitest::Assertion => e
    # Yay! The assert in the code block failed, as expected.
    # Swallow the failure so the test passes.
    logger.notify 'An assertion was expected to fail, and did. ' +
                  'This is probably due to a known product bug, ' +
                  'and is probably not a problem. ' +
                  "Additional info: '#{explanation}' " +
                  "Failed assertion: '#{e}'"
    return
  end
  # Uh-oh! The assert in the code block unexpectedly passed.
  fail('An assertion was expected to fail, but passed. ' +
           'This is probably because a product bug was fixed, and ' +
           '"expect_failure()" needs to be removed from this test. ' +
           "Additional info: '#{explanation}'")
end

def inspect_host(host, property, one_or_more_values)

@!visibility private
def inspect_host(host, property, one_or_more_values)
  Array(one_or_more_values).any? do |value|
    case value
    when String
      host[property.to_s].include? value
    when Regexp
      value.match?(host[property.to_s])
    else
      false
    end
  end
end

def manual_step step_name

Parameters:
  • step_name (String) -- The name of the step to be logged.
def manual_step step_name
  require 'readline'
  logger.notify "\n* #{step_name}\n"
  if !@options.has_key?(:exec_manual_tests)
    # if the option -exec-manual-tests is not set then this has executed outside of a manual tests
    # so we raise an error to avoid issues
    raise('--exec-manual-tests option not set, this means a manual_step was used outside a manual_test')
  end
  set_current_step_name(step_name)
  # Here we prompt the user to tell us if the step passed or failed
  loop do
    input = Readline.readline('Did this step pass, Y/n? ', true).squeeze(" ").strip.downcase
    if %w(y yes).include?(input)
      break
    elsif %w(n no).include?(input)
      # if the step failed, the user can enter a fail message.
      # we loops to ensure they give use a fail message
      fail_message = ''
      loop do
        fail_message = Readline.readline('What was the reason for failure? ', true).squeeze(" ").strip
        break unless fail_message == ''
        # if nothing is entered we tell the user to enter something
        puts "No reason for failure given, please enter reason for failure."
      end
      raise Beaker::DSL::FailTest, fail_message
    else
      # if something other than Y or n is returned we ask them again
      puts "Please enter Y or n."
    end
  end
end

def manual_test manual_test_name, &block

Parameters:
  • block (Proc) -- The actions to be performed during this test.
  • manual_test_name (String) -- The name of the test to be logged.
def manual_test manual_test_name, &block
  if @options.has_key?(:exec_manual_tests) && @options[:exec_manual_tests] == true
    # here the option is set so we run the test as normal
    test_name manual_test_name, &block
  else
    # here no option was set so we log the test name and skip it
    test_name manual_test_name
    raise(Beaker::DSL::SkipTest,
          '--exec-manual-tests option not set, so skipping manual test')
  end
end

def select_hosts(criteria, host_array = nil, &block)

Returns:
  • (Array) - Returns an array of hosts that meet the provided criteria

Parameters:
  • block (Proc) -- Addition checks to determine suitability of hosts
  • host_array (Array) -- This creatively named parameter is
  • (Hash{Symbol,String=>String,Regexp,Array}) --
def select_hosts(criteria, host_array = nil, &block)
  hosts_to_select_from = host_array || hosts
  criteria.each_pair do |property, value|
    hosts_to_select_from = hosts_to_select_from.select do |host|
      inspect_host host, property, value
    end
  end
  hosts_to_select_from = hosts_to_select_from.select(&block) if block
  hosts_to_select_from
end

def step step_name, &block

Parameters:
  • block (Proc) -- The actions to be performed in this step.
  • step_name (String) -- The name of the step to be logged.
def step step_name, &block
  logger.notify "\n* #{step_name}\n"
  set_current_step_name(step_name)
  return unless block
  begin
    logger.with_indent(&block)
  rescue Exception => e
    if @options.has_key?(:debug_errors) && @options[:debug_errors] == true
      begin
        require 'pry'
      rescue LoadError
        begin
          require 'debug'
        rescue LoadError
          logger.exception('Unable to load pry and debug while debug_errors was true')
        else
          logger.info("Exception raised during step execution and debug-errors option is set, entering debug. Exception was: #{e.inspect}")
          binding.break # rubocop:disable Lint/Debugger
        end
      else
        logger.info("Exception raised during step execution and debug-errors option is set, entering pry. Exception was: #{e.inspect}")
        logger.info("HINT: Use the pry 'backtrace' and 'up' commands to navigate to the test code")
        binding.pry # rubocop:disable Lint/Debugger
      end
    end
    raise e
  end
end

def teardown &block

Other tags:
    Example: Always remove /etc/puppet/modules -

Parameters:
  • block (Proc) -- block of code to execute during teardown
def teardown &block
  @teardown_procs << block
end

def test_name my_name, &block

Parameters:
  • block (Proc) -- The actions to be performed during this test.
  • my_name (String) -- The name of the test to be logged.
def test_name my_name, &block
  logger.notify "\n#{my_name}\n"
  set_current_test_name(my_name)
  return unless block
  logger.with_indent(&block)
end