diff --git a/extensible-effects.cabal b/extensible-effects.cabal
--- a/extensible-effects.cabal
+++ b/extensible-effects.cabal
@@ -6,7 +6,7 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             1.9.2.2
+version:             1.10.0.1
 
 -- A short (one-line) description of the package.
 synopsis:            An Alternative to Monad Transformers
@@ -85,11 +85,8 @@
   other-modules:       Data.OpenUnion.Internal.Base
   if impl(ghc >= 7.8.1)
      other-modules:    Data.OpenUnion.Internal.OpenUnion2
-     default-extensions:  Safe
   else
      other-modules:    Data.OpenUnion.Internal.OpenUnion1
-     other-extensions: Safe
-                       , Trustworthy
 
   -- LANGUAGE extensions used by modules in this package.
   other-extensions:    BangPatterns
@@ -108,8 +105,10 @@
                        , PatternGuards
                        , PolyKinds
                        , RankNTypes
+                       , Safe
                        , ScopedTypeVariables
                        , TupleSections
+                       , Trustworthy
                        , TypeOperators
                        , UndecidableInstances
   if impl(ghc < 7.8.1)
@@ -149,6 +148,7 @@
     , test-framework == 0.8.*
     , test-framework-hunit == 0.3.*
     , test-framework-quickcheck2 == 0.3.*
+    , test-framework-th >= 0.2
     , extensible-effects
     , void >= 0.6 && < 0.8
 
