Определенные hspec тесты, вызванные со стеком, выдают ошибку, когда тестовый файл определен как модуль

Я пытаюсь понять причину, по которой тестовый файл, содержащий модульные тесты, который определен как модуль, не работает при запуске с stack build --test.

Скажем, с помощью простого тестового модуля, определенного с нуля:

stack new test-module
cd test-module

vim package.yaml # remove "executables" section, add "hspec" as tests dependency

Следуя инструкциям "начало работы" из документации Hspec, я изменил такие файлы, как:

Шаг 1: Опишите желаемое поведение

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

Шаг 2: Напишите немного кода

-- file src/Lib.hs

module Lib (divides) where

divides :: Integer -> Integer -> Bool
divides d n = rem n d == 0

Запуск stack build --test выдает следующую ошибку:

<no location info>: error:
    output was redirected with -o, but no output will be generated
because there is no Main module.

Когда я комментирую строку «определение модуля» из файла test/Spec.hs, сборка завершается успешно, и модульный тест проходит:

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

Это связано с Hspec или со стеком? Или, может быть, я упускаю что-то очевидное?


person mjarosie    schedule 20.11.2019    source источник


Ответы (1)


Это часть языка Haskell.

Программа на Haskell представляет собой набор модулей, один из которых по соглашению должен называться Main и должен экспортировать значение main.

Допускается сокращенная форма модуля, состоящая только из тела модуля. Если это используется, предполагается, что заголовок будет module Main(main) where.


Отчет Haskell 2010, раздел 5 (Модули) https://www.haskell.org/onlinereport/haskell2010/haskellch5.html#x11-980005


См. также документацию Cabal, о конфигурации, для которой package.yaml является прокси, поле, содержащее тестовый/исполняемый файл:

main-is: (...) хотя имя файла может быть разным, сам модуль должен называться Main.


https://www.haskell.org/cabal/users-guide/developing-packages.html#pkg-field-executable-main-is


В GHC есть опция -main-is MyModule.mymain для переопределения этого поведения (описано в руководстве пользователя GHC).

person Li-yao Xia    schedule 20.11.2019
comment
Я только что перепроверил - когда вместо запуска stack build --test я помещаю src/Lib.hs файл и test/Spec.hs файл в верхний каталог и, следуя руководству Hspec, я вызываю stack exec -- runhaskell Spec.hs С определением модуля (без комментариев), он не выдает ошибку. Теперь еще больше запутанно :P - person mjarosie; 21.11.2019
comment
Это очень сбивает с толку. - person Li-yao Xia; 21.11.2019
comment
Возможно ли, что runhaskell (который, насколько я понимаю, является псевдонимом runghc и является способом запуска программ на Haskell без их компиляции) извлекает все, что называется модулем, и каким-то образом перезаписывает им параметр main-is? - person mjarosie; 21.11.2019
comment
Да, безусловно. - person Li-yao Xia; 21.11.2019