#Beaker for Modules ##Read the Beaker Docs [Beaker How To](https://github.com/puppetlabs/beaker/wiki) Beaker DSL API ##Understand the Difference Between beaker and beaker-rspec [beaker vs. beaker-rspec](https://github.com/puppetlabs/beaker/wiki/beaker-vs.-beaker-rspec) ##beaker-rspec Details ###Supported ENV variables `BEAKER_debug` - turn on extended debug logging `BEAKER_set` - set to the name of the node file to be used during testing (exclude .yml file extension, it will be added by beaker-rspec), assumed to be in module's spec/acceptance/nodesets directory `BEAKER_setfile` - set to the full path to a node file be used during testing (be sure to include full path and file extensions, beaker-rspec will use this path without editing/altering it in any way) `BEAKER_destroy` - set to `no` to preserve test boxes after testing, set to `onpass` to destroy only if tests pass `BEAKER_provision` - set to `no` to skip provisioning boxes before testing, will then assume that boxes are already provisioned and reachable ##Typical Workflow 1. Run tests with `BEAKER_destroy=no`, no setting for `BEAKER_provision` * beaker-rspec will use spec/acceptance/nodesets/default.yml node file * boxes will be newly provisioned * boxes will be preserved post-testing * Run tests with `BEAKER_destroy=no` and `BEAKER_provision=no` * beaker-rspec will use spec/acceptance/nodesets/default.yml node file * boxes will be re-used from previous run * boxes will be preserved post-testing * Nodes become corrupted with too many test runs/bad data and need to be refreshed then GOTO step 1 * Testing is complete and you want to clean up, run once more with `BEAKER_destroy` unset * you can also: cd .vagrant/beaker_vagrant_files/default.yml ; vagrant destroy --force ##Building your Module Testing Environment Using puppetlabs-mysql as an example module. ###Clone the module repository of the module that you wish to test git clone https://github.com/puppetlabs/puppetlabs-mysql cd puppetlabs-mysql ###Create the spec_helper_acceptance.rb Create example file spec_helper_acceptance.rb: ```ruby require 'beaker-rspec' require 'pry' hosts.each do |host| # Install Puppet on host, install_puppet end RSpec.configure do |c| module_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) c.formatter = :documentation # Configure all nodes in nodeset c.before :suite do # Install module puppet_module_install(:source => module_root, :module_name => 'mysql') hosts.each do |host| on host, puppet('module','install','puppetlabs-stdlib'), { :acceptable_exit_codes => [0,1] } end end end ``` Update spec_helper_acceptance.rb to reflect the module under test. You will need to set the correct module name and add any module dependencies. Place the file in the /spec directory (in this case puppetlabs-mysql/spec) ###Install beaker-rspec ####From Gem (preferred) gem install beaker-rspec ###Update the module's Gemfile In module's top level directory edit Gemfile. Add `gem 'beaker-rspec', :require => false` under `group :development, :test do`. bundle install ###Create node files These files indicate the nodes (or hosts) that the tests will be run on. By default, any node file called `default.yml` will be used. You can override this using the `BEAKER_set` environment variable to indicate an alternate file. Do not provide full path or the '.yml' file extension to `BEAKER_set`, it is assumed to be located in 'spec/acceptance/nodesets/${NAME}.yml' by beaker-rspec. If you wish to use a completely different file location use `BEAKER_setfile` and set it to the full path (including file extension) of your hosts file. Nodes are pulled from Puppet Labs Vagrant Boxes. Example node files can be found here: *[Puppet Labs example Vagrant node files](Example-Vagrant-Hosts-Files.md) Create the nodesets directory. From module's top level directory: mkdir -p spec/acceptance/nodesets Copy any nodesets that you wish to use into the nodesets directory. ###Create spec tests for your module Spec tests are written in RSpec. Example spec file (mysql_account_delete_spec.rb): ```ruby require 'spec_helper_acceptance' describe 'mysql::server::account_security class' do describe 'running puppet code' do it 'should work with no errors' do pp = <<-EOS class { 'mysql::server': remove_default_accounts => true } EOS # Run it twice and test for idempotency apply_manifest(pp, :catch_failures => true) expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero end describe 'accounts' do it 'should delete accounts' do shell("mysql -e 'show grants for root@127.0.0.1;'", :acceptable_exit_codes => 1) end it 'should delete databases' do shell("mysql -e 'show databases;' |grep test", :acceptable_exit_codes => 1) end end end end ``` ###Run your spec tests From module's top level directory bundle exec rspec spec/acceptance