首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何正确约束`任意性` UUID-Generation?

如何正确约束`任意性` UUID-Generation?
EN

Stack Overflow用户
提问于 2020-05-12 16:31:52
回答 1查看 112关注 0票数 3

我正在尝试为我的一些类型创建Arbitrary实例,以便在QuickCheck属性测试中使用。我需要随机生成的UUID,其约束是不允许全零(nil) UUIDs即00000000-0000-0000-0000-000000000000。因此,我设置了以下生成器:

代码语言:javascript
复制
nonzeroIdGen :: Gen UUID.UUID
nonzeroIdGen = arbitrary `suchThat` (not . UUID.null)

我在Arbitrary实例中使用它,如下所示:

代码语言:javascript
复制
instance Arbitrary E.EventId where
    arbitrary = do
        maybeEid <- E.mkEventId <$> nonzeroIdGen
        return $ fromJust maybeEid

一般来说,这是不安全的代码;但是对于测试来说,假设有非零UUID,我认为fromJust是正常的。

mkEventId被定义为

代码语言:javascript
复制
mkEventId :: UUID.UUID -> Maybe EventId
mkEventId uid = EventId <$> validateId uid

使用EventIdUUID.UUID进行了新的类型包装,并且

代码语言:javascript
复制
validateId :: UUID.UUID -> Maybe UUID.UUID
validateId uuid = if UUID.null uuid then Nothing else Just uuid

令我惊讶的是,由于上面的代码生成了全零的UUID,我得到了失败的测试。mkEventId中的trace显示以下内容:

代码语言:javascript
复制
00000001-0000-0001-0000-000000000001
Just (EventId {getEventId = 00000001-0000-0001-0000-000000000001})

00000000-0000-0000-0000-000000000000
Nothing
    Create valid Events. FAILED [1]

第一个生成的ID是正常的,第二个是全零的,尽管我在上面生成了nonzeroIdGen生成器。我遗漏了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-12 19:33:47

我通常发现,在这样的情况下,使用newtype定义Arbitrary的实例会更好。下面是我为有效的UUID值创建的一个值:

代码语言:javascript
复制
newtype NonNilUUID = NonNilUUID { getNonNilUUID :: UUID } deriving (Eq, Show)

instance Arbitrary NonNilUUID where
  arbitrary = NonNilUUID <$> arbitrary `suchThat` (/= nil)

然后,您可以从这个实例组合其他Arbitrary实例,就像我在这里对Reservation数据类型所做的那样:

代码语言:javascript
复制
newtype ValidReservation =
  ValidReservation { getValidReservation :: Reservation } deriving (Eq, Show)

instance Arbitrary ValidReservation where
  arbitrary = do
    (NonNilUUID rid) <- arbitrary
    (FutureTime d) <- arbitrary
    n <- arbitrary
    e <- arbitrary
    (QuantityWithinCapacity q) <- arbitrary
    return $ ValidReservation $ Reservation rid d n e q

请注意,模式匹配(NonNilUUID rid) <- arbitraryrid解构为UUID值。

您可能注意到,我还为我的Reservation数据类型创建了一个ValidReservation newtype。I依赖(I consistently do this to avoid orphan instances ),并避免使用QuickCheck依赖来污染我的域模型。(我并不反对QuickCheck,但是特定于测试的功能不属于“生产”代码。)

这里显示的所有代码都是available in context on GitHub

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61747155

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档