I'm trying to get my head around the reason why the test file containing unit-tests which is defined as a module fails when run with stack build --test
.
Say having a simple test module defined from scratch with:
stack new test-module
cd test-module
vim package.yaml # remove "executables" section, add "hspec" as tests dependency
Following "getting started" instructions from Hspec documentation I've modified files such as:
-- file test/Spec.hs
module LibSpec where
import Test.Hspec
import Lib
main :: IO ()
main = hspec $ do
describe "divides" $ do
it "returns True when the first number divides the second" $
2 `divides` 4 `shouldBe` True
-- file src/Lib.hs
module Lib (divides) where
divides :: Integer -> Integer -> Bool
divides d n = rem n d == 0
Running stack build --test
throws the following error:
<no location info>: error:
output was redirected with -o, but no output will be generated
because there is no Main module.
When I comment out the "module definition" line from the test/Spec.hs
file the build succeeds and the unit-test passes:
-- file test/Spec.hs
-- Notice the next line is commented out:
-- module LibSpec where
import Test.Hspec
import Lib
main :: IO ()
main = hspec $ do
describe "divides" $ do
it "returns True when the first number divides the second" $
2 `divides` 4 `shouldBe` True
Is that Hspec related or Stack related? Or maybe am I missing something obvious?
It's part of Haskell the language.
A Haskell program is a collection of modules, one of which, by convention, must be called
Main
and must export the valuemain
.An abbreviated form of module, consisting only of the module body, is permitted. If this is used, the header is assumed to be
module Main(main) where
.
The Haskell 2010 report, section 5 (Modules) https://www.haskell.org/onlinereport/haskell2010/haskellch5.html#x11-980005
See also the cabal documentation, about the configuration that package.yaml
is a proxy for, the field containing the test/executable file:
main-is
: (...) while the name of the file may vary, the module itself must be named Main.
https://www.haskell.org/cabal/users-guide/developing-packages.html#pkg-field-executable-main-is
GHC has an option -main-is MyModule.mymain
to override this behavior (documented in the GHC user guide).