diff --git a/drawille.cabal b/drawille.cabal
--- a/drawille.cabal
+++ b/drawille.cabal
@@ -1,79 +1,102 @@
-Name:                   drawille
-Version:                0.1.0.6
-Category:               System
-Author:                 Pedro Yamada <tacla.yamada@gmail.com>
-Maintainer:             Pedro Yamada <tacla.yamada@gmail.com>
-Copyright:              (c) Pedro Yamada
-License:                GPL-3
-License-File:           LICENSE
-Synopsis:               A port of asciimoo's drawille to haskell
-Homepage:               https://github.com/yamadapc/haskell-drawille
-Description:            A tiny library for drawing with braille.
-Cabal-Version:          >= 1.10
-Build-Type:             Simple
+-- This file has been generated from package.yaml by hpack version 0.14.0.
+--
+-- see: https://github.com/sol/hpack
 
-Flag no-tests
-    Description:        Don't build test suites
-    Default:            False
+name:                   drawille
+version:                0.1.2.0
+synopsis:               A port of asciimoo's drawille to haskell
+description:            A tiny library for drawing with braille.
+category:               System
+homepage:               https://github.com/yamadapc/haskell-drawille#readme
+bug-reports:            https://github.com/yamadapc/haskell-drawille/issues
+author:                 Pedro Yamada <tacla.yamada@gmail.com>
+maintainer:             Pedro Yamada <tacla.yamada@gmail.com>
+copyright:              (c) Pedro Yamada
+license:                GPL-3
+license-file:           LICENSE
+build-type:             Simple
+cabal-version:          >= 1.10
 
-Flag examples
-    Description:        Build examples
-    Default:            False
+source-repository head
+  type: git
+  location: https://github.com/yamadapc/haskell-drawille
 
-Library
-  Default-Language:     Haskell2010
-  HS-Source-Dirs:       src
-  GHC-Options:          -Wall -threaded -O3
-  Exposed-Modules:      System.Drawille
-  Build-Depends:        base >=4 && <5
-                      , containers >=0.5 && <0.6
+flag examples
+  description: Build examples
+  manual: False
+  default: False
 
-Executable senoid
-  Default-Language:     Haskell2010
-  HS-Source-Dirs:       examples
-                      , src
-  Ghc-Options:          -Wall -O3
-  Main-Is:              Senoid.hs
+flag no-tests
+  description: Don't build test suites
+  manual: False
+  default: False
+
+library
+  hs-source-dirs:
+      src
+  build-depends:
+      base >=4 && <5
+    , containers >=0.5 && <0.6
+  exposed-modules:
+      System.Drawille
+  other-modules:
+      Paths_drawille
+  default-language: Haskell2010
+
+executable image2term
+  main-is: Image2Term.hs
+  hs-source-dirs:
+      examples
+    , src
+  ghc-options: -Wall -threaded -O3
   if flag(examples)
-    Build-Depends:        base >=4 && <5
-                        , containers >=0.5 && <0.6
-                        , AC-Angle >=1.0 && <1.1
-    Buildable: True
+    build-depends:
+        base >=4 && <5
+      , containers >=0.5
+      , friday >=0.1 && <0.2
+      , terminal-size >=0.2
+      , vector
   else
-    Buildable: False
+    buildable: False
+  other-modules:
+      Senoid
+      System.Drawille
+  default-language: Haskell2010
 
-Executable image2term
-  Default-Language:     Haskell2010
-  HS-Source-Dirs:       examples
-                      , src
-  Ghc-Options:          -Wall -threaded -O3
-  Main-Is:              Image2Term.hs
+executable senoid
+  main-is: Senoid.hs
+  hs-source-dirs:
+      examples
+    , src
+  ghc-options: -threaded -Wall -O3
   if flag(examples)
-    Build-Depends:        base >=4 && <5
-                        , containers >=0.5
-                        , friday >=0.1 && <0.2
-                        , terminal-size >=0.2
-                        , vector
-    Buildable: True
+    build-depends:
+        base >=4 && <5
+      , containers >=0.5 && <0.6
+      , AC-Angle >=1.0 && <1.1
   else
-    Buildable: False
+    buildable: False
+  other-modules:
+      Image2Term
+      System.Drawille
+  default-language: Haskell2010
 
