hspec defined tests invoked with stack throw an error when test file is defined as a module
Asked Answered
R

1

5

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:

Step 1: Describe your desired behavior

-- 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

Step 2: Write some code

-- 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?

Romilda answered 20/11, 2019 at 0:7 Comment(0)
O
3

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 value main.

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).

Oletaoletha answered 20/11, 2019 at 1:53 Comment(4)
I just double-checked - when instead of running stack build --test I put src/Lib.hs file and test/Spec.hs file in the top directory and following the Hspec tutorial I invoke stack exec -- runhaskell Spec.hs WITH the module definition (uncommented) it doesn't throw an error. Now it's even more confusing : PRomilda
That IS very confusing.Oletaoletha
Is that possible that runhaskell (which as far as I understand is an alias of runghc and is a way to run Haskell programs without compiling them) extracts whatever the module is called and somehow overwrites the main-is option with it?Romilda
Yes definitely.Oletaoletha

© 2022 - 2024 — McMap. All rights reserved.