diff --git a/src/Control/Eff.hs b/src/Control/Eff.hs
--- a/src/Control/Eff.hs
+++ b/src/Control/Eff.hs
@@ -1,3 +1,5 @@
+{-# OPTIONS_HADDOCK show-extensions #-}
+
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE TupleSections #-}
 {-# LANGUAGE RankNTypes #-}
@@ -83,7 +85,7 @@
 import Data.Typeable
 import Data.Void
 
-#if MIN_VERSION_base(4,7,0)
+#if __GLASGOW_HASKELL__ >= 708
 #define Typeable1 Typeable
 #endif
 
diff --git a/src/Control/Eff/Exception.hs b/src/Control/Eff/Exception.hs
--- a/src/Control/Eff/Exception.hs
+++ b/src/Control/Eff/Exception.hs
@@ -26,7 +26,7 @@
 import Control.Eff
 import Control.Eff.Lift
 
-#if MIN_VERSION_base(4,7,0)
+#if __GLASGOW_HASKELL__ >= 708
 #define Typeable1 Typeable
 #endif
 
diff --git a/src/Control/Eff/Lift.hs b/src/Control/Eff/Lift.hs
--- a/src/Control/Eff/Lift.hs
+++ b/src/Control/Eff/Lift.hs
@@ -8,6 +8,8 @@
 {-# LANGUAGE CPP #-}
 #if __GLASGOW_HASKELL__ < 708
 {-# LANGUAGE Trustworthy #-}
+#else
+{-# LANGUAGE Safe #-}
 #endif
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# OPTIONS -fno-warn-orphans #-}
@@ -24,13 +26,13 @@
 import Control.Monad.IO.Class (MonadIO (..))
 import Data.Typeable
 
-#if MIN_VERSION_base(4,7,0)
+#if __GLASGOW_HASKELL__ >= 708
 #define Typeable1 Typeable
 #endif
 
 -- | Lift a Monad m to an effect.
 data Lift m v = forall a. Lift (m a) (a -> v)
-#if MIN_VERSION_base(4,7,0)
+#if __GLASGOW_HASKELL__ >= 708
     deriving (Typeable) -- starting from ghc-7.8 Typeable can only be derived
 #else
 
diff --git a/src/Control/Eff/Operational.hs b/src/Control/Eff/Operational.hs
--- a/src/Control/Eff/Operational.hs
+++ b/src/Control/Eff/Operational.hs
@@ -8,6 +8,8 @@
 {-# LANGUAGE DeriveDataTypeable #-}
 #if __GLASGOW_HASKELL__ < 708
 {-# LANGUAGE Trustworthy #-}
+#else
+{-# LANGUAGE Safe #-}
 #endif
 
 -- | Operational Monad (<https://wiki.haskell.org/Operational>) implemented with
@@ -23,14 +25,14 @@
 import Data.Typeable
 import Control.Eff
 
-#if MIN_VERSION_base(4,7,0)
+#if __GLASGOW_HASKELL__ >= 708
 #define Typeable1 Typeable
 #endif
 
 -- | Lift values to an effect.
 -- You can think this is a generalization of @Lift@.
 data Program instr v = forall a. Program (instr a) (a -> v)
-#if MIN_VERSION_base(4,7,0)
+#if __GLASGOW_HASKELL__ >= 708
          deriving (Typeable) -- starting from ghc-7.8 Typeable can only be derived
 #else
 
diff --git a/src/Control/Eff/Operational/Example.hs b/src/Control/Eff/Operational/Example.hs
--- a/src/Control/Eff/Operational/Example.hs
+++ b/src/Control/Eff/Operational/Example.hs
@@ -4,6 +4,7 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE Safe #-}
 
+-- | Example usage of "Control.Eff.Operational".
 module Control.Eff.Operational.Example where
 
 import Control.Eff.Operational
@@ -13,7 +14,7 @@
 import Control.Eff.State.Lazy
 import Data.Typeable
 
-#if MIN_VERSION_base(4,7,0)
+#if __GLASGOW_HASKELL__ >= 708
 #define Typeable1 Typeable
 #endif
 
diff --git a/src/Data/OpenUnion.hs b/src/Data/OpenUnion.hs
--- a/src/Data/OpenUnion.hs
+++ b/src/Data/OpenUnion.hs
@@ -1,3 +1,5 @@
+{-# OPTIONS_HADDOCK show-extensions #-}
+
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE PolyKinds #-}
@@ -7,8 +9,9 @@
 
 -- Only for SetMember below, when emulating Monad Transformers
 {-# LANGUAGE FunctionalDependencies, UndecidableInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
 
-#if MIN_VERSION_base(4,7,0)
+#if __GLASGOW_HASKELL__ >= 708
 #define Typeable1 Typeable
 #endif
 -- | Original work at <http://okmij.org/ftp/Haskell/extensible/OpenUnion1.hs>
@@ -19,8 +22,11 @@
 -- incorporating ideas from <http://okmij.org/ftp/Haskell/extensible/TList.hs>
 module Data.OpenUnion(
   -- * Classes
+  -- | @`Member` t r@ specifies whether @t@ is present anywhere in the sum type
+  -- @r@, where @t@ is some effectful type, e.g. @`Lift` `IO`@, @`State` Int`@
   Member
   -- ** Monad transformer related
+  -- | @`SetMember` set t r@ is used to emulate monad transformers.
   , SetMember
     -- * Type-indexed co-product
     -- ** Datatypes
diff --git a/src/Data/OpenUnion/Imports.hs b/src/Data/OpenUnion/Imports.hs
--- a/src/Data/OpenUnion/Imports.hs
+++ b/src/Data/OpenUnion/Imports.hs
@@ -1,8 +1,15 @@
+{-# OPTIONS_HADDOCK ignore-exports, show-extensions #-}
+
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE Safe #-}
 
+-- For 'Member' and 'MemberU' aliases below
+{-# LANGUAGE ConstraintKinds, PolyKinds #-}
+
 module Data.OpenUnion.Imports( Applicative(..)
                              , module Impl
+                             , Member
+                             , MemberU
                              ) where
 
 #if __GLASGOW_HASKELL__ < 710
@@ -10,6 +17,10 @@
 #endif
 #if __GLASGOW_HASKELL__ >= 708
 import Data.OpenUnion.Internal.OpenUnion2 as Impl
+type Member = MemberImpl OU2
+type MemberU = MemberUImpl OU2
 #else
 import Data.OpenUnion.Internal.OpenUnion1 as Impl
+type Member = MemberImpl OU1
+type MemberU = MemberUImpl OU1
 #endif
diff --git a/src/Data/OpenUnion/Internal/Base.hs b/src/Data/OpenUnion/Internal/Base.hs
--- a/src/Data/OpenUnion/Internal/Base.hs
+++ b/src/Data/OpenUnion/Internal/Base.hs
@@ -1,21 +1,35 @@
+{-# OPTIONS_HADDOCK hide, show-extensions #-}
+
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE MultiParamTypeClasses, ConstraintKinds, UndecidableInstances #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE PolyKinds, FunctionalDependencies #-}
 {-# LANGUAGE KindSignatures #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE CPP #-}
-{-# LANGUAGE Safe #-}
+{-# LANGUAGE Trustworthy #-} -- GHC.Exts.Constraint makes module not 'Safe'
 
-#if MIN_VERSION_base(4,7,0)
+#if __GLASGOW_HASKELL__ >= 708
 #define Typeable1 Typeable
 #endif
 
 -- | Adapted from <http://okmij.org/ftp/Haskell/extensible/OpenUnion1.hs> and
 -- <http://okmij.org/ftp/Haskell/extensible/OpenUnion2.hs>
-module Data.OpenUnion.Internal.Base( Union (..)
-                                   , (:>)
-                                   ) where
+module Data.OpenUnion.Internal.Base(
+  -- * Datatypes
+  Union (..)
+  , (:>)
+  -- * Classes
+  , MemberConstraint
+  , MemberImpl
+  -- ** Monad transformer related
+  , MemberUConstraint
+  , MemberUImpl
+  ) where
 
 import Data.Typeable
+import GHC.Exts (Constraint)
 
 -- | Parameter @r@ is phantom: it just tells what could be in the union.
 -- Where @r@ is @t1 :> t2 ... :> tn@, @`Union` r v@ can be constructed with a
@@ -24,8 +38,9 @@
 --
 -- NOTE: exposing the constructor below allows users to bypass the type
 -- system. See 'Data.OpenUnion.unsafeReUnion' for example.
-data Union r v = forall t. (Functor t, Typeable1 t) => Union (t v)
-                 deriving Typeable
+data Union (r :: *) (v :: *) =
+  forall t. (Functor t, Typeable1 t) => Union (t v)
+  deriving Typeable
 
 instance Functor (Union r) where
     {-# INLINE fmap #-}
@@ -33,7 +48,19 @@
 
 -- | A sum data type, for composing effects
 infixr 1 :>
-data ((a :: * -> *) :> b)
+data ((a :: * -> *) :> (b :: *))
 #if __GLASGOW_HASKELL__ >= 708
   deriving Typeable
 #endif
+
+type family MemberConstraint impl (t :: * -> *) r :: Constraint
+-- | The @`MemberImpl` impl t r@ specifies whether @t@ is present anywhere in
+-- the sum type @r@, where @t@ is some effectful type
+-- (e.g. @`Lift` `IO`@, @`State` Int`@), for a particular implementation ('impl'
+-- label, eg. 'OU1' representing 'OpenUnion1').
+class (MemberConstraint impl t r) => MemberImpl impl (t :: * -> *) r
+
+type family MemberUConstraint impl (t :: * -> *) r :: Constraint
+-- | This class is used for emulating monad transformers
+class MemberUConstraint impl (t :: * -> *) r
+      => MemberUImpl impl (tag :: k -> * -> *) (t :: * -> *) r | tag r -> t
diff --git a/src/Data/OpenUnion/Internal/OpenUnion1.hs b/src/Data/OpenUnion/Internal/OpenUnion1.hs
--- a/src/Data/OpenUnion/Internal/OpenUnion1.hs
+++ b/src/Data/OpenUnion/Internal/OpenUnion1.hs
@@ -1,31 +1,34 @@
+{-# OPTIONS_HADDOCK hide, show-extensions #-}
+
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE PolyKinds #-}
 {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
+{-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE Safe #-}
 
 -- Only for MemberU below, when emulating Monad Transformers
-{-# LANGUAGE FunctionalDependencies, OverlappingInstances, UndecidableInstances #-}
+{-# LANGUAGE OverlappingInstances, UndecidableInstances #-}
 
 -- | Original work at <http://okmij.org/ftp/Haskell/extensible/OpenUnion1.hs>.
 -- Open unions (type-indexed co-products) for extensible effects.
 -- This implementation relies on _closed_ overlapping instances
 -- (or closed type function overlapping soon to be added to GHC).
-module Data.OpenUnion.Internal.OpenUnion1( Union (..)
-                                         , (:>)
-                                         , Member
-                                         , MemberU
+module Data.OpenUnion.Internal.OpenUnion1( OU1
+                                         , module Base
                                          ) where
 
-import Data.OpenUnion.Internal.Base
+import Data.OpenUnion.Internal.Base as Base
 
--- | The @`Member` t r@ specifies whether @t@ is present anywhere in the sum
--- type @r@, where @t@ is some effectful type,
--- e.g. @`Lift` `IO`@, @`State` Int`@.
-class Member (t :: * -> *) r
-instance Member t (t :> r)
-instance Member t r => Member t (t' :> r)
+-- | Label to represent 'OpenUnion1' implementation
+data OU1
 
--- | This class is used for emulating monad transformers
-class Member t r => MemberU (tag :: k -> * -> *) (t :: * -> *) r | tag r -> t
-instance MemberU tag (tag e) (tag e :> r)
-instance MemberU tag t r => MemberU tag t (t' :> r)
+-- | @`MemberImpl` OU1 t r@ specifies whether @t@ is present anywhere in the
+-- sum type @r@, where @t@ is some effectful type
+type instance MemberConstraint OU1 t r = ()
+instance MemberImpl OU1 t (t :> r)
+instance MemberImpl OU1 t r => MemberImpl OU1 t (t' :> r)
+
+-- | For emulating monad transformers
+type instance MemberUConstraint OU1 t r = (MemberImpl OU1 t r)
+instance MemberUImpl OU1 tag (tag e) (tag e :> r)
+instance MemberUImpl OU1 tag t r => MemberUImpl OU1 tag t (t' :> r)
diff --git a/src/Data/OpenUnion/Internal/OpenUnion2.hs b/src/Data/OpenUnion/Internal/OpenUnion2.hs
--- a/src/Data/OpenUnion/Internal/OpenUnion2.hs
+++ b/src/Data/OpenUnion/Internal/OpenUnion2.hs
@@ -1,7 +1,11 @@
+{-# OPTIONS_HADDOCK hide, show-extensions #-}
+
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ConstraintKinds #-}
 {-# LANGUAGE DataKinds, PolyKinds #-}
 {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE Safe #-}
 
 -- Only for MemberU below, when emulating Monad Transformers
@@ -11,22 +15,23 @@
 -- Open unions (type-indexed co-products) for extensible effects.
 -- This implementation relies on _closed_ type families added to GHC 7.8. It has
 -- NO overlapping instances
-module Data.OpenUnion.Internal.OpenUnion2( Union (..)
-                                         , (:>)
-                                         , Member
-                                         , MemberU
+module Data.OpenUnion.Internal.OpenUnion2( OU2
+                                         , module Base
                                          ) where
 
-import Data.OpenUnion.Internal.Base
+import Data.OpenUnion.Internal.Base as Base
 
--- | Class Member is defined only for the sake of the interface compatibility
--- with OpenUnion1. Generally, the closed type family Member' below could be
--- used instead.
+-- | Label to represent 'OpenUnion1' implementation
+data OU2
+
+-- | Instance MemberImpl is defined only for the sake of the interface
+-- compatibility with OpenUnion1. Generally, the closed type family Member'
+-- below could be used instead.
 --
--- The @`Member` t r@ specifies whether @t@ is present anywhere in the sum type
--- @r@, where @t@ is some effectful type, e.g. @`Lift` `IO`@, @`State` Int`@.
-class (Member' t r ~ 'True) => Member (t :: * -> *) r
-instance (Member' t r ~ 'True) => Member t r
+-- @`MemberImpl` OU2 t r@ specifies whether @t@ is present anywhere in the sum
+-- type @r@, where @t@ is some effectful type
+type instance MemberConstraint OU2 t r = (Member' t r ~ 'True)
+instance (MemberConstraint OU2 t r) => MemberImpl OU2 t r
 
 type family Member' (t :: * -> *) r :: Bool where
   Member' t (t :> r)  = 'True
@@ -37,12 +42,12 @@
   EQU a a = 'True
   EQU a b = 'False
 
--- | This class is used for emulating monad transformers
-class Member t r => MemberU (tag :: k -> * -> *) (t :: * -> *) r | tag r -> t
-instance (MemberU' (EQU t1 t2) tag t1 (t2 :> r)) => MemberU tag t1 (t2 :> r)
+-- | For emulating monad transformers
+type instance MemberUConstraint OU2 t r = (MemberImpl OU2 t r)
+instance (MemberU' (EQU t1 t2) tag t1 (t2 :> r)) => MemberUImpl OU2 tag t1 (t2 :> r)
 
-class Member t r =>
+class MemberImpl OU2 t r =>
       MemberU' (f::Bool) (tag :: k -> * -> *) (t :: * -> *) r | tag r -> t
 instance MemberU' 'True tag (tag e) (tag e :> r)
-instance (Member' t (t' :> r) ~ 'True, MemberU tag t r) =>
+instance (Member' t (t' :> r) ~ 'True, MemberUImpl OU2 tag t r) =>
            MemberU' 'False tag t (t' :> r)
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE CPP #-}
@@ -8,6 +9,7 @@
 import Test.Framework (defaultMain)
 import Test.Framework.Providers.HUnit
 import Test.Framework.Providers.QuickCheck2
+import Test.Framework.TH
 
 import Test.HUnit hiding (State)
 import Test.QuickCheck
@@ -25,6 +27,18 @@
 import Control.Eff.Writer.Strict as StrictW
 import Data.Void
 
+main :: IO ()
+main = defaultMain tests
+
+tests = [
+  $(testGroupGenerator)
+#if __GLASGOW_HASKELL__ >= 708
+  , testProperty "Test nested Eff." testNestedEff
+#endif
+        ]
+
+-- {{{ utils
+
 withError :: a -> ErrorCall -> a
 withError a _ = a
 
@@ -34,9 +48,6 @@
 assertNoUndefined :: a -> Assertion
 assertNoUndefined a = catch (seq a $ return ()) (withError $ assertFailure "")
 
-main :: IO ()
-main = defaultMain tests
-
 allEqual :: Eq a => [a] -> Bool
 allEqual = all (uncurry (==)) . pairs
   where
@@ -45,14 +56,19 @@
 safeLast [] = Nothing
 safeLast l = Just $ last l
 
-testDocs :: [Integer] -> Property
-testDocs l = let
-              (total1, ()) = run $ LazyS.runState 0 $ sumAll l
-              (last1, ()) = run $ LazyW.runLastWriter $ writeAll l
-              (total2, (last2, ())) = run $ LazyS.runState 0 $ LazyW.runLastWriter $ writeAndAdd l
-              (last3, (total3, ())) = run $ LazyW.runLastWriter $ LazyS.runState 0 $ writeAndAdd l
-             in allEqual [safeLast l, last1, last2, last3]
-           .&&. allEqual [sum l, total1, total2, total3]
+-- }}}
+
+-- {{{ Documentation example
+
+prop_Documentation_example :: [Integer] -> Property
+prop_Documentation_example l = let
+  (total1, ()) = run $ LazyS.runState 0 $ sumAll l
+  (last1, ()) = run $ LazyW.runLastWriter $ writeAll l
+  (total2, (last2, ())) = run $ LazyS.runState 0 $ LazyW.runLastWriter $ writeAndAdd l
+  (last3, (total3, ())) = run $ LazyW.runLastWriter $ LazyS.runState 0 $ writeAndAdd l
+  in
+   allEqual [safeLast l, last1, last2, last3]
+   .&&. allEqual [sum l, total1, total2, total3]
   where
     writeAll :: (Typeable a, Member (LazyW.Writer a) e)
              => [a]
@@ -71,39 +87,43 @@
         writeAll lst
         sumAll lst
 
-testCensor :: [Integer] -> Property
-testCensor l = property
-             $ listE (mapM_ (LazyW.tell . inc) l) == listE (LazyW.censor inc $ mapM_ LazyW.tell l)
-  where
-    inc :: Integer -> Integer
-    inc = (+1)
+-- }}}
 
-    listE :: Eff (LazyW.Writer Integer :> Void) () -> [Integer]
-    listE = fst . run . LazyW.runWriter (:) []
+-- {{{ Reader.runReader
 
-testReaderLaziness :: Assertion
-testReaderLaziness = let e = run $ LazyR.runReader voidReader (undefined :: ())
-                     in assertNoUndefined (e :: ())
+case_Lazy_Reader_runReader :: Assertion
+case_Lazy_Reader_runReader = let
+  e = run $ LazyR.runReader voidReader (undefined :: ())
+  in
+   assertNoUndefined (e :: ())
   where
     voidReader = do
         _ <- (LazyR.ask :: Eff (LazyR.Reader () :> Void) ())
         return ()
 
-testReaderStrictness :: Assertion
-testReaderStrictness = let e = run $ StrictR.runReader voidReader (undefined :: ())
-                       in assertUndefined (e :: ())
+case_Strict_Reader_runReader :: Assertion
+case_Strict_Reader_runReader = let
+  e = run $ StrictR.runReader voidReader (undefined :: ())
+  in
+   assertUndefined (e :: ())
   where
     voidReader = do
         _ <- (StrictR.ask :: Eff (StrictR.Reader () :> Void) ())
         return ()
 
-testStateLaziness :: Assertion
-testStateLaziness = let (r, ()) = run
-                                $ LazyS.runState undefined
-                                $ getVoid
-                               >> putVoid undefined
-                               >> putVoid ()
-                    in assertNoUndefined r
+-- }}}
+
+-- {{{ State.runState
+
+case_Lazy_State_runState :: Assertion
+case_Lazy_State_runState = let
+  (r, ()) = run
+            $ LazyS.runState undefined
+            $ getVoid
+            >> putVoid undefined
+            >> putVoid ()
+  in
+   assertNoUndefined r
   where
     getVoid :: Eff (LazyS.State () :> Void) ()
     getVoid = LazyS.get
@@ -111,13 +131,15 @@
     putVoid :: () -> Eff (LazyS.State () :> Void) ()
     putVoid = LazyS.put
 
-testStateStrictness :: Assertion
-testStateStrictness = let (r, ()) = run
-                                  $ StrictS.runState undefined
-                                  $ getVoid
-                                 >> putVoid undefined
-                                 >> putVoid ()
-                      in assertUndefined r
+case_Strict_State_runState :: Assertion
+case_Strict_State_runState = let
+  (r, ()) = run
+            $ StrictS.runState undefined
+            $ getVoid
+            >> putVoid undefined
+            >> putVoid ()
+  in
+   assertUndefined r
   where
     getVoid :: Eff (StrictS.State () :> Void) ()
     getVoid = StrictS.get
@@ -125,20 +147,57 @@
     putVoid :: () -> Eff (StrictS.State () :> Void) ()
     putVoid = StrictS.put
 
-testLastWriterLaziness :: Assertion
-testLastWriterLaziness = let (Just m, ()) = run $ LazyW.runLastWriter $ mapM_ LazyW.tell [undefined, ()]
-                         in assertNoUndefined (m :: ())
+-- }}}
 
-testLastWriterStrictness :: Assertion
-testLastWriterStrictness = let (Just m, ()) = run $ StrictW.runLastWriter $ mapM_ StrictW.tell [undefined, ()]
-                           in assertUndefined (m :: ())
+-- {{{ Writer
 
-testFirstWriterLaziness :: Assertion
-testFirstWriterLaziness = let (Just m, ()) = run $ LazyW.runFirstWriter $ mapM_ LazyW.tell [(), undefined]
-                          in assertNoUndefined (m :: ())
+-- {{{ Writer.censor
 
-testFailure :: Assertion
-testFailure =
+prop_Lazy_Writer_censor :: [Integer] -> Property
+prop_Lazy_Writer_censor l =
+  property
+  $ listE (mapM_ (LazyW.tell . inc) l) == listE (LazyW.censor inc $ mapM_ LazyW.tell l)
+  where
+    inc :: Integer -> Integer
+    inc = (+1)
+
+    listE :: Eff (LazyW.Writer Integer :> Void) () -> [Integer]
+    listE = fst . run . LazyW.runWriter (:) []
+
+-- }}}
+
+-- {{{ Writer.runFirstWriter
+
+case_Lazy_Writer_runFirstWriter :: Assertion
+case_Lazy_Writer_runFirstWriter = let
+  (Just m, ()) = run $ LazyW.runFirstWriter $ mapM_ LazyW.tell [(), undefined]
+  in
+   assertNoUndefined (m :: ())
+
+-- }}}
+
+-- {{{ Writer.runLastWriter
+
+case_Lazy_Writer_runLastWriter :: Assertion
+case_Lazy_Writer_runLastWriter = let
+  (Just m, ()) = run $ LazyW.runLastWriter $ mapM_ LazyW.tell [undefined, ()]
+  in
+   assertNoUndefined (m :: ())
+
+case_Strict_Writer_runLastWriter :: Assertion
+case_Strict_Writer_runLastWriter = let
+  (Just m, ()) = run $ StrictW.runLastWriter $ mapM_ StrictW.tell [undefined, ()]
+  in
+   assertUndefined (m :: ())
+
+-- }}}
+
+-- }}}
+
+-- {{{ Eff Failure
+
+case_Failure_Effect :: Assertion
+case_Failure_Effect =
   let go :: Eff (Exc () :> StrictW.Writer Int :> Void) Int
          -> Int
       go = fst . run . StrictW.runWriter (+) 0 . ignoreFail
@@ -151,17 +210,25 @@
         return 5
    in assertEqual "Fail should stop writing" 6 ret
 
-#if MIN_VERSION_base(4,7,0)
+-- }}}
+
+#if __GLASGOW_HASKELL__ >= 708
 #define Typeable1 Typeable
 #endif
 
+-- {{{ test Lift building
+
 -- | Ensure that https://github.com/RobotGymnast/extensible-effects/issues/11 stays resolved.
-testLift :: Assertion
-testLift = runLift possiblyAmbiguous
+case_Lift_building :: Assertion
+case_Lift_building = runLift possiblyAmbiguous
   where
     possiblyAmbiguous :: (Typeable1 m, Monad m, SetMember Lift (Lift m) r) => Eff r ()
     possiblyAmbiguous = lift $ return ()
 
+-- }}}
+
+-- {{{ Nested Eff
+
 #if __GLASGOW_HASKELL__ >= 708
 testNestedEff :: Property
 testNestedEff = forAll arbitrary (\x -> property (qu x == x))
@@ -180,8 +247,12 @@
       return x
 #endif
 
-testOperational :: Assertion
-testOperational =
+-- }}}
+
+-- {{{ Operational Monad
+
+case_Operational_Monad :: Assertion
+case_Operational_Monad =
   let comp :: (Member (LazyS.State [String]) r
                , Member (LazyW.Writer String) r)
               => Eff r ()
@@ -192,20 +263,4 @@
    "Evaluating Operational Monad example"
    "getting input...\nok\nthe input is foo\n" go
 
-tests =
-  [ testProperty "Documentation example." testDocs
-  , testProperty "Test Writer.Lazy.censor." testCensor
-  , testCase "Test runReader laziness." testReaderLaziness
-  , testCase "Test runReader strictness." testReaderStrictness
-  , testCase "Test runState laziness." testStateLaziness
-  , testCase "Test runState strictness." testStateStrictness
-  , testCase "Test runLastWriter laziness." testLastWriterLaziness
-  , testCase "Test runLastWriter strictness." testLastWriterStrictness
-  , testCase "Test runFirstWriter laziness." testFirstWriterLaziness
-  , testCase "Test failure effect." testFailure
-  , testCase "Test lift building." testLift
-#if __GLASGOW_HASKELL__ >= 708
-  , testProperty "Test nested Eff." testNestedEff
-#endif
-  , testCase "Test Operational monad." testOperational
-  ]
+-- }}}
