问题描述
背景
使用堆栈及其预设文件Spec.hs
,据我所知您需要导入以下测试框架模块才能执行正确的测试:
import qualified Test.Framework as TF
import qualified Test.Framework.Providers.HUnit as FHU
import qualified Test.Framework.Providers.QuickCheck2 as QC2
import qualified Test.HUnit as HU
import qualified Test.QuickCheck as QC
因此,您还需要将添加依赖项添加到package.yaml
文件中,如下所示:
tests:
XYZ-test:
main: Spec.hs
source-dirs: test
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- Test4
- test-framework
- test-framework-hunit
- test-framework-quickcheck2
- HUnit
- QuickCheck
如果您导入要测试的主题(称为 MyModule
)并在 Spec.hs
中为该模块实现测试用例,则您无法测试模块内部使用的函数({{1} }).
要测试内部函数,您可以在模块 (MyModule
) 内实现测试并导出测试。
MyModule
但是您还需要导入测试框架(至少,Test.Framework、Test.Framework.Providers.HUnit 和 Test.HUnit)并且还需要向 ({{1} })。因此,package.yaml 将如下所示:
module MyModule
(
...
testCases,-- exported test cases
-- fun1 -- internal function not exported
) where
...
import qualified Test.Framework as TF
import qualified Test.Framework.Providers.HUnit as FHU
import qualified Test.HUnit as HU
fun1 :: [Bool] -> Integer -- internal function not exported
fun1 ...
testCases =
(FHU.testCase "MyModule.fun1 #1" ((fun1 []) HU.@?= 0)) :
(FHU.testCase "MyModule.fun1 #2" ((fun1 [True]) HU.@?= 0)) :
(FHU.testCase "MyModule.fun1 #2" ((fun1 [True,True]) HU.@?= 2)) :
[]
问题
是否有更精简的方法来导出模块 MyModule
的单元测试?
解决方法
添加数据类型以包装每个测试用例的绑定。理想情况下,在一个模块(例如 TestCaseWrap)中,将其重用于其他具有要测试的内部功能的模块。
...
dependencies:
- ...
- test-framework
- test-framework-hunit
- HUnit
library:
source-dirs: src
...
注意:数据结构 MyModule
支持断言,并且可以为概率快速测试进行扩展。
在模块 {-| wraps a test case
* prefix: tcw,TCW
* for an assertion
* to hold/evaluate the test case name
* to hold/evaluate the actual value of test case
* to hold/evaluate the expected value of test case
-}
data TestCaseWrap a =
TestAssertion {
-- | name of the test case,needed to reference and find the test case if failed
rsName :: String,-- | function and actual value evaluated by test case,respectively
rxActual :: a,-- | expected value evaluated by test case,respectively
rxExpected :: a }
中导入 TestCaseWrap
以定义数据类型 MyModule
。用所有测试用例填充一个数组(例如 TestCaseWrap
)。
TestCaseWrap
实现一个函数,将包装好的测试信息转换为 testCasesWrap
。同样,理想情况下,在模块中(例如 TestCaseUnwrap)。
module MyModule
(
...
lTestCasesWrap
) where
import qualified TestCaseWrap as TCW
...
fun1 :: [Bool] -> Integer
fun1 ...
testCasesWrap :: [TCW.TestCaseWrap Integer]
testCasesWrap =
(TCW.TestAssertion "MyModule.fun1 #1" (fun1 []) 0) :
(TCW.TestAssertion "MyModule.fun1 #2" (fun1 [True]) 0) :
(TCW.TestAssertion "MyModule.fun1 #3" (fun1 [True,True]) 2) :
[]
像这样实现 Spec.hs:
Test
...它会像这样执行:
module TestCaseUnwrap
(
testCaseFromTestCaseWrap,testCaseFromTestCaseWrapList
) where
import qualified TestCaseWrap as TCW
import qualified Test.Framework as TF
import qualified Test.Framework.Providers.HUnit as FHU
import qualified Test.HUnit as HU
testCaseFromTestCaseWrap :: (Eq a,Show a) => (TCW.TestCaseWrap a) -> TF.Test
testCaseFromTestCaseWrap (TCW.TestAssertion sName xActual xExpected) = FHU.testCase sName (xActual HU.@?= xExpected)
testCaseFromTestCaseWrapList :: (Eq a,Show a) => [TCW.TestCaseWrap a] -> [TF.Test]
testCaseFromTestCaseWrapList ltcwA = fmap testCaseFromTestCaseWrap ltcwA