-Test-Suite spec
-  Type:                 exitcode-stdio-1.0
-  Default-Language:     Haskell2010
-  Hs-Source-Dirs:       src
-                      , test
-  Ghc-Options:          -Wall
-  Main-Is:              Spec.hs
-  if !flag(no-tests)
-    Build-Depends:        base >=4 && <5
-                        , hspec >=1.11 && <2.3
-                        , QuickCheck >=2.6 && <3
-                        , containers >=0.5 && <0.6
-    Buildable: True
+test-suite spec
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  hs-source-dirs:
+      src
+    , test
+  ghc-options: -Wall
+  if !(flag(no-tests))
+    build-depends:
+        base >=4 && <5
+      , hspec >=1.11 && <2.4
+      , QuickCheck >=2.6
+      , containers >=0.5 && <0.6
   else
-    Buildable: False
-
-Source-Repository head
-  Type:                 git
-  Location:             git://github.com/yamadapc/haskell-drawille
+    buildable: False
+  other-modules:
+      System.Drawille
+      DrawilleSpec
+  default-language: Haskell2010
diff --git a/test/DrawilleSpec.hs b/test/DrawilleSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/DrawilleSpec.hs
@@ -0,0 +1,81 @@
+module DrawilleSpec (main, spec) where
+
+import Test.Hspec
+import Test.QuickCheck
+import qualified Data.Map as M
+
+import qualified System.Drawille as D
+
+main :: IO ()
+main = hspec spec
+
+-- ---------------
+-- | 0x01 | 0x08 |
+-- | 0x02 | 0x10 |
+-- | 0x04 | 0x20 |
+-- | 0x40 | 0x80 |
+-- ---------------
+
+spec :: Spec
+spec = do
+  describe "empty" $
+    it "is an empty map of points to ints" $
+      D.empty `shouldBe` M.empty
+
+  describe "set" $ do
+    it "sets nonexistent coordinates" $
+      M.lookup (0, 0) (D.set D.empty (1, 1)) `shouldBe` Just 16
+
+    it "updates existent coordinates" $ do
+      let c = D.set D.empty (1, 1)
+      M.lookup (0, 0) (D.set c (0, 1)) `shouldBe` Just 18
+
+  describe "unset" $ do
+    it "clears existent coordinates" $ do
+      let c = D.set D.empty (1, 1)
+      M.lookup (0, 0) (D.unset c (1, 1)) `shouldBe` Just 0
+
+    it "updates special cases" $ do
+      let c = D.set (D.set D.empty (1, 1)) (0, 0)
+      M.lookup (0, 0) (D.unset c (1, 1)) `shouldBe` Just 1
+
+    it "reverses the `set` operations" $ property unsetSetProp
+
+  describe "toggle" $ do
+    it "sets unset coordinates" $ do
+      let c = D.set D.empty (1, 1)
+      M.lookup (0, 0) (D.toggle c (0, 0)) `shouldBe` Just 17
+
+    it "unsets set coordinates" $ do
+      let c = D.set D.empty (1, 1)
+      M.lookup (0, 0) (D.toggle c (1, 1)) `shouldBe` Just 0
+
+    it "reverses itself" $ property toggleRevProp
+
+  describe "get" $
+    it "gets a coordinates' value" $ do
+      let c = D.set D.empty (1, 1)
+      D.get c (1, 1) `shouldBe` True
+      D.get c (0, 0) `shouldBe` False
+
+  describe "frame" $
+    it "gives back a string representation of canvas" $ do
+      let c = D.set (D.set D.empty (0, 0)) (1, 2)
+      D.frame c `shouldBe` "⠡\n"
+      let d = D.fromList [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]
+      D.frame d `shouldBe` "⡇\n⠃\n"
+
+  describe "fromList" $
+    it "creates a canvas based on a list of tuples" $ do
+      let c = D.set (D.set D.empty (0, 0)) (10, 20)
+      D.fromList [(0, 0), (10, 20)] `shouldBe` c
+
+toggleRevProp :: Positive Int -> Positive Int -> Bool
+toggleRevProp (Positive x) (Positive y) = M.lookup (D.toPs p) c == Just 0
+    where p = (x, y)
+          c = D.toggle (D.toggle D.empty p) p
+
+unsetSetProp :: Positive Int -> Positive Int -> Bool
+unsetSetProp (Positive x) (Positive y) = M.lookup (D.toPs p) c == Just 0
+    where p = (x, y)
+          c = D.unset (D.set D.empty p) p
