diff --git a/Data/List/Unique.hs b/Data/List/Unique.hs
--- a/Data/List/Unique.hs
+++ b/Data/List/Unique.hs
@@ -148,10 +148,15 @@
 --
 
 isUnique :: Eq a => a -> [a] -> Maybe Bool
-isUnique x = checkNumber . countElem x
-    where checkNumber 0 = Nothing
-          checkNumber 1 = Just True
-          checkNumber _ = Just False
+isUnique a = go Nothing a
+    where go s _ [] = s
+          go s@Nothing x (z:zs)
+            | x == z = go (Just True) x zs
+            | otherwise = go s x zs
+          go s@(Just True) x (z:zs)
+            | x == z = Just False
+            | otherwise = go s x zs
+          go s@(Just False) _ _ = s
 
 -- | 'isRepeated' is a reverse function to 'isUnique'
 --
diff --git a/Unique.cabal b/Unique.cabal
--- a/Unique.cabal
+++ b/Unique.cabal
@@ -1,72 +1,50 @@
--- Initial Unique.cabal generated by cabal init.  For further
--- documentation, see http://haskell.org/cabal/users-guide/
-
--- The name of the package.
 name:                Unique
 
--- The package version.  See the Haskell package versioning policy (PVP)
--- for standards guiding when and how versions should be incremented.
--- http://www.haskell.org/haskellwiki/Package_versioning_policy
--- PVP summary:      +-+------- breaking API changes
---                   | | +----- non-breaking API additions
---                   | | | +--- code changes with no API change
-version:             0.4.5
-
--- A short (one-line) description of the package.
-synopsis:           It provides the functionality like unix "uniq" utility
-
--- A longer description of the package.
-description:      Library provides the functions to find unique and duplicate elements in the list
+version:             0.4.6
 
--- The license under which the package is released.
+synopsis:            It provides the functionality like unix "uniq" utility
+description:         Library provides the functions to find unique and duplicate elements in the list
 license:             BSD3
-
--- The file containing the license text.
 license-file:        LICENSE
-
--- The package author(s).
 author:              Volodymyr Yaschenko
-
--- An email address to which users can send suggestions, bug reports, and
--- patches.
 maintainer:          ualinuxcn@gmail.com
-
 category:            Data
-
 build-type:          Simple
-
--- Extra files to be distributed with the package, such as examples or a
--- README.
--- extra-source-files:
-
--- Constraint on the version of Cabal needed to build this package.
 cabal-version:       >=1.10
 
 source-repository head
-   type:        darcs
-   location:    http://hub.darcs.net/kapral/Unique/
+   type:             darcs
+   location:         http://hub.darcs.net/kapral/Unique/
 
 library
-  -- Modules exported by the library.
   exposed-modules:      Data.List.Unique,
                         Data.List.UniqueStrict,
                         Data.List.UniqueUnsorted
 
-  -- Modules included in this library but not exported.
-  -- other-modules:
-
-  -- LANGUAGE extensions used by modules in this package.
-  -- other-extensions:
-
-  -- Other library packages from which modules are imported.
   build-depends:         base >=4.0 && < 5
                        , extra
                        , containers
                        , hashable
                        , unordered-containers
-  -- Directories containing source files.
-  -- hs-source-dirs:
+  default-language:    Haskell2010
+  ghc-options:         -Wall -O2
 
-  -- Base language which the package is written in.
+
+Test-Suite HspecTest
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      tests
+  main-is:             Main.hs
+  other-modules:       Complex
+                     , IsUnique
+                     , RepeatedBy
+                     , SortUniq
+
+  build-depends:       base >=4.8 && <4.9
+                     , hspec
+                     , containers
+                     , QuickCheck
+                     , Unique
+
   default-language:    Haskell2010
