Temporary Files for Testing in Haskell
Just a quick tip as I had to try a couple different ways to get it working.
First off, you’ll need to install the temporary package.
I needed to test parsing an actual file on disk. I still find some difficulty writing good tests that perform IO in Haskell, but this worked well enough.
Buster has a function to parse a YAML config file that looks like:
loadConfig :: FilePath -> IO (Either String Config)
= decodeFileEither
loadConfig
decodeFileEither :: FromJSON a => FilePath -> IO (Either String a)
= decodeHelper (Y.decodeFile fp) >>= either throwIO return decodeFileEither fp
I’ve already thoroughly tested the pure parsing component but I was not completely certain of my implementation of the file one.
Wrapping Specs with Temp Files
Here’s an excerpt from the test suite:
spec :: Spec
= describe "parsing from file" $
spec "parses a full config successfully" $
it $ \path ->
withPreloadedFile fullConfigStr `shouldReturn` Right fullConfig
loadConfig path where fullConfigStr = "....."
= Config { ... }
fullConfig
withPreloadedFile :: ByteString -> (FilePath -> IO a) -> IO a
= withSystemTempFile filenameTemplate callback
withPreloadedFile content action where filenameTemplate = "buster_fixture.yml"
= BS.hPut handle content >> hFlush handle >> action path callback path handle
withSystemTempFile
will open up a file in your system-specific temporary dir (such as /tmp) using the filename template you specify. That file basically gets treated like a prefix, so it may generate a file like buster_fixter.ymlAAA, or something close to it.
Take special note of the flush. You want to ensure the write gets flushed before the test runs or it will appear to be empty.