我正在学习使用HSpec和QuickCheck。例如,我正在实现来自维基百科:扩展的欧几里德算法的伪代码。您可以在github找到用于实现测试代码的项目。
我特别想知道有两种做法:
a>0 && b>0的效率很低。我最感兴趣的是什么是一个很好的实践来确认两种算法产生相同的结果。
module EuclidSpec ( spec )
where
import Test.Hspec
import Test.Hspec.Core.QuickCheck
import Test.QuickCheck
import Lib
spec :: Spec
spec = do
describe "Trivial" $ do
it "trivial example 99 1" $
let trivial = extendedEuclid 99 1
in trivial `shouldBe` (EuclidRes 1 (0) 1)
it "trivial example 99 99" $
let trivial = extendedEuclid 99 99
in trivial `shouldBe` (EuclidRes 99 (0) 1)
describe "Examples" $ do
it "explanation example 99 78" $
let wikiExample = extendedEuclid 99 78
in wikiExample `shouldBe` (EuclidRes 3 (-11) 14)
it "explanation example flipped 78 99" $
let wikiExample = extendedEuclid 78 99
in wikiExample `shouldBe` (EuclidRes 3 14 (-11) )
it "explanation example 99 78" $
let wikiExample = extendedEuclid 240 46
in wikiExample `shouldBe` (EuclidRes 2 (-9) 47)
describe "properties" $ do
it "both numbers divisible a%gcd == 0, b%gcd ==0" $ property $
prop_divisible
it "bezout a*s+b*t = gcd" $ property $
prop_bezout
it "recursive and iterative algorithm have same result" $ property $
prop_same_as_recursive
prop_divisible a b = a>0 && b>0 ==> a `mod` d ==0 && b `mod`d == 0
where EuclidRes d s t = extendedEuclid a b
prop_bezout a b = a>0 && b>0 ==> a*s + b*t == d
where EuclidRes d s t = extendedEuclid a b
prop_same_as_recursive a b = a>0 && b>0 ==> extendedEuclid a b == extendedEuclid' a b发布于 2020-06-30 12:15:43
啊,一个好的Spec。我已经有一段时间没有使用Hspec了,但是您的测试似乎是合理的。所以,首先:well完成了!
但是,有一点我们应该修复,您已经自己识别了它:属性测试。
创建任何类型的数字,然后检查它是否为正数是一个麻烦,因为一半的数字将被每个候选人丢弃。但是,由于Hspec使用QuickCheck,所以我们只能使用Positive生成正数:
prop_divisible (Positive a) (Positive b) = a `mod` d == 0 && b `mod`d == 0
where EuclidRes d s t = extendedEuclid a b除此之外,没有比这更客观的改进。
然而,有一些个人我会使用在我自己的规格。
中的let … in …绑定
考虑下面的规范
describe "Trivial" $ do
it "trivial example 99 1" $
let trivial = extendedEuclid 99 1
in trivial `shouldBe` (EuclidRes 1 (0) 1)如果我想理解规范,我必须阅读第一行,记住trivial的值(并且它在调用extendedEuclid后没有被更改),并在下一行中提供它。
如果我改写
describe "Trivial" $ do
it "trivial example 99 1" $
extendedEuclid 99 1 `shouldBe` (EuclidRes 1 (0) 1)
-- or
it "trivial example 99 99" $
extendedEuclid 99 99
`shouldBe` (EuclidRes 99 (0) 1)我立即看到extendedEucild正在接受测试。这也是符合官方风格,其中let … in …绑定根本不使用。
您可以使用来自Test.Hspec.QuickCheck的D22而不是it "..." $ property $ ...:
import Test.Hspec.QuickCheck
...
describe "properties" $ do
prop "both numbers divisible a%gcd == 0, b%gcd ==0" $
prop_divisible
...https://codereview.stackexchange.com/questions/244774
复制相似问题