为GitHub自动评分器实现Tasty-HUnit IO测试遇hDuplicateTo导出错误
解决IO函数测试的hDuplicateTo未导出问题及完整测试代码
问题分析
- hDuplicateTo未导出:该函数属于GHC内部模块
GHC.IO.Handle,而非System.IO的默认导出列表,因此需要显式导入。 - 原测试逻辑错误:
- 试图向只读的
stdin写入内容会触发IO错误 - 仅提供一行输入,但
countLetters需要三次输入,与预期结果不匹配 - 使用
/dev/null无法提供测试所需的输入内容
- 试图向只读的
完整测试代码
首先确保你的项目依赖包含tasty、tasty-hunit、directory和temporary,在cabal文件中添加:
build-depends: base >= 4.14 && < 5, tasty >= 1.4, tasty-hunit >= 0.10, directory >= 1.3, temporary >= 1.3
测试代码文件:
import Test.Tasty import Test.Tasty.HUnit import System.IO import GHC.IO.Handle (hDuplicateTo, hDuplicate) import System.Directory (removeFile) import System.IO.Temp (writeSystemTempFile) -- 目标函数(可根据实际情况调整导入) countLetters :: IO [Int] countLetters = do putStr "First entry: " x <- getLine putStr "Second entry: " y <- getLine putStr "Third entry: " z <- getLine return [length x, length y, length z] test_countLetters :: TestTree test_countLetters = testCase "test_countLetters" $ do -- 保存原始stdin句柄,测试后恢复避免影响其他测试 originalStdin <- hDuplicate stdin -- 创建临时文件并写入三次测试输入 tempFile <- writeSystemTempFile "count_letters_input" "Haskell\nIs\nFun\n" -- 打开临时文件的读句柄 inputHandle <- openFile tempFile ReadMode -- 将stdin重定向到临时文件读句柄 hDuplicateTo inputHandle stdin -- 执行目标函数 result <- countLetters -- 恢复原始stdin hDuplicateTo originalStdin stdin -- 清理资源 hClose inputHandle removeFile tempFile -- 断言结果是否符合预期 assertEqual "Count letters" [7,2,3] result main :: IO () main = defaultMain $ testGroup "IO Function Tests" [ test_countLetters ]
代码说明
- 使用临时文件提供测试输入,确保跨平台兼容性
- 保存并恢复原始
stdin,避免测试影响后续代码执行 - 显式导入
GHC.IO.Handle中的hDuplicateTo解决导出问题 - 提供与预期结果匹配的三次输入(
Haskell、Is、Fun),确保逻辑正确性
内容的提问来源于stack exchange,提问作者Emily Miller
相关产品推荐
相关产品推荐

