diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,13 @@
 pwstore-cli
 ===========
 
+Version 0.3
+-----------
+
+  * Bumped dependency on cmdargs to allow versions >= 0.7 and < 1.0.
+  * Switched tests from hspec to test-framework.
+  * Define a cabal test suite.
+
 Version 0.2
 -----------
 
diff --git a/pwstore-cli.cabal b/pwstore-cli.cabal
--- a/pwstore-cli.cabal
+++ b/pwstore-cli.cabal
@@ -1,5 +1,5 @@
 name:                pwstore-cli
-version:             0.2
+version:             0.3
 synopsis:            Command line interface for the pwstore library
 description:
   This program provides a command line interface for Peter Scott's
@@ -14,7 +14,7 @@
 stability:           Experimental
 category:            Cryptography, Console
 build-type:          Simple
-cabal-version:       >=1.4
+cabal-version:       >=1.8
 extra-source-files:  README NEWS tests/test.hs
 
 flag fast
@@ -26,9 +26,21 @@
   other-modules:     Paths_pwstore_cli
   ghc-options:       -Wall
   extensions:        DeriveDataTypeable, RecordWildCards
-  build-depends:     base < 5, bytestring, text, cmdargs >= 0.7 && < 0.8
+  build-depends:     base < 5, bytestring, text, cmdargs >= 0.7 && < 1.0
 
   if flag(fast)
      build-depends:   pwstore-fast >= 2.2 && < 3.0
   else
      build-depends:   pwstore-purehaskell >= 2.0 && < 3.0
+
+test-suite test-pwstore-cli
+  type:              exitcode-stdio-1.0
+  hs-source-dirs:    tests
+  main-is:           test.hs
+  build-depends:     base < 5
+                   , bytestring
+                   , process
+                   , test-framework == 0.4.*
+                   , test-framework-hunit == 0.2.*
+                   , HUnit
+                   , pwstore-fast >= 2.2 && < 3.0
diff --git a/tests/test.hs b/tests/test.hs
--- a/tests/test.hs
+++ b/tests/test.hs
@@ -6,52 +6,52 @@
 import Data.List (isPrefixOf)
 import qualified Crypto.PasswordStore as P
 import System.Process (readProcess)
-import Test.HUnit
-import Test.Hspec
-import Test.Hspec.HUnit
+import Test.Framework (Test, defaultMain, buildTest)
+import Test.Framework.Providers.HUnit
+import Test.HUnit hiding (Test)
 
 -- | Runs the pwstore command with the given arguments and standard
 -- input.
 runPwstore :: [String] -> String -> IO String
 runPwstore = readProcess "dist/build/pwstore/pwstore"
 
--- | A valid hunter2 hash.
+-- | A known valid hunter2 hash.
 hunter2hash :: String
 hunter2hash = "sha256|12|YmBsCrO7FQIcrbMt23jnOA==|E8FZPaJnwa/dakuXOnz1A9OL2qj3nlzwDE02olsXMy0="
 
-specs :: IO Specs
-specs = describe "pwstore-cli"
-  [ it "verifies hash with good password" $
+tests :: [Test]
+tests =
+  [ testCase "verity hash with good password" $
     do actual <- runPwstore ["verify", hunter2hash] "hunter2"
        "good password\n" @=? actual
 
-  , it "does not verify hash with bad password" $
+  , testCase "verify hash with bad password" $
     do actual <- runPwstore ["verify", hunter2hash] "badpass"
        "bad password\n" @=? actual
 
-  , it "generates hash with given salt" $
+  , testCase "generate hash with given salt" $
     do actual <- runPwstore ["generate", "--salt=72cd18b5ebfe6e96"] "hunter2"
        "sha256|12|NzJjZDE4YjVlYmZlNmU5Ng==|M17VU2ciK8VaKyyDfVeGHS5eiLAuiStg/Y647B+Y4aE=\n" @=? actual
 
-  , it "generates hash without given salt" $
+  , testCase "generate hash without given salt" $
     do hash' <- runPwstore ["generate"] "hunter2"
        let hash = init hash'    -- Remove trailing \n
        assertBool "" $ P.verifyPassword "hunter2" (B.pack hash)
 
-  , it "generates hash with given strength" $
+  , testCase "generate hash with given strength" $
     do hash' <- runPwstore ["generate", "--strength=15"] "hunter2"
        let hash = init hash'    -- Remove trailing \n
        assertBool "" $ P.verifyPassword "hunter2" (B.pack hash)
        assertBool "" $ "sha256|15|" `isPrefixOf` hash
 
-  , it "strengthens hashes" $
+  , testCase "strengthen hash with stronger" $
     do actual <- runPwstore ["strengthen", "-s15", hunter2hash] ""
        "sha256|15|YmBsCrO7FQIcrbMt23jnOA==|6ugvNWDF6KznLSsNC6AGXEObUalzx60UKauaivGkPkU=\n" @=? actual
 
-  , it "does not weaken hashes" $
+  , testCase "strengthen hash with weaker" $
     do actual <- runPwstore ["strengthen", "-s11", hunter2hash] ""
        hunter2hash ++ "\n" @=? actual
   ]
 
 main :: IO ()
-main = hspecX specs
+main = defaultMain tests
