diff --git a/microstache.cabal b/microstache.cabal
--- a/microstache.cabal
+++ b/microstache.cabal
@@ -1,5 +1,5 @@
 name:               microstache
-version:            1.0.2.1
+version:            1.0.2.2
 cabal-version:      >=1.10
 license:            BSD3
 license-file:       LICENSE
@@ -40,7 +40,8 @@
    || ==8.8.4
    || ==8.10.7
    || ==9.0.2
-   || ==9.2.2
+   || ==9.2.4
+   || ==9.4.1
 
 source-repository head
   type:     git
@@ -48,8 +49,8 @@
 
 library
   build-depends:
-      aeson                 >=0.11    && <1.6 || >=2.0.0.0 && <2.1
-    , base                  >=4.5     && <4.17
+      aeson                 >=0.11    && <1.6 || >=2.0.0.0 && <2.2
+    , base                  >=4.5     && <4.18
     , containers            >=0.4.2.1 && <0.7
     , deepseq               >=1.3.0.0 && <1.5
     , directory             >=1.1.0.2 && <1.4
@@ -58,7 +59,7 @@
     , text                  >=1.2.3.0 && <1.3 || >=2.0 && <2.1
     , transformers          >=0.3.0.0 && <0.7
     , unordered-containers  >=0.2.5   && <0.3
-    , vector                >=0.11    && <0.13
+    , vector                >=0.11    && <0.14
 
   if impl(ghc <=7.6)
     build-depends: ghc-prim
@@ -77,23 +78,29 @@
   ghc-options:      -Wall
   default-language: Haskell2010
 
-test-suite tests
+test-suite spec
   main-is:          Spec.hs
-  hs-source-dirs:   tests
+  hs-source-dirs:   tests tasty-as-hspec
   type:             exitcode-stdio-1.0
   build-depends:
       aeson
     , base
     , containers
-    , hspec        >=2.0 && <3.0
     , microstache
     , parsec
     , text
 
+  -- tasty-as-hspec
+  build-depends:
+      base-orphans  >=0.8.7    && <0.9
+    , tasty         >=1.4.0.1  && <1.5
+    , tasty-hunit   >=0.10.0.3 && <0.11
+
   if !impl(ghc >=8.0)
     build-depends: semigroups
 
   other-modules:
+    Test.Hspec
     Text.Microstache.ParserSpec
     Text.Microstache.RenderSpec
     Text.Microstache.TypeSpec
@@ -102,16 +109,22 @@
 
 test-suite mustache-spec
   main-is:          Spec.hs
-  hs-source-dirs:   mustache-spec
+  hs-source-dirs:   mustache-spec tasty-as-hspec
   type:             exitcode-stdio-1.0
   build-depends:
       aeson
     , base
     , bytestring
     , containers
-    , hspec
     , microstache
     , parsec
     , text
 
+  -- tasty-as-hspec
+  build-depends:
+      base-orphans  >=0.8.7    && <0.9
+    , tasty         >=1.4.0.1  && <1.5
+    , tasty-hunit   >=0.10.0.3 && <0.11
+
+  other-modules:    Test.Hspec
   default-language: Haskell2010
diff --git a/tasty-as-hspec/Test/Hspec.hs b/tasty-as-hspec/Test/Hspec.hs
new file mode 100644
--- /dev/null
+++ b/tasty-as-hspec/Test/Hspec.hs
@@ -0,0 +1,102 @@
+{-# LANGUAGE ConstraintKinds            #-}
+{-# LANGUAGE DeriveFunctor              #-}
+{-# LANGUAGE FlexibleContexts           #-}
+{-# LANGUAGE GADTs                      #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE TypeOperators              #-}
+-- | A @hspec@ like interface build on top of tasty.
+module Test.Hspec (
+    -- * Runner
+    Spec,
+    hspec,
+    -- * Test trees
+    describe,
+    context,
+    it,
+    -- * Checks
+    Expectation,
+    expectationFailure,
+    shouldBe,
+    shouldContain,
+    shouldNotContain,
+    compareWith,
+) where
+
+import Control.Applicative (Applicative)
+import Control.Monad       (unless)
+import Data.List           (isInfixOf)
+import Data.Orphans ()
+import Prelude
+       (Bool, Eq, Functor, IO, Monad, Show, String, flip, fst, id, not, show,
+       ($), (++))
+import Test.Tasty          (TestName, TestTree, defaultMain, testGroup)
+import Test.Tasty.HUnit
+       (Assertion, HasCallStack, assertFailure, testCase, (@?=))
+
+-------------------------------------------------------------------------------
+-- Runner
+-------------------------------------------------------------------------------
+
+type Spec = TestTreeM ()
+
+hspec :: TestTreeM () -> IO ()
+hspec t = defaultMain (testGroup "X" (runTestTreeM t))
+
+-------------------------------------------------------------------------------
+-- Test trees
+-------------------------------------------------------------------------------
+
+newtype TestTreeM a = TestTreeM (Writer [TestTree] a)
+  deriving (Functor, Applicative, Monad)
+
+runTestTreeM :: TestTreeM () -> [TestTree]
+runTestTreeM (TestTreeM m) = fst (runWriter m)
+
+class Describe r where
+    describe :: TestName -> TestTreeM () -> r
+
+instance a ~ () =>  Describe (TestTreeM a) where
+    describe n t = TestTreeM $ tell [ describe n t ]
+
+instance Describe TestTree where
+    describe n t = testGroup n $ runTestTreeM t
+
+it :: TestName -> Assertion -> TestTreeM ()
+it n assertion = TestTreeM $ tell [ testCase n assertion ]
+
+context :: Describe r => TestName -> TestTreeM () -> r
+context n t = describe n t
+
+-------------------------------------------------------------------------------
+-- Checks
+-------------------------------------------------------------------------------
+
+type Expectation = Assertion
+
+expectationFailure :: String -> Expectation
+expectationFailure = assertFailure
+
+shouldBe :: (Eq a, Show a, HasCallStack) => a -> a -> Expectation
+shouldBe = (@?=)
+
+shouldContain :: (Eq a, Show a, HasCallStack) => [a] -> [a] -> Expectation
+shouldContain = compareWith (flip isInfixOf) "does not contain"
+
+shouldNotContain :: (Eq a, Show a, HasCallStack) => [a] -> [a] -> Expectation
+shouldNotContain = compareWith (\x y -> not (isInfixOf y x)) "contains"
+
+compareWith :: (Show a, Show b, HasCallStack) => (a -> b -> Bool) -> String -> a -> b -> Expectation
+compareWith f msg x y = unless (f x y) $ assertFailure $
+    show x ++ " " ++ msg ++ " " ++ show y
+
+-------------------------------------------------------------------------------
+-- Writer
+-------------------------------------------------------------------------------
+
+type Writer = (,)
+
+runWriter :: Writer w a -> (w, a)
+runWriter = id
+
+tell :: w -> (w, ())
+tell w = (w, ())
