diff --git a/package.yaml b/package.yaml
index 4cfa0b673203d2ddebfebf04c675be75bf96c04d..12ec06e7c7f1f907d71e8b5b228a3045950a0b2c 100644
--- a/package.yaml
+++ b/package.yaml
@@ -68,9 +68,10 @@ executables:
       - shift
 
 tests:
-  unit:
-    main: Main.hs
+  doctest:
+    main: Doctest.hs
     source-dirs:
       - test
     dependencies:
       - shift
+      - doctest
diff --git a/shift.cabal b/shift.cabal
index 2b69ecfd4ce79ea7868ee82d920596034244a3ff..cf00da29015e27ecefc4a4c3487113d1e6cac3b4 100644
--- a/shift.cabal
+++ b/shift.cabal
@@ -19,7 +19,7 @@ license-file:   LICENSE
 build-type:     Simple
 extra-source-files:
     README.md
-    test/Spec.hs
+    test/Doctest.hs
 
 library
   exposed-modules:
@@ -101,11 +101,10 @@ executable dab
     , versions
   default-language: Haskell2010
 
-test-suite unit
+test-suite doctest
   type: exitcode-stdio-1.0
-  main-is: Main.hs
+  main-is: Doctest.hs
   other-modules:
-      Spec
       Paths_shift
   hs-source-dirs:
       test
@@ -117,6 +116,7 @@ test-suite unit
     , cmark-gfm
     , containers
     , data-default
+    , doctest
     , exceptions
     , github
     , hgit
diff --git a/src/Shift/Rendering.hs b/src/Shift/Rendering.hs
index d65f8dc002b41882c8671e8f3363006385e5f8a0..2c8a6b3da026b94efe873f0bd2c6e86ce7d9841a 100644
--- a/src/Shift/Rendering.hs
+++ b/src/Shift/Rendering.hs
@@ -39,6 +39,9 @@ import Shift.Types
     crTests,
   )
 
+-- $setup
+-- >>> :set -XOverloadedStrings
+
 renderRef ::
   (MonadIO m, MonadState s m, ClientState s, MonadThrow m) =>
   Ref hash ->
@@ -124,11 +127,35 @@ renderMergeCommit (ref, commit, MergeCommit subject) = do
               ]
       ]
 
+-- | Renders a range of `TagRef`s.
+--
+-- Examples:
+--
+-- >>> import Shift.Types (TagRef(TagRef))
+-- >>> renderRange (TagRef "1.0.0" Nothing) (TagRef "1.1.0" Nothing)
+-- "1.0.0 to 1.1.0"
 renderRange :: TagRef -> TagRef -> Text
 renderRange tx ty =
   mconcat
     [renderTagRef tx, " to ", renderTagRef ty]
 
+-- | Renders a `TagRef`.
+--
+-- >>> import Data.Versions
+-- >>> import Shift.Types (TagRef(TagRef))
+-- >>> let version = Ideal $ SemVer 1 0 0 [] []
+-- >>> renderTagRef (TagRef "1.0.0" (Just version))
+-- "1.0.0"
+--
+-- >>> import Data.Versions
+-- >>> import Shift.Types (TagRef(TagRef))
+-- >>> let version = Ideal $ SemVer 1 0 0 [] []
+-- >>> renderTagRef (TagRef "1.0.1" (Just version))
+-- "1.0.0"
+--
+-- >>> import Shift.Types (TagRef(TagRef))
+-- >>> renderTagRef (TagRef "1.0.1" (Nothing))
+-- "1.0.1"
 renderTagRef :: TagRef -> Text
 renderTagRef tr = case _tVersioning tr of
   Just versioning -> prettyV versioning
diff --git a/test/Doctest.hs b/test/Doctest.hs
new file mode 100644
index 0000000000000000000000000000000000000000..dcd315217c448c9203a15b833a1fd5cc3f8fcdb8
--- /dev/null
+++ b/test/Doctest.hs
@@ -0,0 +1,4 @@
+import Test.DocTest
+
+main :: IO ()
+main = doctest ["-isrc", "src"]
\ No newline at end of file
diff --git a/test/Spec.hs b/test/Spec.hs
deleted file mode 100644
index cd4753fc9c10722ad5c3ec4fd34de99972243b6c..0000000000000000000000000000000000000000
--- a/test/Spec.hs
+++ /dev/null
@@ -1,2 +0,0 @@
-main :: IO ()
-main = putStrLn "Test suite not yet implemented"