packages feed

hspec-pg-transact 0.1.0.2 → 0.1.0.3

raw patch · 5 files changed

+153/−24 lines, 5 filesdep +hspec-coredep +hspec-pg-transactnew-uploaderPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: hspec-core, hspec-pg-transact

API changes (from Hackage documentation)

+ Test.Hspec.DB: describeDBWithConfig :: Config -> (Connection -> IO ()) -> String -> SpecWith TestDB -> Spec
+ Test.Hspec.DB: setupDBWithConfig :: Config -> (Connection -> IO ()) -> IO (Either StartError TestDB)
+ Test.Hspec.DB: wrapCallback :: (Connection -> IO ()) -> DB -> IO TestDB
- Test.Hspec.DB: setupDB :: (Connection -> IO ()) -> IO TestDB
+ Test.Hspec.DB: setupDB :: (Connection -> IO ()) -> IO (Either StartError TestDB)

Files

README.md view
@@ -1,1 +1,27 @@-# hspec-pg-transact+# hspec-pg-transact [![CI](https://github.com/jfischoff/pg-transact-hspec/actions/workflows/ci.yml/badge.svg)](https://github.com/jfischoff/pg-transact-hspec/actions/workflows/ci.yml)++Helpers for creating database tests with hspec and pg-transact++hspec-pg-transact utilizes tmp-postgres to automatically and connect to a+temporary instance of postgres on a random port.++ ```haskell+describeDB migrate "Query" $+  itDB "work" $ do+    execute_ [sql|+      INSERT INTO things+      VALUES (‘me’) |]+    query_ [sql|+      SELECT name+        FROM things |]+      `shouldReturn` [Only "me"]+ ```++In the example above describeDB wraps describe with a beforeAll hook for+creating a db and a afterAll hook for stopping a db.++Tests can be written with itDB which is wrapper around it that uses the passed+in TestDB to run a db transaction automatically for the test.++The libary also provides a few other functions for more fine grained control+over running transactions in tests.
hspec-pg-transact.cabal view
@@ -1,5 +1,5 @@ name:                hspec-pg-transact-version:             0.1.0.2+version:             0.1.0.3 synopsis: Helpers for creating database tests with hspec and pg-transact description:  Helpers for creating database tests with hspec and pg-transact@@ -28,7 +28,7 @@ license-file:        LICENSE author:              Jonathan Fischoff maintainer:          jonathangfischoff@gmail.com-copyright:           2017 Jonathan Fischoff+copyright:           2021 Jonathan Fischoff category:            Web build-type:          Simple extra-source-files:  README.md@@ -45,8 +45,26 @@                , bytestring                , text                , resource-pool-  default-language:    Haskell2010+  default-language: Haskell2010   ghc-options: -Wall -Wno-unused-do-bind++test-suite test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  other-modules:+      Hspec.DBSpec+  hs-source-dirs:+      test+  build-depends:+      base >= 4.7 && < 5+    , hspec-pg-transact+    , pg-transact+    , postgresql-simple+    , hspec+    , hspec-core+    , tmp-postgres+  default-language: Haskell2010+  ghc-options: -Wall -Wno-unused-do-bind -threaded -rtsopts -with-rtsopts=-N  source-repository head   type:     git
src/Test/Hspec/DB.hs view
@@ -22,43 +22,50 @@ The libary also provides a few other functions for more fine grained control over running transactions in tests.  -}-{-# LANGUAGE RecordWildCards #-}+ module Test.Hspec.DB where-import           Control.Exception+ import           Control.Monad-import qualified Data.ByteString.Char8        as BSC import           Data.Pool-import qualified Database.Postgres.Temp       as Temp import           Database.PostgreSQL.Simple import           Database.PostgreSQL.Transact+import qualified Database.Postgres.Temp       as Temp import           Test.Hspec  data TestDB = TestDB-  { tempDB     :: Temp.DB+  { tempDB :: Temp.DB   -- ^ Handle for temporary @postgres@ process-  , pool :: Pool Connection+  , pool   :: Pool Connection   -- ^ Pool of 50 connections to the temporary @postgres@   }  -- | Start a temporary @postgres@ process and create a pool of connections to it-setupDB :: (Connection -> IO ()) -> IO TestDB-setupDB migrate = do-  tempDB     <- either throwIO return =<< Temp.startAndLogToTmp []-  putStrLn $ Temp.connectionString tempDB-  pool <- createPool-    (connectPostgreSQL (BSC.pack $ Temp.connectionString tempDB))+setupDB :: (Connection -> IO ()) -> IO (Either Temp.StartError TestDB)+setupDB = setupDBWithConfig Temp.defaultConfig++-- | Start a temporary @postgres@ process using the provided configuration+setupDBWithConfig :: Temp.Config+  -> (Connection -> IO ())+  -> IO (Either Temp.StartError TestDB)+setupDBWithConfig c f =+  traverse (wrapCallback f) =<< Temp.startConfig c++wrapCallback :: (Connection -> IO ()) -> Temp.DB -> IO TestDB+wrapCallback f d = do+  p <- createPool+    (connectPostgreSQL $ Temp.toConnectionString d)     close     1     100000000     50-  withResource pool migrate-  return TestDB {..}+  withResource p f+  pure $ TestDB d p  -- | Drop all the connections and shutdown the @postgres@ process teardownDB :: TestDB -> IO ()-teardownDB TestDB {..} = do-  destroyAllResources pool-  void $ Temp.stop tempDB+teardownDB (TestDB d p) = do+  destroyAllResources p+  void $ Temp.stop d  -- | Run an 'IO' action with a connection from the pool withPool :: TestDB -> (Connection -> IO a) -> IO a@@ -78,6 +85,10 @@ itDB :: String -> DB a -> SpecWith TestDB itDB msg action = it msg $ void . withDB action +-- | Wraps 'describeDBWithConfig' using the default configuration+describeDB :: (Connection -> IO ()) -> String -> SpecWith TestDB -> Spec+describeDB = describeDBWithConfig Temp.defaultConfig+ -- | Wraps 'describe' with a -- -- @@@ -91,6 +102,11 @@ -- @ -- -- hook for stopping a db.-describeDB :: (Connection -> IO ()) -> String -> SpecWith TestDB -> Spec-describeDB migrate str =-  beforeAll (setupDB migrate) . afterAll teardownDB . describe str+describeDBWithConfig :: Temp.Config -> (Connection -> IO ()) -> String -> SpecWith TestDB -> Spec+describeDBWithConfig c f s =+  beforeAll (catch =<< setupDBWithConfig c f) . afterAll teardownDB . describe s+  where+    catch :: Either Temp.StartError TestDB -> IO TestDB+    catch r = case r of+      Left x   -> error (show x)+      Right db -> pure db
+ test/Hspec/DBSpec.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE QuasiQuotes      #-}+{-# LANGUAGE TypeApplications #-}+{-# OPTIONS_GHC -Wno-deferred-type-errors #-}++module Hspec.DBSpec where++import           Control.Monad.IO.Class           (MonadIO (liftIO))+import           Data.Functor                     (void)+import           Data.Monoid                      (Last (Last))+import           Database.PostgreSQL.Simple       (Only (..))+import           Database.PostgreSQL.Simple.SqlQQ (sql)+import           Database.PostgreSQL.Transact     (DBT, execute, execute_,+                                                   query_, runDBTSerializable)+import           Database.Postgres.Temp           (Config (port, postgresConfig),+                                                   ProcessConfig (stdIn, stdOut),+                                                   defaultConfig)+import           System.IO                        (Handle)+import           Test.Hspec                       (SpecWith, shouldBe)+import           Test.Hspec.Core.Spec             (Spec)+import           Test.Hspec.DB                    (TestDB, describeDB,+                                                   describeDBWithConfig, itDB)++defaultSpec :: Spec+defaultSpec =+  describeDB (runDBTSerializable migrate) "with default config" test++customSpec :: Handle -> Handle -> Spec+customSpec i o =+  describeDBWithConfig+    ( defaultConfig+        { postgresConfig =+            (postgresConfig defaultConfig)+              { stdIn = Last $ Just i,+                stdOut = Last $ Just o+              }+        , port = Last $ Just $ Just 8999+        }+    )+    (runDBTSerializable migrate)+    "with custom config"+    test++migrate :: DBT IO ()+migrate = void $ execute_ [sql| CREATE TABLE things (n VARCHAR NOT NULL) |]++test :: SpecWith TestDB+test =+  itDB "basic insert/select" $ do+    execute [sql| INSERT INTO things (n) VALUES (?) |] (Only name)+    name' <- query_ [sql| SELECT n FROM things |]+    liftIO $ name' `shouldBe` [Only name]+  where+    name = "dupont"
+ test/Spec.hs view
@@ -0,0 +1,16 @@+module Main where++import qualified Hspec.DBSpec+import           System.IO+import           Test.Hspec   (Spec, describe, hspec)++main :: IO ()+main = do+  withFile "/tmp/pgto.log" AppendMode $+    hspec . spec stdin++spec :: Handle -> Handle -> Spec+spec i o = do+  describe "pg-transact-hspec" $ do+    Hspec.DBSpec.defaultSpec+    Hspec.DBSpec.customSpec i o