diff --git a/Library/Homebrew/test/exceptions_spec.rb b/Library/Homebrew/test/exceptions_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..33547ea32efb1b8199803586b34d017abd462e08
--- /dev/null
+++ b/Library/Homebrew/test/exceptions_spec.rb
@@ -0,0 +1,188 @@
+require "exceptions"
+
+describe MultipleVersionsInstalledError do
+  subject { described_class.new("foo") }
+  its(:to_s) { is_expected.to eq("foo has multiple installed versions") }
+end
+
+describe NoSuchKegError do
+  subject { described_class.new("foo") }
+  its(:to_s) { is_expected.to eq("No such keg: #{HOMEBREW_CELLAR}/foo") }
+end
+
+describe FormulaValidationError do
+  subject { described_class.new("foo", "sha257", "magic") }
+  its(:to_s) {
+    is_expected.to eq(%q(invalid attribute for formula 'foo': sha257 ("magic")))
+  }
+end
+
+describe FormulaUnavailableError do
+  subject { described_class.new("foo") }
+
+  describe "#dependent_s" do
+    it "returns nil if there is no dependent" do
+      expect(subject.dependent_s).to be nil
+    end
+
+    it "returns nil if it depended on by itself" do
+      subject.dependent = "foo"
+      expect(subject.dependent_s).to be nil
+    end
+
+    it "returns a string if there is a dependent" do
+      subject.dependent = "foobar"
+      expect(subject.dependent_s).to eq("(dependency of foobar)")
+    end
+  end
+
+  context "without a dependent" do
+    its(:to_s) { is_expected.to eq('No available formula with the name "foo" ') }
+  end
+
+  context "with a dependent" do
+    before(:each) do
+      subject.dependent = "foobar"
+    end
+
+    its(:to_s) {
+      is_expected.to eq('No available formula with the name "foo" (dependency of foobar)')
+    }
+  end
+end
+
+describe TapFormulaUnavailableError do
+  subject { described_class.new(tap, "foo") }
+  let(:tap) { double(Tap, user: "u", repo: "r", to_s: "u/r", installed?: false) }
+  its(:to_s) { is_expected.to match(%r{Please tap it and then try again: brew tap u/r}) }
+end
+
+describe FormulaClassUnavailableError do
+  subject { described_class.new("foo", "foo.rb", "Foo", list) }
+  let(:mod) do
+    Module.new do
+      class Bar < Requirement; end
+      class Baz < Formula; end
+    end
+  end
+
+  context "no classes" do
+    let(:list) { [] }
+    its(:to_s) {
+      is_expected.to match(/Expected to find class Foo, but found no classes\./)
+    }
+  end
+
+  context "class not derived from Formula" do
+    let(:list) { [mod.const_get(:Bar)] }
+    its(:to_s) {
+      is_expected.to match(/Expected to find class Foo, but only found: Bar \(not derived from Formula!\)\./)
+    }
+  end
+
+  context "class derived from Formula" do
+    let(:list) { [mod.const_get(:Baz)] }
+    its(:to_s) { is_expected.to match(/Expected to find class Foo, but only found: Baz\./) }
+  end
+end
+
+describe FormulaUnreadableError do
+  subject { described_class.new("foo", formula_error) }
+  let(:formula_error) { LoadError.new("bar") }
+  its(:to_s) { is_expected.to eq("foo: bar") }
+end
+
+describe TapUnavailableError do
+  subject { described_class.new("foo") }
+  its(:to_s) { is_expected.to eq("No available tap foo.\n") }
+end
+
+describe TapAlreadyTappedError do
+  subject { described_class.new("foo") }
+  its(:to_s) { is_expected.to eq("Tap foo already tapped.\n") }
+end
+
+describe TapPinStatusError do
+  context "pinned" do
+    subject { described_class.new("foo", true) }
+    its(:to_s) { is_expected.to eq("foo is already pinned.") }
+  end
+
+  context "unpinned" do
+    subject { described_class.new("foo", false) }
+    its(:to_s) { is_expected.to eq("foo is already unpinned.") }
+  end
+end
+
+describe BuildError do
+  subject { described_class.new(formula, "badprg", %w[arg1 arg2], {}) }
+  let(:formula) { double(Formula, name: "foo") }
+  its(:to_s) { is_expected.to eq("Failed executing: badprg arg1 arg2") }
+end
+
+describe OperationInProgressError do
+  subject { described_class.new("foo") }
+  its(:to_s) { is_expected.to match(/Operation already in progress for foo/) }
+end
+
+describe FormulaInstallationAlreadyAttemptedError do
+  subject { described_class.new(formula) }
+  let(:formula) { double(Formula, full_name: "foo/bar") }
+  its(:to_s) { is_expected.to eq("Formula installation already attempted: foo/bar") }
+end
+
+describe FormulaConflictError do
+  subject { described_class.new(formula, [conflict]) }
+  let(:formula) { double(Formula, full_name: "foo/qux") }
+  let(:conflict) { double(name: "bar", reason: "I decided to") }
+  its(:to_s) { is_expected.to match(/Please `brew unlink bar` before continuing\./) }
+end
+
+describe CompilerSelectionError do
+  subject { described_class.new(formula) }
+  let(:formula) { double(Formula, full_name: "foo") }
+  its(:to_s) { is_expected.to match(/foo cannot be built with any available compilers\./) }
+end
+
+describe CurlDownloadStrategyError do
+  context "file does not exist" do
+    subject { described_class.new("file:///tmp/foo") }
+    its(:to_s) { is_expected.to eq("File does not exist: /tmp/foo") }
+  end
+
+  context "download failed" do
+    subject { described_class.new("http://brew.sh") }
+    its(:to_s) { is_expected.to eq("Download failed: http://brew.sh") }
+  end
+end
+
+describe ErrorDuringExecution do
+  subject { described_class.new("badprg", %w[arg1 arg2]) }
+  its(:to_s) { is_expected.to eq("Failure while executing: badprg arg1 arg2") }
+end
+
+describe ChecksumMismatchError do
+  subject { described_class.new("/file.tar.gz", hash1, hash2) }
+  let(:hash1) { double(hash_type: "sha256", to_s: "deadbeef") }
+  let(:hash2) { double(hash_type: "sha256", to_s: "deadcafe") }
+  its(:to_s) { is_expected.to match(/SHA256 mismatch/) }
+end
+
+describe ResourceMissingError do
+  subject { described_class.new(formula, resource) }
+  let(:formula) { double(Formula, full_name: "bar") }
+  let(:resource) { double(inspect: "<resource foo>") }
+  its(:to_s) { is_expected.to eq("bar does not define resource <resource foo>") }
+end
+
+describe DuplicateResourceError do
+  subject { described_class.new(resource) }
+  let(:resource) { double(inspect: "<resource foo>") }
+  its(:to_s) { is_expected.to eq("Resource <resource foo> is defined more than once") }
+end
+
+describe BottleVersionMismatchError do
+  subject { described_class.new("/foo.bottle.tar.gz", "1.0", formula, "1.1") }
+  let(:formula) { double(Formula, full_name: "foo") }
+  its(:to_s) { is_expected.to match(/Bottle version mismatch/) }
+end
diff --git a/Library/Homebrew/test/exceptions_test.rb b/Library/Homebrew/test/exceptions_test.rb
deleted file mode 100644
index e9fedef0472193f1c23accb330a4c4dfb95cc2dc..0000000000000000000000000000000000000000
--- a/Library/Homebrew/test/exceptions_test.rb
+++ /dev/null
@@ -1,147 +0,0 @@
-require "testing_env"
-require "exceptions"
-
-class ExceptionsTest < Homebrew::TestCase
-  def test_multiple_versions_installed_error
-    assert_equal "foo has multiple installed versions",
-      MultipleVersionsInstalledError.new("foo").to_s
-  end
-
-  def test_no_such_keg_error
-    assert_equal "No such keg: #{HOMEBREW_CELLAR}/foo",
-      NoSuchKegError.new("foo").to_s
-  end
-
-  def test_formula_validation_error
-    assert_equal %q(invalid attribute for formula 'foo': sha257 ("magic")),
-      FormulaValidationError.new("foo", "sha257", "magic").to_s
-  end
-
-  def test_formula_unavailable_error
-    e = FormulaUnavailableError.new "foo"
-    assert_nil e.dependent_s
-
-    e.dependent = "foo"
-    assert_nil e.dependent_s
-
-    e.dependent = "foobar"
-    assert_equal "(dependency of foobar)", e.dependent_s
-
-    assert_equal "No available formula with the name \"foo\" (dependency of foobar)",
-      e.to_s
-  end
-
-  def test_tap_formula_unavailable_error
-    t = stub(user: "u", repo: "r", to_s: "u/r", installed?: false)
-    assert_match "Please tap it and then try again: brew tap u/r",
-      TapFormulaUnavailableError.new(t, "foo").to_s
-  end
-
-  def test_formula_class_unavailable_error
-    mod = Module.new
-    mod.module_eval <<-EOS.undent
-      class Bar < Requirement; end
-      class Baz < Formula; end
-    EOS
-
-    assert_match "Expected to find class Foo, but found no classes.",
-      FormulaClassUnavailableError.new("foo", "foo.rb", "Foo", []).to_s
-
-    list = [mod.const_get(:Bar)]
-    assert_match "Expected to find class Foo, but only found: Bar (not derived from Formula!).",
-      FormulaClassUnavailableError.new("foo", "foo.rb", "Foo", list).to_s
-
-    list = [mod.const_get(:Baz)]
-    assert_match "Expected to find class Foo, but only found: Baz.",
-      FormulaClassUnavailableError.new("foo", "foo.rb", "Foo", list).to_s
-  end
-
-  def test_formula_unreadable_error
-    formula_error = LoadError.new("bar")
-    assert_equal "foo: bar", FormulaUnreadableError.new("foo", formula_error).to_s
-  end
-
-  def test_tap_unavailable_error
-    assert_equal "No available tap foo.\n", TapUnavailableError.new("foo").to_s
-  end
-
-  def test_tap_already_tapped_error
-    assert_equal "Tap foo already tapped.\n",
-      TapAlreadyTappedError.new("foo").to_s
-  end
-
-  def test_pin_status_error
-    assert_equal "foo is already pinned.",
-      TapPinStatusError.new("foo", true).to_s
-    assert_equal "foo is already unpinned.",
-      TapPinStatusError.new("foo", false).to_s
-  end
-
-  def test_build_error
-    f = stub(name: "foo")
-    assert_equal "Failed executing: badprg arg1 arg2",
-      BuildError.new(f, "badprg", %w[arg1 arg2], {}).to_s
-  end
-
-  def test_operation_in_progress_error
-    assert_match "Operation already in progress for bar",
-      OperationInProgressError.new("bar").to_s
-  end
-
-  def test_formula_installation_already_attempted_error
-    f = stub(full_name: "foo/bar")
-    assert_equal "Formula installation already attempted: foo/bar",
-      FormulaInstallationAlreadyAttemptedError.new(f).to_s
-  end
-
-  def test_formula_conflict_error
-    f = stub(full_name: "foo/qux")
-    c = stub(name: "bar", reason: "I decided to")
-    assert_match "Please `brew unlink bar` before continuing.",
-      FormulaConflictError.new(f, [c]).to_s
-  end
-
-  def test_compiler_selection_error
-    f = stub(full_name: "foo")
-    assert_match "foo cannot be built with any available compilers.",
-      CompilerSelectionError.new(f).to_s
-  end
-
-  def test_curl_download_strategy_error
-    assert_equal "File does not exist: /tmp/foo",
-      CurlDownloadStrategyError.new("file:///tmp/foo").to_s
-    assert_equal "Download failed: http://brew.sh",
-      CurlDownloadStrategyError.new("http://brew.sh").to_s
-  end
-
-  def test_error_during_execution
-    assert_equal "Failure while executing: badprg arg1 arg2",
-      ErrorDuringExecution.new("badprg", %w[arg1 arg2]).to_s
-  end
-
-  def test_checksum_mismatch_error
-    h1 = stub(hash_type: "sha256", to_s: "deadbeef")
-    h2 = stub(hash_type: "sha256", to_s: "deadcafe")
-    assert_match "SHA256 mismatch",
-      ChecksumMismatchError.new("/file.tar.gz", h1, h2).to_s
-  end
-
-  def test_resource_missing_error
-    f = stub(full_name: "bar")
-    r = stub(inspect: "<resource foo>")
-    assert_match "bar does not define resource <resource foo>",
-      ResourceMissingError.new(f, r).to_s
-  end
-
-  def test_duplicate_resource_error
-    r = stub(inspect: "<resource foo>")
-    assert_equal "Resource <resource foo> is defined more than once",
-      DuplicateResourceError.new(r).to_s
-  end
-
-  def test_bottle_version_mismatch_error
-    f = stub(full_name: "foo")
-    assert_match "Bottle version mismatch",
-      BottleVersionMismatchError.new("/foo.bottle.tar.gz", "1.0", f, "1.1").to_s
-  end
-end