diff --git a/example/Test.hs b/example/Test.hs
deleted file mode 100644
--- a/example/Test.hs
+++ /dev/null
@@ -1,7 +0,0 @@
-module Main where
-
-import Text.HTML.Tagchup.Test as Test
-
-main :: IO ()
-main =
-   putStrLn Test.laziness
diff --git a/src/Text/HTML/Tagchup/Test.hs b/src/Text/HTML/Tagchup/Test.hs
deleted file mode 100644
--- a/src/Text/HTML/Tagchup/Test.hs
+++ /dev/null
@@ -1,76 +0,0 @@
-module Text.HTML.Tagchup.Test (
-    -- * Tests on laziness
-    laziness, lazyTags, lazyWarnings, restrictedWarnings,
-   ) where
-
-import qualified Text.HTML.Tagchup.Tag    as Tag
-import qualified Text.HTML.Tagchup.Parser as Parser
-import qualified Text.XML.Basic.Name.MixedCase as Name
-import Data.List (isPrefixOf, )
-
-{-
-*Text.HTML.TagSoup.HT> mapM print $ runSoup $ "</html " ++ cycle " abc=a_b&c"
-("anonymous input" (line 1, column 1),TagClose "html")
-("anonymous input" (line 1, column 9),TagWarning "Junk in closing tag: \"abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a
--}
-
-{- |
-This routine tests the laziness of the TagSoup parser.
-For each critical part of the parser we provide a test input
-with a token of infinite size.
-Then the output must be infinite too.
-If the laziness is broken, then the output will stop early.
-We collect the thousandth character of the output of each test case.
-If computation of the list stops somewhere,
-you have found a laziness stopper.
--}
-laziness :: [Char]
-laziness = lazyTags ++ lazyWarnings ++ restrictedWarnings
-
-runSoup :: String -> [Tag.T Name.T String]
-runSoup = Parser.runSoup
-
-lazyTags :: [Char]
-lazyTags =
-   map ((!!1000) . show . runSoup) $
-      (cycle "Rhabarber") :
-      (repeat '&') :
-      ('&' : '#' : repeat '1') :
-      ('&' : repeat 'a') :
-      ("<"++cycle "html") :
-      ("<html "++cycle "name") :
-      ("<html "++cycle "na!me=value ") :
-      ("<html name="++cycle "value") :
-      ("<html name=\""++cycle "value") :
-      ("<html name="++cycle "val!ue") :
-      ("<html name="++cycle "val&ue") :
-      ("<html name="++cycle "va&l!ue") :
-      ("</"++cycle "html") :
-      ("</html "++cycle "junk") :
-      ("<!-- "++cycle "comment") :
-      ("<!"++cycle "doctype") :
-      ("<![CDATA["++cycle "content&am<") :
-      ("<!DOCTYPE"++cycle " description") :
-      ("<?xml "++cycle "name") :
-      ("<?custom "++cycle "name") :
-      (cycle "1<2 ") :
-      []
-
-lazyWarnings :: [Char]
-lazyWarnings =
-   map ((!!1000) . show . tail . runSoup) $
-      (repeat '&') :
-      ("<html "++cycle "na!me=value ") :
-      ("</html "++cycle "junk") :
-      (cycle "1<2 ") :
-      []
-
-restrictedWarnings :: [Char]
-restrictedWarnings =
-   map (last . show . head .
-        dropWhile (not . maybe False (isPrefixOf "further") . Tag.maybeWarning) .
-        runSoup) $
-      ("<html name="++cycle "val!ue") :
-      ("<html name="++cycle "val&ue") :
-      ("<html name="++cycle "va&l!ue") :
-      []
diff --git a/tagchup.cabal b/tagchup.cabal
--- a/tagchup.cabal
+++ b/tagchup.cabal
@@ -1,5 +1,5 @@
 Name:           tagchup
-Version:        0.4.0.4
+Version:        0.4.0.5
 License:        GPL
 License-File:   LICENSE
 Author:         Henning Thielemann <tagchup@henning-thielemann.de>
@@ -22,7 +22,7 @@
    .
    The name Tagchup resembles Ketchup.
 Build-Type:  Simple
-Cabal-Version: >= 1.6
+Cabal-Version: >= 1.10
 
 Data-Files:
    example/Escape/iso8859.xhtml
@@ -38,27 +38,24 @@
 Source-Repository this
    Type:     darcs
    Location: http://code.haskell.org/~thielema/tagchup/
-   Tag:      0.4.0.4
+   Tag:      0.4.0.5
 
 Flag buildExamples
    description: Build example executables
    default:     False
 
-Flag buildTests
-   description: Build test suite
-   default:     False
 
-
 Library
    Build-Depends:
       xml-basic >=0.1.1 && <0.2,
-      transformers >=0.2 && <0.5,
+      transformers >=0.2 && <0.6,
       explicit-exception >=0.1 && <0.2,
       bytestring >=0.9.0.1 && <0.11,
       containers >=0.1 && <0.6,
       data-accessor >=0.2 && <0.3,
       utility-ht >=0.0.1 && <0.1,
       base >=3 && <5
+   Default-Language: Haskell98
    GHC-Options: -Wall
    Hs-Source-Dirs: src
    Exposed-Modules:
@@ -77,31 +74,48 @@
       Text.HTML.Tagchup.Parser.Stream
       Text.HTML.Tagchup.Parser.Tag
 
-Executable tagchuptest
-   If !flag(buildTests)
-     Buildable: False
+Test-Suite tagchuptest
+   Type:           exitcode-stdio-1.0
    If impl(ghc >= 6.12)
      GHC-Options: -rtsopts
    GHC-Options:    -Wall
-   Hs-Source-Dirs: src, example
+   Hs-Source-Dirs: testsuite
    Other-Modules:  Text.HTML.Tagchup.Test
    Main-Is:        Test.hs
+   Build-Depends:
+     tagchup,
+     xml-basic,
+     base
+   Default-Language: Haskell98
 
-Executable tagchupspeed
-   If flag(buildTests)
-     Build-Depends: old-time >=1.0 && <1.1
-   Else
-     Buildable: False
+Benchmark tagchupspeed
+   Type:           exitcode-stdio-1.0
+   Build-Depends:  old-time >=1.0 && <1.2
    GHC-Options:    -Wall
    Hs-Source-Dirs: src, example
    Main-Is:        Speed.hs
+   Build-Depends:
+     xml-basic,
+     data-accessor,
+     explicit-exception,
+     transformers,
+     containers,
+     utility-ht,
+     bytestring,
+     base
+   Default-Language: Haskell98
 
 Executable validate-tagchup
    If !flag(buildExamples)
      Buildable: False
    GHC-Options:    -Wall
-   Hs-Source-Dirs: src, example
+   Hs-Source-Dirs: example
    Main-Is:        Validate.hs
+   Build-Depends:
+     tagchup,
+     xml-basic,
+     base
+   Default-Language: Haskell98
 
 Executable escape-html
    If flag(buildExamples)
@@ -109,12 +123,22 @@
    Else
      Buildable: False
    GHC-Options:    -Wall
-   Hs-Source-Dirs: src, example
+   Hs-Source-Dirs: example
    Main-Is:        Escape.hs
+   Build-Depends:
+     tagchup,
+     xml-basic,
+     base
+   Default-Language: Haskell98
 
 Executable strip-html
    If !flag(buildExamples)
      Buildable: False
    GHC-Options:    -Wall
-   Hs-Source-Dirs: src, example
+   Hs-Source-Dirs: example
    Main-Is:        Strip.hs
+   Build-Depends:
+     tagchup,
+     xml-basic,
+     base
+   Default-Language: Haskell98
diff --git a/testsuite/Test.hs b/testsuite/Test.hs
new file mode 100644
--- /dev/null
+++ b/testsuite/Test.hs
@@ -0,0 +1,7 @@
+module Main where
+
+import Text.HTML.Tagchup.Test as Test
+
+main :: IO ()
+main =
+   putStrLn Test.laziness
diff --git a/testsuite/Text/HTML/Tagchup/Test.hs b/testsuite/Text/HTML/Tagchup/Test.hs
new file mode 100644
--- /dev/null
+++ b/testsuite/Text/HTML/Tagchup/Test.hs
@@ -0,0 +1,76 @@
+module Text.HTML.Tagchup.Test (
+    -- * Tests on laziness
+    laziness, lazyTags, lazyWarnings, restrictedWarnings,
+   ) where
+
+import qualified Text.HTML.Tagchup.Tag    as Tag
+import qualified Text.HTML.Tagchup.Parser as Parser
+import qualified Text.XML.Basic.Name.MixedCase as Name
+import Data.List (isPrefixOf, )
+
+{-
+*Text.HTML.TagSoup.HT> mapM print $ runSoup $ "</html " ++ cycle " abc=a_b&c"
+("anonymous input" (line 1, column 1),TagClose "html")
+("anonymous input" (line 1, column 9),TagWarning "Junk in closing tag: \"abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a_b&c abc=a
+-}
+
+{- |
+This routine tests the laziness of the TagSoup parser.
+For each critical part of the parser we provide a test input
+with a token of infinite size.
+Then the output must be infinite too.
+If the laziness is broken, then the output will stop early.
+We collect the thousandth character of the output of each test case.
+If computation of the list stops somewhere,
+you have found a laziness stopper.
+-}
+laziness :: [Char]
+laziness = lazyTags ++ lazyWarnings ++ restrictedWarnings
+
+runSoup :: String -> [Tag.T Name.T String]
+runSoup = Parser.runSoup
+
+lazyTags :: [Char]
+lazyTags =
+   map ((!!1000) . show . runSoup) $
+      (cycle "Rhabarber") :
+      (repeat '&') :
+      ('&' : '#' : repeat '1') :
+      ('&' : repeat 'a') :
+      ("<"++cycle "html") :
+      ("<html "++cycle "name") :
+      ("<html "++cycle "na!me=value ") :
+      ("<html name="++cycle "value") :
+      ("<html name=\""++cycle "value") :
+      ("<html name="++cycle "val!ue") :
+      ("<html name="++cycle "val&ue") :
+      ("<html name="++cycle "va&l!ue") :
+      ("</"++cycle "html") :
+      ("</html "++cycle "junk") :
+      ("<!-- "++cycle "comment") :
+      ("<!"++cycle "doctype") :
+      ("<![CDATA["++cycle "content&am<") :
+      ("<!DOCTYPE"++cycle " description") :
+      ("<?xml "++cycle "name") :
+      ("<?custom "++cycle "name") :
+      (cycle "1<2 ") :
+      []
+
+lazyWarnings :: [Char]
+lazyWarnings =
+   map ((!!1000) . show . tail . runSoup) $
+      (repeat '&') :
+      ("<html "++cycle "na!me=value ") :
+      ("</html "++cycle "junk") :
+      (cycle "1<2 ") :
+      []
+
+restrictedWarnings :: [Char]
+restrictedWarnings =
+   map (last . show . head .
+        dropWhile (not . maybe False (isPrefixOf "further") . Tag.maybeWarning) .
+        runSoup) $
+      ("<html name="++cycle "val!ue") :
+      ("<html name="++cycle "val&ue") :
+      ("<html name="++cycle "va&l!ue") :
+      []
