Merge pull request #20 from fgrehm/acceptance-tests

Write some initial acceptance specs
This commit is contained in:
Fabio Rehm 2013-04-21 14:54:17 -07:00
commit 6f2068d5ec
14 changed files with 243 additions and 31 deletions

View file

@ -5,4 +5,4 @@ rvm:
matrix:
allow_failures:
- rvm: 2.0.0
script: "bundle exec rake"
script: "bundle exec rake ci"

View file

@ -1,6 +1,3 @@
# A sample Guardfile
# More info at https://github.com/guard/guard#readme
guard 'bundler' do
watch('Gemfile')
watch(/^.+\.gemspec/)
@ -15,20 +12,7 @@ guard 'rspec' do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/vagrant-lxc/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" }
watch('spec/unit_helper.rb') { "spec/unit" }
watch('spec/acceptance_helper.rb') { "spec/acceptance" }
watch('spec/spec_helper.rb') { "spec/" }
# Rails example
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
watch('config/routes.rb') { "spec/routing" }
watch('app/controllers/application_controller.rb') { "spec/controllers" }
# Capybara features specs
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
# Turnip features and steps
watch(%r{^spec/acceptance/(.+)\.feature$})
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
watch(%r{^spec/support/(.+)\.rb$}) { "spec/" }
end

View file

@ -104,7 +104,13 @@ If want to develop from your physical machine, just sing that same old song:
git clone git://github.com/fgrehm/vagrant-lxc.git
cd vagrant-lxc
bundle install
bundle exec rake # to run all specs
bundle exec rake # to run unit specs
```
To run acceptance specs, you'll have to ssh into one of the [development boxes](development/Vagrantfile) and run:
```
bundle exec rake spec:acceptance
```
To build the provided quantal64 box:

33
spec/Vagrantfile vendored Normal file
View file

@ -0,0 +1,33 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
def local_apt_cache(box_name)
cache_dir = File.join(File.expand_path(Vagrant::Environment::DEFAULT_HOME),
'cache',
'apt',
box_name)
partial_dir = File.join(cache_dir, 'partial')
FileUtils.mkdir_p(partial_dir) unless File.exists? partial_dir
cache_dir
end
Vagrant.require_plugin 'vagrant-lxc'
Vagrant.configure("2") do |config|
config.vm.box = "quantal64"
config.vm.hostname = 'lxc-test-box'
config.vm.box_url = 'http://dl.dropbox.com/u/13510779/lxc-quantal64-2013-04-10.box'
# Uncomment to test boxes built locally:
# config.vm.box_url = '../boxes/output/lxc-quantal64.box'
cache_dir = local_apt_cache(config.vm.box)
config.vm.synced_folder cache_dir, "/var/cache/apt/archives", id: "vagrant-apt-cache"
config.vm.provision :shell,
inline: 'mkdir -p /vagrant/tmp && echo -n "Provisioned" > /vagrant/tmp/provisioning'
config.vm.network :forwarded_port, guest: 80, host: 8080
config.vm.provision :shell,
inline: 'sudo apt-get install apache2 -y'
end

View file

@ -0,0 +1,74 @@
require 'acceptance_helper'
describe 'Sanity check' do
after(:all) { destroy_container }
context 'running `vagrant up` from scratch' do
before(:all) do
destroy_container
vagrant_up
end
it 'creates a container' do
containers = `sudo lxc-ls`.chomp.split(/\s+/).uniq
expect(containers).to include vagrant_container_name
end
it 'starts the newly created container' do
status = `sudo lxc-info -n #{vagrant_container_name}`
expect(status).to include 'RUNNING'
end
it "is able to be SSH'ed" do
expect(vagrant_ssh('hostname')).to eq 'lxc-test-box'
end
it 'mounts shared folders with the right permissions' do
vagrant_ssh 'mkdir -p /vagrant/tmp && echo -n "Shared" > /vagrant/tmp/shared'
shared_file_contents = File.read('/vagrant/spec/tmp/shared')
expect(shared_file_contents).to eq 'Shared'
end
it 'provisions the container based on Vagrantfile configs' do
provisioned_file_contents = File.read('/vagrant/spec/tmp/provisioning')
expect(provisioned_file_contents).to eq 'Provisioned'
end
it 'forwards configured ports' do
output = `curl -s localhost:8080`.strip.chomp
expect(output).to include 'It works!'
end
end
context '`vagrant halt` on a running container' do
before(:all) do
destroy_container
vagrant_up
vagrant_halt
end
it 'shuts down container' do
status = `sudo lxc-info -n #{vagrant_container_name}`
expect(status).to include 'STOPPED'
end
it 'clears forwarded ports' do
`curl -s localhost:8080 --connect-timeout 2`
expect($?.exitstatus).to_not eq 0
end
end
context '`vagrant destroy`' do
before(:all) do
destroy_container
vagrant_up
@container_name = vagrant_container_name
vagrant_destroy
end
it 'destroys the underlying container' do
containers = `sudo lxc-ls`.chomp.split(/\s+/).uniq
expect(containers).to_not include @container_name
end
end
end

