RSpec is coming in for acceptance tests. More details follow...
RSpec was chosen to be used for acceptance tests for many reasons: * The tests are actually much cleaner now. It is clearer to see what is being tested, and what is being used for setup. * Matcher transition will be coming soon. This will really clean up a lot of the "assert" boilerplate all over. There was a lot of repetition in this area. * Shared examples will help greatly for testing common error cases for many commands. * The test runner for RSpec is simply much better. Being able to specify the exact test to run by line, for example, is a great help.
This commit is contained in:
parent
699c67c1aa
commit
87bc6ec63f
4
Rakefile
4
Rakefile
|
@ -1,6 +1,7 @@
|
|||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
require 'rake/testtask'
|
||||
require 'rspec/core/rake_task'
|
||||
Bundler::GemHelper.install_tasks
|
||||
|
||||
task :default => "test:unit"
|
||||
|
@ -12,9 +13,8 @@ namespace :test do
|
|||
t.pattern = "test/unit/**/*_test.rb"
|
||||
end
|
||||
|
||||
Rake::TestTask.new do |t|
|
||||
RSpec::Core::RakeTask.new do |t|
|
||||
t.name = "acceptance"
|
||||
t.libs << "test/acceptance"
|
||||
t.pattern = "test/acceptance/**/*_test.rb"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
require "rubygems"
|
||||
require "contest"
|
||||
require "rspec/autorun"
|
||||
|
||||
require "log4r"
|
||||
|
||||
require File.expand_path("../helpers/config", __FILE__)
|
||||
require File.expand_path("../helpers/isolated_environment", __FILE__)
|
||||
require File.expand_path("../helpers/output", __FILE__)
|
||||
require File.expand_path("../helpers/virtualbox", __FILE__)
|
||||
require File.expand_path("../support/base_context", __FILE__)
|
||||
require File.expand_path("../support/config", __FILE__)
|
||||
require File.expand_path("../support/virtualbox", __FILE__)
|
||||
|
||||
# If VirtualBox is currently running, fail.
|
||||
if Acceptance::VirtualBox.find_vboxsvc
|
||||
|
@ -32,55 +32,7 @@ end
|
|||
|
||||
$acceptance_options = Acceptance::Config.new(ENV["ACCEPTANCE_CONFIG"])
|
||||
|
||||
class AcceptanceTest < Test::Unit::TestCase
|
||||
# This method is a shortcut to give access to the global configuration
|
||||
# setup by the acceptance tests.
|
||||
def config
|
||||
$acceptance_options
|
||||
end
|
||||
|
||||
# Executes the given command in the isolated environment. This
|
||||
# is just a shortcut to IsolatedEnvironment#execute.
|
||||
#
|
||||
# @return [Object]
|
||||
def execute(*args, &block)
|
||||
@environment.execute(*args, &block)
|
||||
end
|
||||
|
||||
# This is a shortcut method to instantiate an Output matcher.
|
||||
#
|
||||
# @return [Acceptance::Output]
|
||||
def output(text)
|
||||
Acceptance::Output.new(text)
|
||||
end
|
||||
|
||||
# This method is an assertion helper for asserting that a process
|
||||
# succeeds. It is a wrapper around `execute` that asserts that the
|
||||
# exit status was successful.
|
||||
def assert_execute(*args, &block)
|
||||
result = execute(*args, &block)
|
||||
assert(result.success?, "expected '#{args.join(" ")}' to succeed")
|
||||
result
|
||||
end
|
||||
|
||||
setup do
|
||||
# Wait for VBoxSVC to disappear
|
||||
Acceptance::VirtualBox.wait_for_vboxsvc
|
||||
|
||||
# Setup the environment so that we have an isolated area
|
||||
# to run Vagrant. We do some configuration here as well in order
|
||||
# to replace "vagrant" with the proper path to Vagrant as well
|
||||
# as tell the isolated environment about custom environmental
|
||||
# variables to pass in.
|
||||
apps = { "vagrant" => config.vagrant_path }
|
||||
@environment = Acceptance::IsolatedEnvironment.new(apps, config.env)
|
||||
|
||||
# Setup a logger for this test, since tests often log to assist
|
||||
# with the debugging process in case of failure.
|
||||
@logger = Log4r::Logger.new("acceptance::#{self.class.name.downcase.gsub("test", "")}")
|
||||
end
|
||||
|
||||
teardown do
|
||||
@environment.close if @environment
|
||||
end
|
||||
# Configure RSpec
|
||||
RSpec.configure do |c|
|
||||
c.expect_with :stdlib
|
||||
end
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
require File.expand_path("../base", __FILE__)
|
||||
|
||||
class BoxTest < AcceptanceTest
|
||||
describe "vagrant box" do
|
||||
include_context "acceptance"
|
||||
|
||||
def require_box(name)
|
||||
if !config.boxes.has_key?(name) || !File.file?(config.boxes[name])
|
||||
raise ArgumentError, "The configuration should specify a '#{name}' box."
|
||||
end
|
||||
end
|
||||
|
||||
should "have no boxes by default" do
|
||||
it "has no boxes by default" do
|
||||
result = execute("vagrant", "box", "list")
|
||||
assert(output(result.stdout).no_boxes,
|
||||
"output should say there are no installed boxes")
|
||||
end
|
||||
|
||||
should "add a box from a file" do
|
||||
it "can add a box from a file" do
|
||||
require_box("default")
|
||||
|
||||
# Add the box, which we expect to succeed
|
||||
|
@ -26,15 +28,15 @@ class BoxTest < AcceptanceTest
|
|||
"foo box should exist after it is added")
|
||||
end
|
||||
|
||||
should "give an error if the file doesn't exist" do
|
||||
it "gives an error if the file doesn't exist" do
|
||||
results = execute("vagrant", "box", "add", "foo", "/tmp/nope/nope/nope/nonono.box")
|
||||
assert(!results.success?, "Box add should fail.")
|
||||
assert(output(results.stdout).box_path_doesnt_exist,
|
||||
"Should show an error message about the file not existing.")
|
||||
end
|
||||
|
||||
should "give an error if the file is not a valid box" do
|
||||
invalid = @environment.workdir.join("nope.txt")
|
||||
it "gives an error if the file is not a valid box" do
|
||||
invalid = environment.workdir.join("nope.txt")
|
||||
invalid.open("w+") do |f|
|
||||
f.write("INVALID!")
|
||||
end
|
||||
|
@ -45,12 +47,11 @@ class BoxTest < AcceptanceTest
|
|||
"should say the box is invalid")
|
||||
end
|
||||
|
||||
should "add a box from an HTTP server" do
|
||||
# TODO: Spin up an HTTP server to serve a file, add and test.
|
||||
skip("Need to setup HTTP server functionality")
|
||||
it "can add a box from an HTTP server" do
|
||||
pending("Need to setup HTTP server functionality")
|
||||
end
|
||||
|
||||
should "remove a box" do
|
||||
it "can remove a box" do
|
||||
require_box("default")
|
||||
|
||||
# Add the box, remove the box, then verify that the box no longer
|
||||
|
@ -63,11 +64,11 @@ class BoxTest < AcceptanceTest
|
|||
"No boxes should be installed")
|
||||
end
|
||||
|
||||
should "repackage a box" do
|
||||
it "can repackage a box" do
|
||||
require_box("default")
|
||||
|
||||
original_size = File.size(config.boxes["default"])
|
||||
@logger.debug("Original package size: #{original_size}")
|
||||
logger.debug("Original package size: #{original_size}")
|
||||
|
||||
# Add the box, repackage it, and verify that a package.box is
|
||||
# dumped of relatively similar size.
|
||||
|
@ -75,12 +76,12 @@ class BoxTest < AcceptanceTest
|
|||
execute("vagrant", "box", "repackage", "foo")
|
||||
|
||||
# By default, repackage should dump into package.box into the CWD
|
||||
repackaged_file = @environment.workdir.join("package.box")
|
||||
repackaged_file = environment.workdir.join("package.box")
|
||||
assert(repackaged_file.file?, "package.box should exist in cwd of environment")
|
||||
|
||||
# Compare the sizes
|
||||
repackaged_size = repackaged_file.size
|
||||
@logger.debug("Repackaged size: #{repackaged_size}")
|
||||
logger.debug("Repackaged size: #{repackaged_size}")
|
||||
size_diff = (repackaged_size - original_size).abs
|
||||
assert(size_diff < 1000, "Sizes should be very similar")
|
||||
end
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
require File.expand_path("../base", __FILE__)
|
||||
|
||||
class InitTest < AcceptanceTest
|
||||
should "create a Vagrantfile in the working directory" do
|
||||
vagrantfile = @environment.workdir.join("Vagrantfile")
|
||||
describe "vagrant init" do
|
||||
include_context "acceptance"
|
||||
|
||||
it "creates a Vagrantfile in the working directory" do
|
||||
vagrantfile = environment.workdir.join("Vagrantfile")
|
||||
assert(!vagrantfile.exist?, "Vagrantfile shouldn't exist")
|
||||
|
||||
result = execute("vagrant", "init")
|
||||
|
@ -10,8 +12,8 @@ class InitTest < AcceptanceTest
|
|||
assert(vagrantfile.exist?, "Vagrantfile should exist")
|
||||
end
|
||||
|
||||
should "create a Vagrantfile with the box set to the given argument" do
|
||||
vagrantfile = @environment.workdir.join("Vagrantfile")
|
||||
it "creates a Vagrantfile with the box set to the given argument" do
|
||||
vagrantfile = environment.workdir.join("Vagrantfile")
|
||||
|
||||
result = execute("vagrant", "init", "foo")
|
||||
assert(result.success?, "init should succeed")
|
||||
|
@ -19,8 +21,8 @@ class InitTest < AcceptanceTest
|
|||
"config.vm.box should be set to 'foo'")
|
||||
end
|
||||
|
||||
should "create a Vagrantfile with the box URL set to the given argument" do
|
||||
vagrantfile = @environment.workdir.join("Vagrantfile")
|
||||
it "creates a Vagrantfile with the box URL set to the given argument" do
|
||||
vagrantfile = environment.workdir.join("Vagrantfile")
|
||||
|
||||
result = execute("vagrant", "init", "foo", "bar")
|
||||
assert(result.success?, "init should succeed")
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
require File.expand_path("../base", __FILE__)
|
||||
|
||||
class SSHTest < AcceptanceTest
|
||||
should "fail if no Vagrantfile is found" do
|
||||
describe "vagrant ssh" do
|
||||
include_context "acceptance"
|
||||
|
||||
it "fails if no Vagrantfile is found" do
|
||||
result = execute("vagrant", "ssh")
|
||||
assert(!result.success?, "vagrant ssh should fail")
|
||||
assert(output(result.stdout).no_vagrantfile,
|
||||
"Vagrant should error since there is no Vagrantfile")
|
||||
end
|
||||
|
||||
should "fail if the virtual machine is not created" do
|
||||
it "fails if the virtual machine is not created" do
|
||||
assert_execute("vagrant", "init")
|
||||
|
||||
result = execute("vagrant", "ssh")
|
||||
|
@ -17,7 +19,7 @@ class SSHTest < AcceptanceTest
|
|||
"Vagrant should error that the VM must be created.")
|
||||
end
|
||||
|
||||
should "be able to SSH into a running virtual machine" do
|
||||
it "is able to SSH into a running virtual machine" do
|
||||
assert_execute("vagrant", "box", "add", "base", config.boxes["default"])
|
||||
assert_execute("vagrant", "init")
|
||||
assert_execute("vagrant", "up")
|
||||
|
@ -35,7 +37,7 @@ class SSHTest < AcceptanceTest
|
|||
"Vagrant should bring up a virtual machine and be able to SSH in.")
|
||||
end
|
||||
|
||||
should "be able to execute a single command via the command line" do
|
||||
it "is able to execute a single command via the command line" do
|
||||
assert_execute("vagrant", "box", "add", "base", config.boxes["default"])
|
||||
assert_execute("vagrant", "init")
|
||||
assert_execute("vagrant", "up")
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
require File.expand_path("../isolated_environment", __FILE__)
|
||||
require File.expand_path("../output", __FILE__)
|
||||
require File.expand_path("../virtualbox", __FILE__)
|
||||
|
||||
shared_context "acceptance" do
|
||||
# Setup variables for the loggers of this test. These can be used to
|
||||
# create more verbose logs for tests which can be useful in the case
|
||||
# that a test fails.
|
||||
let(:logger_name) { "logger" }
|
||||
let(:logger) { Log4r::Logger.new("acceptance::#{logger_name}") }
|
||||
|
||||
# This is the global configuration given by the acceptance test
|
||||
# configurations.
|
||||
let(:config) { $acceptance_options }
|
||||
|
||||
# Setup the environment so that we have an isolated area
|
||||
# to run Vagrant. We do some configuration here as well in order
|
||||
# to replace "vagrant" with the proper path to Vagrant as well
|
||||
# as tell the isolated environment about custom environmental
|
||||
# variables to pass in.
|
||||
let!(:environment) do
|
||||
apps = { "vagrant" => config.vagrant_path }
|
||||
Acceptance::IsolatedEnvironment.new(apps, config.env)
|
||||
end
|
||||
|
||||
before(:each) do
|
||||
# Wait for VBoxSVC to disappear, since each test requires its
|
||||
# own isolated VirtualBox process.
|
||||
Acceptance::VirtualBox.wait_for_vboxsvc
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
environment.close
|
||||
end
|
||||
|
||||
# Executes the given command in the context of the isolated environment.
|
||||
#
|
||||
# @return [Object]
|
||||
def execute(*args, &block)
|
||||
environment.execute(*args, &block)
|
||||
end
|
||||
|
||||
# Returns an output matcher for the given text.
|
||||
#
|
||||
# @return [Acceptance::Output]
|
||||
def output(text)
|
||||
Acceptance::Output.new(text)
|
||||
end
|
||||
|
||||
# This method is an assertion helper for asserting that a process
|
||||
# succeeds. It is a wrapper around `execute` that asserts that the
|
||||
# exit status was successful.
|
||||
def assert_execute(*args, &block)
|
||||
result = execute(*args, &block)
|
||||
assert(result.success?, "expected '#{args.join(" ")}' to succeed")
|
||||
result
|
||||
end
|
||||
end
|
|
@ -1,14 +1,14 @@
|
|||
require File.expand_path("../base", __FILE__)
|
||||
|
||||
class UpBasicTest < AcceptanceTest
|
||||
should "fail if not Vagrantfile is found" do
|
||||
describe "vagrant up", "basics" do
|
||||
it "fails if not Vagrantfile is found" do
|
||||
result = execute("vagrant", "up")
|
||||
assert(!result.success?, "vagrant up should fail")
|
||||
assert(output(result.stdout).no_vagrantfile,
|
||||
"Vagrant should error since there is no Vagrantfile")
|
||||
end
|
||||
|
||||
should "bring up a running virtual machine" do
|
||||
it "brings up a running virtual machine" do
|
||||
assert_execute("vagrant", "box", "add", "base", config.boxes["default"])
|
||||
assert_execute("vagrant", "init")
|
||||
assert_execute("vagrant", "up")
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
require File.expand_path("../base", __FILE__)
|
||||
|
||||
# NOTE: Many tests in this test suite require the `expect`
|
||||
# tool to be installed, because `expect` will launch with a
|
||||
# PTY.
|
||||
class VagrantTestColorOutput < AcceptanceTest
|
||||
def has_expect?
|
||||
describe "vagrant and color output" do
|
||||
include_context "acceptance"
|
||||
|
||||
# This is a check to see if the `expect` program is installed on this
|
||||
# computer. Some tests require this and if this doesn't exist then the
|
||||
# test itself will be skipped.
|
||||
def self.has_expect?
|
||||
`which expect`
|
||||
$?.success?
|
||||
end
|
||||
|
@ -16,12 +18,10 @@ class VagrantTestColorOutput < AcceptanceTest
|
|||
text.index("\e[31m")
|
||||
end
|
||||
|
||||
should "output color if there is a TTY" do
|
||||
skip("Test requires `expect`") if !has_expect?
|
||||
|
||||
@environment.workdir.join("color.exp").open("w+") do |f|
|
||||
it "outputs color if there is a TTY", :if => has_expect? do
|
||||
environment.workdir.join("color.exp").open("w+") do |f|
|
||||
f.puts(<<-SCRIPT)
|
||||
spawn #{@environment.replace_command("vagrant")} status
|
||||
spawn #{environment.replace_command("vagrant")} status
|
||||
expect default {}
|
||||
SCRIPT
|
||||
end
|
||||
|
@ -30,12 +30,10 @@ SCRIPT
|
|||
assert(has_color?(result.stdout), "output should contain color")
|
||||
end
|
||||
|
||||
should "not output color if there is a TTY but --no-color is present" do
|
||||
skip("Test requires `expect`") if !has_expect?
|
||||
|
||||
@environment.workdir.join("color.exp").open("w+") do |f|
|
||||
it "doesn't output color if there is a TTY but --no-color is present", :if => has_expect? do
|
||||
environment.workdir.join("color.exp").open("w+") do |f|
|
||||
f.puts(<<-SCRIPT)
|
||||
spawn #{@environment.replace_command("vagrant")} status --no-color
|
||||
spawn #{environment.replace_command("vagrant")} status --no-color
|
||||
expect default {}
|
||||
SCRIPT
|
||||
end
|
||||
|
@ -44,7 +42,7 @@ SCRIPT
|
|||
assert(!has_color?(result.stdout), "output should not contain color")
|
||||
end
|
||||
|
||||
should "not output color in the absense of a TTY" do
|
||||
it "doesn't output color in the absense of a TTY" do
|
||||
# This should always output an error, which on a TTY would
|
||||
# output color. We check that this doesn't output color.
|
||||
# If `vagrant status` itself is broken, another acceptance test
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
require File.expand_path("../base", __FILE__)
|
||||
|
||||
class VersionTest < AcceptanceTest
|
||||
should "print the version to stdout" do
|
||||
describe "vagrant version" do
|
||||
include_context "acceptance"
|
||||
|
||||
it "prints the version to stdout" do
|
||||
result = execute("vagrant", "version")
|
||||
assert(output(result.stdout).is_version?(config.vagrant_version),
|
||||
"output should be version")
|
||||
end
|
||||
|
||||
should "print the version with '-v'" do
|
||||
it "prints the version when called with '-v'" do
|
||||
result = execute("vagrant", "-v")
|
||||
assert(output(result.stdout).is_version?(config.vagrant_version),
|
||||
"output should be version")
|
||||
end
|
||||
|
||||
should "print the version with '--version'" do
|
||||
it "prints the version when called with '--version'" do
|
||||
result = execute("vagrant", "--version")
|
||||
assert(output(result.stdout).is_version?(config.vagrant_version),
|
||||
"output should be version")
|
||||
|
|
|
@ -30,6 +30,8 @@ Gem::Specification.new do |s|
|
|||
s.add_development_dependency "mocha"
|
||||
s.add_development_dependency "posix-spawn", "~> 0.3.6"
|
||||
s.add_development_dependency "sys-proctable", "~> 0.9.1"
|
||||
s.add_development_dependency "rspec-core", "~> 2.7.1"
|
||||
s.add_development_dependency "rspec-mocks", "~> 2.7.0"
|
||||
|
||||
s.files = `git ls-files`.split("\n")
|
||||
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
||||
|
|
Loading…
Reference in New Issue