,因为我想尝试QuickCheck为自己在一个较大的项目,这是一个很好的锻炼我。 QuickCheck是一个库,可以在生成的测试用例的属性中自动测试你的函数。你也可以创建你自己的发电机,但是我没有在这里做。
首先,我安装了QuickCheck cabal install QuickCheck
。我通过import Test.QuickCheck
导入的模块,然后我定义的属性:
prop_substring xs ys = substring xs ys == substring' xs ys
这个属性,如果给快速检查,将生成参数xs
和ys
为String
。它将检查该属性是否为True
,在这种情况下应该发生,因为substring
函数当然应返回相同的结果。
要快速检查功能,我使用了verboseCheck prop_substring
。这将针对100个生成的测试用例进行检查。第一个结果是:
Failed:
""
""
*** Failed! Falsifiable (after 1 test):
""
""
所以:不,这两个功能是不一样的。这是因为在你的函数,substring
,你不测试,这是一个字符串,如果第一个参数是空的基本情况,所以我加了一行:
substring [] ys = True
然后,我又进行了测试。以下是最后两个例子生成的测试用例:
Passed:
"C8Q<r6\[email protected]\v_\195\DC1\170"
"E\219\DLE"
Passed:
"$ I\SYN\232\164\EOT9\182Ldah\255\173\DC2-B\DC2\SUBuF|\235iQ\236l\vS129\237x?}\187\229C\SYNUVUc/3bO7mE\ESCHB7V\DEL\FSM\EM\202^\162!\GS\DC3\\\nja\201\ESC\ENQOi"
"&?\USx>{\147\DC4g\171\EM\240Ha%\"C\ETX \SI\FS=\DC2\214V%H"
+++ OK, passed 100 tests.
但是,这只是100个测试,更多呢?您可以使用其他功能并使用其他参数。让我们尝试使用100.000个测试案例:
*Substring> quickCheckWith stdArgs { maxSuccess = 100000 } prop_substring
+++ OK, passed 100000 tests.
所以是的,似乎这两个函数都提供了相同的结果!虽然有两个缺点:第一个是QuickCheck将不会生成两个字符串,其中包含substring
。由于它随机生成String
,它更可能会生成两个完全不同的String
。这可以通过创建你自己的发电机来解决。第二个缺点是QuickCheck没有给你一个正式的证明。
第一个可以用属性进行分析。如果我们改变prop_substring
到:
prop_substring xs ys =
collect (substring xs ys) $
(substring xs ys == substring' xs ys)
然后我们收集到的结果,所以我们可以看到的结果是什么比例。为100。000这是:
*Substring> quickCheckWith stdArgs { maxSuccess = 100000 } prop_substring
+++ OK, passed 100000 tests:
94% False
5% True
因此,大致5000返回True
。您还可以生成xs
和ys
并给substring
函数参数xs
和xs++ys
或xs
和ys++xs
以仅测试True
个案。两个选项都通过100.000个测试,所以我们几乎可以假设这两个函数都给出相同的结果。
有关QuickCheck的更多信息有点outdated manual。例如,您可以告诉QuickCheck您需要一定数量的True
测试用例,而不是成功测试用例的总数(当两个substring
函数导致False
时都会成功)。
您的解决方案有一个小错误,'substring [] []'是错误的。当你考虑修复时,它不会比其他解决方案短得多。他们可以使用'prefix(x:xs)(y:ys)'而不是'((x == y)&&(前缀xs ys))',这会更好一些。 –
谢谢Willem,很好的回答。这是真正令人愉快的脑锻炼:) – user1875444