View file

@ -0,0 +1,56 @@
module AcceptanceExampleGroup
def self.included(base)
base.metadata[:type] = :acceptance
end
ID_FILE = "/vagrant/spec/.vagrant/machines/default/lxc/id"
def vagrant_container_name
File.read(ID_FILE).strip.chomp if File.exists?(ID_FILE)
end
def destroy_container
if name = vagrant_container_name
`sudo lxc-shutdown -n #{name} 2>/dev/null`
`sudo lxc-wait -n #{name} --state STOPPED 2>/dev/null`
`sudo lxc-destroy -n #{name} 2>/dev/null`
end
`sudo killall -9 redir 2>/dev/null`
end
def with_vagrant_environment
opts = { cwd: 'spec', ui_class: TestUI }
env = Vagrant::Environment.new(opts)
yield env
env.unload
end
def vagrant_up
with_vagrant_environment do |env|
env.cli('up', '--provider', 'lxc')
end
end
def vagrant_halt
with_vagrant_environment do |env|
env.cli('halt')
end
end
def vagrant_destroy
with_vagrant_environment do |env|
env.cli('destroy', '-f')
end
end
def vagrant_ssh(cmd)
output = nil
with_vagrant_environment do |env|
result = env.cli('ssh', '-c', cmd)
if result.to_i != 0
raise "SSH command failed: '#{cmd}'\n#{env.ui.messages.inspect}"
end
output = env.ui.messages[:info].join("\n").chomp
end
output
end
end

View file

@ -0,0 +1,13 @@
# Monkey patch vagrant in order to reuse the UI test object that is set on
# our Vagrant::Environments
#
# TODO: Find out if this makes sense to be on vagrant core itself
require 'vagrant/machine'
Vagrant::Machine.class_eval do
alias :old_action :action
define_method :action do |name, extra_env = nil|
extra_env = { ui: @env.ui }.merge(extra_env || {})
old_action name, extra_env
end
end

View file

@ -0,0 +1,22 @@
class TestUI < Vagrant::UI::Interface
attr_reader :messages
METHODS = [:clear_line, :report_progress, :warn, :error, :info, :success]
def initialize(resource = nil)
super
@messages = METHODS.each_with_object({}) { |m, h| h[m] = [] }
end
def ask(*args)
super
# Automated tests should not depend on user input, obviously.
raise Errors::UIExpectsTTY
end
METHODS.each do |method|
define_method(method) do |message, *opts|
@messages[method].push message
end
end
end

21
spec/acceptance_helper.rb Normal file
View file

@ -0,0 +1,21 @@
require 'spec_helper'
unless ENV['USER'] == 'vagrant'
puts 'Acceptance specs are supposed to run from one of the vagrant-lxc dev machines'
exit 1
end
if defined? SimpleCov
SimpleCov.command_name 'acceptance'
end
require 'vagrant'
require 'vagrant-lxc'
Dir[File.dirname(__FILE__) + "/acceptance/support/**/*.rb"].each { |f| require f }
RSpec.configure do |config|
config.include AcceptanceExampleGroup, :type => :acceptance, :example_group => {
:file_path => /\bspec\/acceptance\//
}
end

View file

@ -2,14 +2,8 @@ if ENV['COVERAGE']
require 'simplecov'
require 'coveralls'
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
SimpleCov::Formatter::HTMLFormatter,
Coveralls::SimpleCov::Formatter
]
SimpleCov.start do
add_filter { |source_file| source_file.filename =~ /\/spec\/support/ }
end
SimpleCov.start { add_filter '/spec/' }
SimpleCov.merge_timeout 300
end
require 'bundler/setup'

0
spec/support/.gitkeep Normal file
View file

View file

@ -1,5 +1,11 @@
require 'spec_helper'
Dir[File.dirname(__FILE__) + "/unit/support/**/*.rb"].each { |f| require f }
if defined? SimpleCov
SimpleCov.command_name 'unit'
end
RSpec.configure do |config|
config.include RSpec::Fire

View file

@ -1,12 +1,15 @@
begin
require 'rspec/core/rake_task'
require 'coveralls/rake/task'
# TODO: add 'spec:acceptance' and 'spec:integration' then they are in place
desc 'Run all specs'
task :spec => ['spec:unit']
task :spec => ['spec:unit', 'spec:acceptance']
desc 'Default task which runs all specs with code coverage enabled'
task :default => ['spec:set_coverage', 'spec']
task :default => ['spec:set_coverage', 'spec:unit']
Coveralls::RakeTask.new
task :ci => ['spec:set_coverage', 'spec:unit', 'coveralls:push']
rescue LoadError; end
namespace :spec do