Search code examples
haskellcabalhspec

Cabal test producing errors for Haskell


My Main.hs file takes in commandline arguments:

module Main (toLowerStr, Result(..), grade, main) where

...

grade :: [String] -> String -> String -> (Bool, Result, [Highlight])
    grade dictWords correctAnswer studentAnswer =
            ...

...

main :: IO ()
main = do
        args <- getArgs
        dict <- readFile $ args !! 0
        ...

Which works fine, except when I try to test. My testing file is

module Testing where

import Main
import Test.Hspec

main :: IO ()
main = do
        dict <- readFile "dict.txt"
        let dictWords = map toLowerStr $ lines dict
        hspec $ do
        describe "Validate passing answers" $ do
                it "Match should be verified exactly" $ do
                        grade dictWords "house" "house"
                              `shouldBe` (True, Perfect, [])

Yet when I run cabal test it still gives me

Preprocessing test suite 'tests' for grade-0.1.0.0...
[2 of 2] Compiling Testing          ( src/HSpecTests.hs, dist/build/tests/tests-tmp/Testing.o )
Linking dist/build/tests/tests ...
Running 1 test suites...
Test suite tests: RUNNING...
tests: Prelude.(!!): index too large

Test suite tests: FAIL

I'm pretty sure it's failing because of the calls to args in Main.main, because the executable itself works fine, and I don't see !! being used anywhere else.

How do I get tests to run?

EDIT: Used pattern matching in Main.hs:

main :: IO ()
main = do
        [filename, correctString, studentString] <- getArgs
        ...

and the error is now

[1 of 2] Compiling Main             ( src/Main.hs, dist/build/tests/tests-tmp/Main.o )
Linking dist/build/tests/tests ...
Running 1 test suites...
Test suite tests: RUNNING...
tests: user error (Pattern match failure in do expression at src/Main.hs:141:9-48)
Test suite tests: FAIL

EDIT 2: My entire grade.cabal file

-- Initial grade.cabal generated by cabal init.  For further documentation,
--  see http://haskell.org/cabal/users-guide/

name:                grade
version:             0.1.0.0
-- synopsis:            
-- description:         
license-file:        LICENSE
author:              Amos Ng <[email protected]>
maintainer:          Amos Ng <[email protected]>
-- copyright:           
category:            Language
build-type:          Simple
cabal-version:       >=1.8

executable grade
  main-is:             Main.hs
  -- other-modules:       
  build-depends:       base, split ==0.2.*
  hs-source-dirs:      src

test-suite tests
  ghc-options:         -Wall
  type: exitcode-stdio-1.0
  main-is:             HSpecTests.hs
  other-modules:       Main
  build-depends:       base, split ==0.2.*, hspec ==1.11.*
  hs-source-dirs:      src

Solution

  • GHC will always use as the entry point the function named main out of the module named Main. Since HSpecTests.hs is the Testing module, not the Main module, its main is completely ignored, instead favoring the main from the Main module. You should break your logic out of the Main module, leaving the Main module as a command-line stub. Then you’ll want to exclude that from the test build, and change module Testing to module Main in HSpecTests.hs.