diff --git a/test/Read.hs b/test/Read.hs
new file mode 100644
--- /dev/null
+++ b/test/Read.hs
@@ -0,0 +1,81 @@
+{-# OPTIONS -fno-warn-type-defaults #-}
+
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Read
+-- Copyright   :  (c) 2009 Sean Leather
+-- License     :  BSD3
+--
+-- Maintainer  :  leather@cs.uu.nl
+--
+-- Tests for Text.XFormat.Read.
+--------------------------------------------------------------------------------
+
+module Read (test) where
+
+--------------------------------------------------------------------------------
+
+import Text.XFormat.Read
+
+--------------------------------------------------------------------------------
+
+test :: Bool
+test = and
+  [ testBasic
+  , testClasses
+  , testRecursive
+  , testTuples
+  ]
+
+testBasic :: Bool
+testBasic = and
+  [ readsf Int "5abc" == [(5, "abc")]
+  , readsf 'a' "5" == []
+  , readsf 'a' "a" == [('a', "")]
+  , readf "Hello" "Hello" == Just "Hello"
+  , readf "Hello" "Goodbye" == Nothing
+  , readf (Int % "." % Int ) "123.456" == Just (123 % "." % 456)
+  , readf (Integer % "." % Integer ) "123.456" == Just (123 % "." % 456)
+  ]
+
+testClasses :: Bool
+testClasses = and
+  [ readf Read "\"34\"" == Just "34"
+  , readf Num "3.4" == Just 3.4
+  ]
+
+testRecursive :: Bool
+testRecursive = and
+  [ readf (Char % Integer % Space % Float % Space % Double % String) "~99 9.9 0.3" ==
+      Just ('~' :%: (99 :%: (" " :%: (9.9 :%: (" " :%: (0.3 :%: ""))))))
+  , readf (Wrap '(' Int ')') "(1)" == Just ('(' % 1 % ')')
+  , readf (Maybe Int) "1" == Just (Just 1)
+  , readf (Maybe Int) "a" == Just Nothing
+  , readf (Choice ['(',')']) ")" == Just ')'
+  , readf (Either Char Int) "1" == Just (Left '1')
+  , readf (EitherL Int Char) "1" == Just (Left 1)
+  , readf (Either Int Char) "a1" == Just (Right 'a')
+  ]
+
+testTuples :: Bool
+testTuples = and
+  [ readf (Char, Char) "ab" == Just ('a', 'b')
+  , readf (Char, Char, Char) "abc" == Just ('a', 'b', 'c')
+  , readf (Char, Char, Char, Char) "abcd" == Just ('a', 'b', 'c', 'd')
+  , readf (Char, Char, Char, Char, Char) "abcde" == Just ('a', 'b', 'c', 'd', 'e')
+  , readf (Char, Char, Char, Char, Char, Char) "abcdef" == Just ('a', 'b', 'c', 'd', 'e', 'f')
+  , readf (Char, Char, Char, Char, Char, Char, Char) "abcdefg" == Just ('a', 'b', 'c', 'd', 'e', 'f', 'g')
+  , readf (Char, Char, Char, Char, Char, Char, Char, Char) "abcdefgh" == Just ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h')
+  , readf (Char, Char, Char, Char, Char, Char, Char, Char, Char) "abcdefghi" == Just ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i')
+  , readf (Char, Char, Char, Char, Char, Char, Char, Char, Char, Char) "abcdefghij" == Just ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j')
+  , readf (Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char) "abcdefghijk" == Just ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k')
+  , readf (Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char) "abcdefghijkl" == Just ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l')
+  , readf (Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char) "abcdefghijklm" == Just ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm')
+  , readf (Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char) "abcdefghijklmn" == Just ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n')
+  , readf (Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char) "abcdefghijklmno" == Just ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o')
+{-
+  -- More than 15 is not yet supported.
+  , readf (Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char) "abcdefghijklmnop" == Just ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p')
+-}
+  ]
+
diff --git a/test/Show.hs b/test/Show.hs
new file mode 100644
--- /dev/null
+++ b/test/Show.hs
@@ -0,0 +1,87 @@
+{-# OPTIONS -fno-warn-type-defaults #-}
+
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Show
+-- Copyright   :  (c) 2009 Sean Leather
+-- License     :  BSD3
+--
+-- Maintainer  :  leather@cs.uu.nl
+--
+-- Tests for Text.XFormat.Show.
+--------------------------------------------------------------------------------
+
+module Show (test) where
+
+--------------------------------------------------------------------------------
+
+import Text.XFormat.Show
+
+--------------------------------------------------------------------------------
+
+test :: Bool
+test = and
+  [ testBasic
+  , testClasses
+  , testOther
+  , testRecursive
+  , testTuples
+  ]
+
+testBasic :: Bool
+testBasic = and
+  [ showsf "abc" "" == "abc"
+  , showsf 'c' "" == "c"
+  , showf Char 'a' == "a"
+  , showf String "abc" == "abc"
+  , showf Int 5 == "5"
+  , showf Integer 999999999999999999 == "999999999999999999"
+  , showf Float 9.2 == "9.2"
+  , showf Double 5.5 == "5.5"
+  ]
+
+testClasses :: Bool
+testClasses = and
+  [ showf Show "99.9" == "\"99.9\""
+  , showf Num 7734 == "7734"
+  ]
+
+testOther :: Bool
+testOther = and
+  [ let n = 15 in showf (Spaces n) == replicate n ' '
+  ]
+
+testRecursive :: Bool
+testRecursive = and
+  [ showf (Show % Int % String) 4.05 20 " blah" == "4.0520 blah"
+  , showf (Wrap '(' Int ')') 24 == "(24)"
+  , showf (Align L 5 String) "abc" == "abc  "
+  , showf (Align R 5 Int) 999 == "  999"
+  , showf (Align L 5 "1234567") == "1234567"
+  , showf (AlignChop L 5 "123") == "123  "
+  , showf (AlignChop L 3 "12345") == "123"
+  , showf (AlignChop R 3 "12345") == "345"
+  ]
+
+testTuples :: Bool
+testTuples = and
+  [ showf (Char, Char) 'a' 'b' == "ab"
+  , showf (Char, Char, Char) 'a' 'b' 'c' == "abc"
+  , showf (Char, Char, Char, Char) 'a' 'b' 'c' 'd' == "abcd"
+  , showf (Char, Char, Char, Char, Char) 'a' 'b' 'c' 'd' 'e' == "abcde"
+  , showf (Char, Char, Char, Char, Char, Char) 'a' 'b' 'c' 'd' 'e' 'f' == "abcdef"
+  , showf (Char, Char, Char, Char, Char, Char, Char) 'a' 'b' 'c' 'd' 'e' 'f' 'g' == "abcdefg"
+  , showf (Char, Char, Char, Char, Char, Char, Char, Char) 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' == "abcdefgh"
+  , showf (Char, Char, Char, Char, Char, Char, Char, Char, Char) 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' == "abcdefghi"
+  , showf (Char, Char, Char, Char, Char, Char, Char, Char, Char, Char) 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' == "abcdefghij"
+  , showf (Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char) 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' == "abcdefghijk"
+  , showf (Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char) 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' == "abcdefghijkl"
+  , showf (Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char) 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' == "abcdefghijklm"
+  , showf (Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char) 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' == "abcdefghijklmn"
+  , showf (Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char) 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' == "abcdefghijklmno"
+{-
+  -- More than 15 is not yet supported.
+  , showf (Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char, Char) 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' == "abcdefghijklmnop"
+-}
+  ]
+
diff --git a/xformat.cabal b/xformat.cabal
--- a/xformat.cabal
+++ b/xformat.cabal
@@ -1,5 +1,5 @@
 name:                   xformat
-version:                0.1.2
+version:                0.1.2.1
 synopsis:
 
   Extensible, type-safe formatting with scanf- and printf-like functions
@@ -57,6 +57,8 @@
   type:                 exitcode-stdio-1.0
   hs-source-dirs:       test
   main-is:              Main.hs
+  other-modules:        Read
+                        Show
   build-depends:        base >= 3.0 && < 5.0,
                         xformat
 
