Distributed automated acceptance testing with Robot and Chef - codecentric AG Blog

:

I just go on working on some edge topics around the Robot Framework and blogging about it.

I’ve assume you’re familiar with Chef and Robot Framework as well as VirtualBox and Vagrant. For the basic setup, I suggest my previous post on a similar topic and on how to set up a basic environment: Provisioning of Java web applications using Chef, VirtualBox and Vagrant

What we now want to do is to distribute a Robot test to several virtual box instances. You would do this primarily in order to reduce the acceptance test run time. Whenever you see a way to run pieces of your acceptance test suite in parallel, you should do it. And with this blog post I would like to show you one possible way how to do it using very well proven tools.

So, you take Robot for acceptance testing. You take Chef to provision basic framework components to several machines. You take Vagrant and VirtualBox for a poor’s man virtualization and wiring with Chef. In a bigger setup, you sure would use different virtualization mechanisms, but Chef might still be your choice for configuration management.

How this all will work

First, you need my freshly created Chef cookbooks for the Robot tests: “robot” and “robottest”: https://github.com/pavlobaron/cookbooks/tree/pb_new

Then, you need to configure your Vagrant (again, I build upon the setup from the previous post). My Vagrantfile looks like this:

# -*- mode: ruby -*-
# vi: set ft=ruby :
 
Vagrant::Config.run do |config|
  config.vm.box = "lucid32"
 
  (1..1).each do |index|
    config.vm.define "n#{index}".to_sym do |cfg|
      cfg.vm.host_name = "n#{index}"
      cfg.vm.network("192.168.100.1#{index}")
      cfg.vm.forward_port "ssh", 22, "220#{index}".to_i
      cfg.ssh.max_tries = 100
      cfg.vm.customize do |vm|
        vm.name = "Node #{index} VM"
        vm.memory_size = 512
      end
 
      cfg.vm.provision :chef_client do |chef|
        chef.chef_server_url = "http://192.168.100.1:4000"
        chef.validation_key_path = "/etc/chef/validation.pem"
        chef.node_name = "n#{index}"
        chef.add_role :robot
        chef.json.merge!({
          :robottest => {
            :runner => "p",
            :urlbase => "http://192.168.100.1/files",
            :archive => "test#{index}.tar.gz",
            :test => "test/test#{index}.txt"
          }
        })
      end
    end
  end
end

# -*- mode: ruby -*- # vi: set ft=ruby :Vagrant::Config.run do |config| config.vm.box = "lucid32"(1..1).each do |index| config.vm.define "n#{index}".to_sym do |cfg| cfg.vm.host_name = "n#{index}" cfg.vm.network("192.168.100.1#{index}") cfg.vm.forward_port "ssh", 22, "220#{index}".to_i cfg.ssh.max_tries = 100 cfg.vm.customize do |vm| vm.name = "Node #{index} VM" vm.memory_size = 512 endcfg.vm.provision :chef_client do |chef| chef.chef_server_url = "http://192.168.100.1:4000" chef.validation_key_path = "/etc/chef/validation.pem" chef.node_name = "n#{index}" chef.add_role :robot chef.json.merge!({ :robottest => { :runner => "p", :urlbase => "http://192.168.100.1/files", :archive => "test#{index}.tar.gz", :test => "test/test#{index}.txt" } }) end end end end

As you can see, I work only with one VirtualBox node – for simplicity. When you look at my loop, you can easily see that I can add whatever further nodes, as long as I use my own naming convention.

Now we need a Chef role like this:

{
  "name": "robot",
  "default_attributes": {
  },
  "json_class": "Chef::Role",
  "env_run_lists": {
  },
  "run_list": [
    "recipe[robot]",
    "recipe[robottest]"
  ],
  "description": "Baseline to run robot tests",
  "chef_type": "role",
  "override_attributes": {
    "robot": {
      "version": "2.7a1"
    },
    "java": {
      "install_flavor": "sun"
    }
  }
}

{ "name": "robot", "default_attributes": { }, "json_class": "Chef::Role", "env_run_lists": { }, "run_list": [ "recipe[robot]", "recipe[robottest]" ], "description": "Baseline to run robot tests", "chef_type": "role", "override_attributes": { "robot": { "version": "2.7a1" }, "java": { "install_flavor": "sun" } } }

The “robot” cookbook itself depends on apt, python etc. This role can be found in the Vagrantfile, so every VirtualBox node will have all the basic stuff provisioned as well as the Robot Framework installed. The “robottest” cookbook is actually there to run the tests. Look at the Vagrantfile how the relevant attributes for the node are getting set according to the documentation I’ve provided with my new cookbooks (README there).

I have a local Apache on the host which provides downloadable tar.gz files in a subdirectory /files (urlbase). My cookbook downloads the gzipped tar, unpacks it and runs a named test there, writing results to the same directory where the test archive has been unpacked in. Archive ensures that you can provision more than just one test but also libraries and dependencies (though I don’t use them in the first step and will add this functionality later). You now can download these files, look at them on the target machine or move them to a location where Apache could access and “show” them from. It’s up to you.

As you hopefully can see, if you follow the naming conventions I use in my Vagrantfile, you can easily provision different tests to different machines. This allows you to do automated distributed acceptance testing with Robot, on the Chef rails.

Please let me know if I should modify anything in the cookbooks or just feel free to contribute. Feedback is anytime very welcome.