为什么 quickCheck 创建单位列表
why does quickCheck create lists of units
为了乐趣和收益,我尝试了 QuickCheck 测试论文中的以下内容。
prop_revApp xs ys = reverse (xs ++ ys) == reverse xs ++ reverse ys
它通过了,尽管它不应该通过。
我 运行 verboseCheck
并且我看到它只检查单位列表,即:
Passed:
[(),(),(),(),(),(),(),(),(),(),(),(),(),()]
我想知道这是为什么。
我知道我可以通过定义 属性 的类型来修复它,但想知道这是否有必要,或者我遗漏了什么。
prop_revApp
函数非常通用:
*Main> :t prop_revApp
prop_revApp :: Eq a => [a] -> [a] -> Bool
如果您只是在 GHCi 中加载代码,并且 运行 它,是的,确实 属性 通过了:
*Main> quickCheck prop_revApp
+++ OK, passed 100 tests.
这是因为 GHCi 带有一组首选默认值。为方便起见,它会尽量使用最简单的类型。
它并没有比 ()
简单多少,并且由于 ()
有一个 Eq
实例,它选择了那个。
另一方面,如果您实际上尝试编写和编译某些属性,则代码无法编译:
import Test.Framework (defaultMain, testGroup)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.QuickCheck
main :: IO ()
main = defaultMain tests
prop_revApp xs ys = reverse (xs ++ ys) == reverse xs ++ reverse ys
tests = [
testGroup "Example" [
testProperty "prop_revApp" prop_revApp
]
]
如果您尝试 运行 使用 stack test
这些测试,您将收到编译器错误:
test\Spec.hs:11:17: error:
* Ambiguous type variable `a0' arising from a use of `testProperty'
prevents the constraint `(Arbitrary a0)' from being solved.
Probable fix: use a type annotation to specify what `a0' should be.
These potential instances exist:
instance (Arbitrary a, Arbitrary b) => Arbitrary (Either a b)
-- Defined in `Test.QuickCheck.Arbitrary'
instance Arbitrary Ordering
-- Defined in `Test.QuickCheck.Arbitrary'
instance Arbitrary Integer
-- Defined in `Test.QuickCheck.Arbitrary'
...plus 19 others
...plus 61 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the expression: testProperty "prop_revApp" prop_revApp
In the second argument of `testGroup', namely
`[testProperty "prop_revApp" prop_revApp]'
In the expression:
testGroup "Example" [testProperty "prop_revApp" prop_revApp]
|
11 | testProperty "prop_revApp" prop_revApp
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
您必须给 属性 一个更具体的类型;例如
tests = [
testGroup "Example" [
testProperty "prop_revApp" (prop_revApp :: [Int] -> [Int] -> Bool)
]
]
现在测试编译了,但是失败了:
$ stack test
Q56101904-0.1.0.0: test (suite: Q56101904-test)
Example:
prop_revApp: [Failed]
*** Failed! Falsifiable (after 3 tests and 3 shrinks):
[1]
[0]
(used seed -7398729956129639050)
Properties Total
Passed 0 0
Failed 1 1
Total 1 1
Q56101904-0.1.0.0: Test suite Q56101904-test failed
Test suite failure for package Q56101904-0.1.0.0
Q56101904-test: exited with: ExitFailure 1
Logs printed to console
为了乐趣和收益,我尝试了 QuickCheck 测试论文中的以下内容。
prop_revApp xs ys = reverse (xs ++ ys) == reverse xs ++ reverse ys
它通过了,尽管它不应该通过。
我 运行 verboseCheck
并且我看到它只检查单位列表,即:
Passed:
[(),(),(),(),(),(),(),(),(),(),(),(),(),()]
我想知道这是为什么。
我知道我可以通过定义 属性 的类型来修复它,但想知道这是否有必要,或者我遗漏了什么。
prop_revApp
函数非常通用:
*Main> :t prop_revApp
prop_revApp :: Eq a => [a] -> [a] -> Bool
如果您只是在 GHCi 中加载代码,并且 运行 它,是的,确实 属性 通过了:
*Main> quickCheck prop_revApp
+++ OK, passed 100 tests.
这是因为 GHCi 带有一组首选默认值。为方便起见,它会尽量使用最简单的类型。
它并没有比 ()
简单多少,并且由于 ()
有一个 Eq
实例,它选择了那个。
另一方面,如果您实际上尝试编写和编译某些属性,则代码无法编译:
import Test.Framework (defaultMain, testGroup)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.QuickCheck
main :: IO ()
main = defaultMain tests
prop_revApp xs ys = reverse (xs ++ ys) == reverse xs ++ reverse ys
tests = [
testGroup "Example" [
testProperty "prop_revApp" prop_revApp
]
]
如果您尝试 运行 使用 stack test
这些测试,您将收到编译器错误:
test\Spec.hs:11:17: error:
* Ambiguous type variable `a0' arising from a use of `testProperty'
prevents the constraint `(Arbitrary a0)' from being solved.
Probable fix: use a type annotation to specify what `a0' should be.
These potential instances exist:
instance (Arbitrary a, Arbitrary b) => Arbitrary (Either a b)
-- Defined in `Test.QuickCheck.Arbitrary'
instance Arbitrary Ordering
-- Defined in `Test.QuickCheck.Arbitrary'
instance Arbitrary Integer
-- Defined in `Test.QuickCheck.Arbitrary'
...plus 19 others
...plus 61 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the expression: testProperty "prop_revApp" prop_revApp
In the second argument of `testGroup', namely
`[testProperty "prop_revApp" prop_revApp]'
In the expression:
testGroup "Example" [testProperty "prop_revApp" prop_revApp]
|
11 | testProperty "prop_revApp" prop_revApp
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
您必须给 属性 一个更具体的类型;例如
tests = [
testGroup "Example" [
testProperty "prop_revApp" (prop_revApp :: [Int] -> [Int] -> Bool)
]
]
现在测试编译了,但是失败了:
$ stack test
Q56101904-0.1.0.0: test (suite: Q56101904-test)
Example:
prop_revApp: [Failed]
*** Failed! Falsifiable (after 3 tests and 3 shrinks):
[1]
[0]
(used seed -7398729956129639050)
Properties Total
Passed 0 0
Failed 1 1
Total 1 1
Q56101904-0.1.0.0: Test suite Q56101904-test failed
Test suite failure for package Q56101904-0.1.0.0
Q56101904-test: exited with: ExitFailure 1
Logs printed to console