Hspec: обнаружение, пользовательский main и передача аргумента в spec

Я пытаюсь использовать hspec-discover наряду с обычаем Main, изготовленный на заказ Main это bracket который создает дескриптор файла, который будет использоваться всеми Spec"S.

Это мое Spec.hs:

{-# OPTIONS_GHC -F -pgmF hspec-discover -optF --module-name=Spec #-}

Это мое Main.hs:

module Main (main) where

import Control.Exception
import System.Posix.IO
import System.Posix.Files
import Test.Hspec
import Spec (spec)

main :: IO ()
main = bracket
  (openFd verybigFile ReadWrite (Just 384) defaultFileFlags)
  (\fd -> closeFd fd >> removeLink verybigFile)
  (\fd -> hspec (spec fd))
    where
      verybigFile = "test/verybigFile"

Для меня spec в отдельном модуле автообнаружения, чтобы принять аргумент дескриптора файла, мне нужно объявить его как

spec :: Fd -> Spec

но hspec-discover требует, чтобы спецификация была объявлена ​​как

spec :: Spec

в противном случае автоматически сгенерированный модуль не компилируется:

test/Spec.hs:8:68:
    Couldn't match type `System.Posix.Types.Fd -> Spec'
                  with `hspec-core-2.1.7:Test.Hspec.Core.Spec.Monad.SpecM () ()'
    Expected type: hspec-core-2.1.7:Test.Hspec.Core.Spec.Monad.SpecWith
                     ()
      Actual type: System.Posix.Types.Fd -> Spec
    In the second argument of `describe', namely `SendfileSpec.spec'
    In the second argument of `postProcessSpec', namely
      `(describe "Sendfile" SendfileSpec.spec)'
    In the expression:
      postProcessSpec
        "test/SendfileSpec.hs" (describe "Sendfile" SendfileSpec.spec)

Итак, как передать аргумент спецификации, не нарушая автообнаружение? Мое воображение смещается в сторону IORefНо идея заставляет меня содрогнуться. Что было бы правильным способом сделать это?

1 ответ

Решение

Совместное использование значений через спецификации файлов в настоящее время не поддерживается с hspec-discover, Но вы все равно можете обмениваться значениями в одном и том же файле спецификации. Следующие работы:

FooSpec.hs:

module FooSpec (spec) where

import           Test.Hspec
import           System.IO

spec :: Spec
spec = beforeAll (openFile "foo.txt" ReadMode) $ afterAll hClose $ do
  describe "hGetLine" $ do
    it "reads a line" $ \h -> do
      hGetLine h `shouldReturn` "foo"

    it "reads an other line" $ \h -> do
      hGetLine h `shouldReturn` "bar"

Spec.hs:

{-# OPTIONS_GHC -F -pgmF hspec-discover #-}

Но учтите, что beforeAll обычно считается запахом кода. Это хорошая практика для использования before вместо этого, если это возможно.

Другие вопросы по тегам