-  ghc-options:         -Wall
+  ghc-options:        -Wall -O2
+                     
diff --git a/tests/Complex.hs b/tests/Complex.hs
new file mode 100644
--- /dev/null
+++ b/tests/Complex.hs
@@ -0,0 +1,26 @@
+module Complex where
+
+import Test.Hspec
+import Test.QuickCheck
+
+import Data.List.Unique
+import Data.List (sort)
+
+
+triplet :: (a -> b) -> (a, a, a) -> (b, b, b)
+triplet f (x, y, z) = (f x, f y, f z)
+
+complexTests :: SpecWith ()
+complexTests =
+  describe "Data.List.Unique.complex" $ do
+  
+  it "complex: should return ([],[],[]) with empty list" $ do
+    complex ( [] :: [Int] ) `shouldBe` ([],[],[])
+
+  it "complex: simple test" $ do
+    complex "This is the test line" `shouldBe` ("This teln","is hte","Tln")
+
+  it "complex: returns the same result as `sortUniq`, `repeated`, `unique` but not sorted" $
+    property $
+    \ xs -> triplet sort ( complex (xs :: String) )
+            == (sortUniq xs, repeated xs, unique xs)
diff --git a/tests/IsUnique.hs b/tests/IsUnique.hs
new file mode 100644
--- /dev/null
+++ b/tests/IsUnique.hs
@@ -0,0 +1,74 @@
+module IsUnique where
+
+import Test.Hspec
+import Test.QuickCheck
+import Control.Exception (evaluate)
+import Data.Maybe (isJust, isNothing)
+
+import Data.List.Unique
+
+isUniqueTests :: SpecWith ()
+isUniqueTests =
+  describe "Data.List.Unique.isUnique" $ do
+  it "isUnique should return Nothing with empty list" $ do
+    isUnique (1 :: Int) [] 
+    `shouldBe`
+      Nothing
+
+  it "isUnique should return Nothing with empty list (quickCheck)" $
+    property $
+    \x -> isNothing $ isUnique (x :: Char) []
+
+  it "isUnique, returns (Just True) when element is unique" $ do
+    isUnique 'a' "foo bar"  `shouldBe` Just True
+
+  it "isUnique , returns (Just False) when list has duplicate of element" $ do
+    isUnique 'o' "foo bar" `shouldBe` Just False
+
+  it "isUnique is a lazy function, 'undefined test'" $ do
+    isUnique 'g' ['g','a','g', undefined ]
+    `shouldBe`
+      Just False
+
+  it "isUnique is a lazy function, 'undefined test'. Generates exeption" $ do
+    evaluate (isUnique 't' ['t', 'd', undefined] )
+    `shouldThrow`
+      errorCall "Prelude.undefined"
+
+  it "isRepeated is a lazy function too, 'undefined test'" $ do
+    isRepeated 'g' ['g','a','g', undefined ]
+    `shouldBe`
+      Just True
+
+  it "isRepeated is reverse function to isUnique" $ do
+    property $
+      \ x xs
+      -> isUnique (x :: Int) xs == fmap not (isRepeated x xs)
+
+  it "isUnique should return (Just ANY) when element is exist in the list" $
+    property $
+    \ ( NonEmpty ls@(x:xs) )
+    -> not (null xs)
+       ==>  isJust (isUnique (x :: Char) ls)
+
+  context "isUnique should return (Just False) when at least two elements are exist in the list" $
+    it "- It checks laziness as well" $
+      property $
+        \ ( NonEmpty ls@(x:xs) )
+        -> not (null xs)
+           ==>  isJust $ isUnique (x :: Char) (ls ++ [x, undefined])
+
+  it "isUnique should return Nothing when element is absent in the list" $
+    property $
+    \ x xs
+    -> notElem x xs
+       ==> isNothing (isUnique (x :: Char) xs)
+      
+  it "isUnique and isRepeated should return Nothing when element is absent in the list" $
+    property $
+    \ x xs
+    -> notElem x xs
+       ==> isNothing (isUnique (x :: Char) xs)
+       &&  isNothing (isRepeated x xs)
+
+
diff --git a/tests/Main.hs b/tests/Main.hs
new file mode 100644
--- /dev/null
+++ b/tests/Main.hs
@@ -0,0 +1,8 @@
+import IsUnique
+import SortUniq
+import RepeatedBy
+import Complex
+import Test.Hspec
+
+main :: IO ()
+main = mapM_ hspec [isUniqueTests, sortUniqTests, repeatedByTests, complexTests]
diff --git a/tests/RepeatedBy.hs b/tests/RepeatedBy.hs
new file mode 100644
--- /dev/null
+++ b/tests/RepeatedBy.hs
@@ -0,0 +1,57 @@
+module RepeatedBy where
+
+import Test.Hspec
+import Test.QuickCheck
+
+import Data.List.Unique
+import Data.List (sort, group)
+
+
+repeatedByTests :: SpecWith ()
+repeatedByTests =
+  describe "Data.List.Unique.repeatedBy,repeated,unique" $ do
+  
+  it "repeatedBy: should return [] with empty list" $ do
+    repeatedBy (>100) ( [] :: [Int] ) `shouldBe` []
+
+  it "repeatedBy: simple test" $ do
+    repeatedBy (>2) "This is the test line" `shouldBe` " eist"
+
+  it "repeatedBy: returns [] when predicate (=< negative) " $
+    property $
+    \x xs -> x < 0
+             ==> null ( repeatedBy (<= x) (xs :: String) )
+
+  it "repeatedBy: removes the duplicated elements like `sortUniq` function when predicate (>= negative)" $
+     property $
+     \ x xs -> x < 0
+               ==> repeatedBy (>= x) (xs :: String) == sortUniq xs
+
+  it "repeatedBy: returns [] when preficate (== 0)" $
+     property $
+     \ xs -> null ( repeatedBy (== 0) (xs :: [Int]) )
+
+  it "repeatedBy: returns sorted result" $
+     property $
+     \x xs ->  x > 0
+              ==> repeatedBy (> x) (xs :: String) == sort (repeatedBy (> x) xs)
+
+  it "repeatedBy: resulted elements should occur only once" $
+    property $
+    \ x xs -> x > 0
+              ==> all (==1) . map length . group $ repeatedBy (> x) ( xs :: String )
+
+  it "unique: simple test" $ do
+    unique  "foo bar" `shouldBe` " abfr"
+
+  it "repeated: simple test" $ do
+    repeated  "foo bar" `shouldBe` "o"
+
+  it "unique: multiple execution should return the same result" $
+    property $
+    \ xs -> unique (xs :: String) == unique (unique xs)
+
+  it "repeated && unique: should return different result on the same non empty list" $
+    property $
+    \ xs -> not (null xs)
+            ==> repeated (xs :: String) /= unique xs
diff --git a/tests/SortUniq.hs b/tests/SortUniq.hs
new file mode 100644
--- /dev/null
+++ b/tests/SortUniq.hs
@@ -0,0 +1,44 @@
+module SortUniq where
+
+import Test.Hspec
+import Test.QuickCheck
+
+import Data.List.Unique
+import Data.List (sort, group)
+import Data.Set (fromList, toList)
+
+
+sortUniqTests :: SpecWith ()
+sortUniqTests =
+  describe "Data.List.Unique.sortUniq" $ do
+  
+  it "sortUniq: should return [] with empty list" $ do
+    sortUniq ( [] :: [Int] ) `shouldBe` []
+
+  it "sortUniq: simple test" $ do
+    sortUniq "foo bar" `shouldBe` " abfor"
+
+  it "sortUniq: multiple execution should return the same result" $
+    property $
+    \ xs -> sortUniq (sortUniq ( xs :: String) ) == sortUniq xs
+
+  it "sortUniq: the result has to be sorted" $
+    property $
+    \ xs -> sortUniq ( xs :: [Int] ) == sort (sortUniq xs)
+
+  it "sortUniq: elements should occur only once" $
+    property $
+    \ ( NonEmpty ls@(x:_) ) -> isUnique (x :: Float) (sortUniq ls) == Just True
+
+  it "sortUniq: elements should occur only once #2" $
+    property $
+    \ xs -> all (==1) . map length . group $ sortUniq ( xs :: [Integer] )
+
+  it "sortUniq: check if it's correct by slow analog function" $
+    property $
+    \ xs -> ( map head . group . sort $ (xs :: String) )
+            == sortUniq xs
+
+  it "sortUniq: check if it's correct by the Faster analog function :)" $
+    property $
+    \ xs -> sortUniq ( xs :: String ) == toList (fromList xs)
