chore: run doctests in parallel

Runs the doctests much faster, which is potentially useful in
combination with postgrest-watch for local development.

This implies that doctests run on compiled code, not in a GHCi session,
which has some implications:
- Only exported functions can be tested.
- Imports need to be made explicit in doctests themselves.

On the flipside, this would allow us to potentially include doctest
results in code coverage, I believe.

This change is a requirement to vendor hasql, which otherwise breaks the
existing doctests: hasql contains a .hsc file, which *needs* to be
compiled - not interpreted - to make the tests work.
This commit is contained in:
Wolfgang Walther
2026-07-14 06:55:32 +00:00
parent aa6c19ebda
commit 44e15e4e9b
13 changed files with 55 additions and 31 deletions
+1 -1
View File
@@ -63,7 +63,7 @@ jobs:
- name: Run doctests - name: Run doctests
if: always() if: always()
run: postgrest-test-doctests run: nix-shell --run postgrest-test-doctests
- name: Check the spec tests for idempotence - name: Check the spec tests for idempotence
if: always() if: always()
+1
View File
@@ -30,3 +30,4 @@ gen_private.json
.pytest_cache .pytest_cache
.ruff_cache .ruff_cache
postgrest-module-graph.png postgrest-module-graph.png
.ghc.environment.*
+3
View File
@@ -2,3 +2,6 @@ packages: postgrest.cabal
tests: true tests: true
allow-newer: allow-newer:
hasql:postgresql-libpq hasql:postgresql-libpq
-- https://github.com/martijnbastiaan/doctest-parallel/blob/main/example/README.md#cabalproject
write-ghc-environment-files: always
-2
View File
@@ -55,8 +55,6 @@ let
withEnv = postgrest.env; withEnv = postgrest.env;
} }
'' ''
# This makes nix-env -iA tests.doctests.bin work.
export NIX_GHC=${postgrest.env.NIX_GHC}
${cabal-install}/bin/cabal v2-run ${devCabalOptions} test:doctests ${cabal-install}/bin/cabal v2-run ${devCabalOptions} test:doctests
''; '';
+1 -4
View File
@@ -352,14 +352,11 @@ test-suite observability
test-suite doctests test-suite doctests
type: exitcode-stdio-1.0 type: exitcode-stdio-1.0
default-language: Haskell2010 default-language: Haskell2010
default-extensions: OverloadedStrings
NoImplicitPrelude
hs-source-dirs: test/doc hs-source-dirs: test/doc
main-is: Main.hs main-is: Main.hs
build-depends: base >= 4.9 && < 4.22 build-depends: base >= 4.9 && < 4.22
, doctest >= 0.8 , doctest-parallel >= 0.4
, postgrest , postgrest
, pretty-simple , pretty-simple
, protolude >= 0.3.1 && < 0.4
ghc-options: -threaded -O0 -Werror -Wall -fwarn-identities ghc-options: -threaded -O0 -Werror -Wall -fwarn-identities
-fno-spec-constr -optP-Wno-nonportable-include-path -fno-spec-constr -optP-Wno-nonportable-include-path
+4
View File
@@ -21,6 +21,7 @@ module PostgREST.ApiRequest.Preferences
, shouldCount , shouldCount
, shouldExplainCount , shouldExplainCount
, prefAppliedHeader , prefAppliedHeader
, toHeaderValue
) where ) where
import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Char8 as BS
@@ -34,7 +35,10 @@ import Protolude
-- $setup -- $setup
-- Setup for doctests -- Setup for doctests
-- >>> :set -XStandaloneDeriving
-- >>> import Text.Pretty.Simple (pPrint) -- >>> import Text.Pretty.Simple (pPrint)
-- >>> import qualified Data.Set as S
-- >>> import Protolude
-- >>> deriving instance Show PreferResolution -- >>> deriving instance Show PreferResolution
-- >>> deriving instance Show PreferRepresentation -- >>> deriving instance Show PreferRepresentation
-- >>> deriving instance Show PreferCount -- >>> deriving instance Show PreferCount
+15
View File
@@ -9,7 +9,18 @@
module PostgREST.ApiRequest.QueryParams module PostgREST.ApiRequest.QueryParams
( parse ( parse
, QueryParams(..) , QueryParams(..)
, pFieldForest
, pFieldName
, pFieldSelect
, pJsonPath
, pLogicTree
, pOpExpr
, pOrder
, pRelationSelect
, pRequestFilter
, pRequestRange , pRequestRange
, pSingleVal
, pSpreadRelationSelect
) where ) where
import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Char8 as BS
@@ -62,6 +73,10 @@ import PostgREST.Error (QPError (..))
import Protolude hiding (Sum, try) import Protolude hiding (Sum, try)
-- $setup
-- >>> import qualified Text.ParserCombinators.Parsec as P
-- >>> import Protolude hiding (Sum, try)
data QueryParams = data QueryParams =
QueryParams QueryParams
{ qsCanonical :: ByteString { qsCanonical :: ByteString
+1
View File
@@ -597,6 +597,7 @@ pgConnString conn | uriDesignator `T.isPrefixOf` conn || shortUriDesignator `T.i
-- | Adds a `fallback_application_name` value to the connection string. This allows querying the PostgREST version on pg_stat_activity. -- | Adds a `fallback_application_name` value to the connection string. This allows querying the PostgREST version on pg_stat_activity.
-- --
-- >>> import Protolude
-- >>> let ver = "11.1.0 (5a04ec7)"::ByteString -- >>> let ver = "11.1.0 (5a04ec7)"::ByteString
-- >>> let strangeVer = "11'1&0@#$%,.:\"[]{}?+^()=asdfqwer"::ByteString -- >>> let strangeVer = "11'1&0@#$%,.:\"[]{}?+^()=asdfqwer"::ByteString
-- --
+8
View File
@@ -19,6 +19,8 @@ module PostgREST.Error
, JwtClaimsError(..) , JwtClaimsError(..)
, errorPayload , errorPayload
, status , status
, noRelBetweenHint
, noRpcHint
) where ) where
import qualified Data.Aeson as JSON import qualified Data.Aeson as JSON
@@ -57,6 +59,12 @@ import PostgREST.Error.Types
import Protolude import Protolude
-- $setup
-- >>> import qualified Data.HashMap.Strict as HM
-- >>> import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..))
-- >>> import PostgREST.SchemaCache.Relationship (Relationship (..))
-- >>> import PostgREST.SchemaCache.Routine (Routine (..), RoutineParam (..))
-- | Encode Error to ByteString -- | Encode Error to ByteString
errorPayload :: (ErrorBody a, ErrorHeaders a) => Verbosity -> a -> LByteString errorPayload :: (ErrorBody a, ErrorHeaders a) => Verbosity -> a -> LByteString
errorPayload verb = JSON.encode . toJsonPgrstError verb errorPayload verb = JSON.encode . toJsonPgrstError verb
+4
View File
@@ -9,6 +9,7 @@ module PostgREST.MediaType
, toContentType , toContentType
, toMime , toMime
, decodeMediaType , decodeMediaType
, tokenizeMediaType
) where ) where
import qualified Data.Aeson as JSON import qualified Data.Aeson as JSON
@@ -22,6 +23,9 @@ import Network.HTTP.Types.Header (Header, hContentType)
import Protolude import Protolude
-- $setup
-- >>> import qualified Text.ParserCombinators.Parsec as P
-- | Enumeration of currently supported media types -- | Enumeration of currently supported media types
data MediaType data MediaType
= MTApplicationJSON = MTApplicationJSON
+10
View File
@@ -24,6 +24,7 @@ module PostgREST.Plan
, InfoPlan(..) , InfoPlan(..)
, CrudPlan(..) , CrudPlan(..)
, legacyWarnings , legacyWarnings
, addNullEmbedFilters
) where ) where
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
@@ -87,7 +88,16 @@ import Protolude hiding (from)
-- $setup -- $setup
-- Setup for doctests -- Setup for doctests
-- >>> :set -XDuplicateRecordFields
-- >>> import Data.Ranged.Ranges (fullRange) -- >>> import Data.Ranged.Ranges (fullRange)
-- >>> import Data.Tree (Tree (..))
-- >>> import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..))
-- >>> import PostgREST.ApiRequest.Types
-- >>> import PostgREST.Plan.CallPlan
-- >>> import PostgREST.Plan.MutatePlan
-- >>> import PostgREST.Plan.ReadPlan as ReadPlan
-- >>> import PostgREST.Plan.Types
-- >>> import Protolude
-- Plan for reading or writing to the db -- Plan for reading or writing to the db
data CrudPlan data CrudPlan
+3
View File
@@ -8,6 +8,9 @@ import qualified Network.HTTP.Types as HTTP
import Numeric (showFFloat) import Numeric (showFFloat)
import Protolude import Protolude
-- $setup
-- >>> import Protolude
-- | ServerTiming represents the timing data for a request, in seconds. -- | ServerTiming represents the timing data for a request, in seconds.
data ServerTiming = data ServerTiming =
ServerTiming ServerTiming
+4 -24
View File
@@ -1,27 +1,7 @@
module Main (main) where module Main where
import Test.DocTest (doctest)
import Protolude
import System.Environment (getArgs)
import Test.DocTest (mainFromCabal)
main :: IO () main :: IO ()
main = main = mainFromCabal "postgrest" =<< getArgs
doctest
[ "-XOverloadedStrings"
, "-XNoImplicitPrelude"
, "-XStandaloneDeriving"
, "-XDuplicateRecordFields"
, "-isrc"
, "src/PostgREST/ApiRequest/Preferences.hs"
, "src/PostgREST/ApiRequest/QueryParams.hs"
, "src/PostgREST/Config.hs"
, "src/PostgREST/Error.hs"
, "src/PostgREST/MediaType.hs"
, "src/PostgREST/Network.hs"
, "src/PostgREST/Plan.hs"
, "src/PostgREST/Query/SqlFragment.hs"
, "src/PostgREST/Response.hs"
, "src/PostgREST/Response/Performance.hs"
, "src/PostgREST/SchemaCache/Identifiers.hs"
]