我在哪里定义任意实例?
Where do I define Arbitrary instances?
我不知道在哪里为我的数据类型定义 Arbitrary
实例。如果我把它 放在 包中,那么包就不必将 QuickCheck
作为依赖项。如果我把它 放在 测试中,那么其他包就不能使用这个实例。如果我把它放在一个单独的 test-utils 包中,那么测试 also 必须放在一个单独的包中,所以它是一个孤立实例并且 also stack test --coverage
不起作用。
还有哪些其他选择?
我通常会选择单独的包选项 — 但我不使用 stack test --coverage
。感谢您向我介绍它!
(编辑:我可能会这样做,然后仅对 运行 stack test --coverage --flag thepackage:arbitrary
使用测试标志选项,这样其他人就不必处理这些标志了。)
可能也值得在 stack
问题跟踪器上提出 --coverage
问题,因为在这种情况下覆盖率检查会起作用。
您要求其他选项 - 最好的可能是测试标志。
一个测试标志
可以在您的 cabal 文件中定义一个标志(默认为 false),如果选择该标志,它将只构建具有您的 QuickCheck 依赖项的模块。
将需要的代码放在目录arbitrary
中(例如)。然后将以下等效内容添加到 package.yaml
(第一个片段)或 the-library.cabal
(第二个片段)文件的相关部分:
flags:
arbitrary:
description: Compile with arbitrary instances
default: false
manual: true
library:
⁝
when:
- condition: flag(arbitrary)
dependencies:
- QuickCheck
source-dirs:
- arbitrary
flag arbitrary
description: Compile with arbitrary instances
manual: True
default: False
library
⁝
if flag(arbitrary)
hs-source-dirs:
arbitrary
build-depends:
QuickCheck
然后,想要使用这些实例的软件包应该在它们的 stack.yaml
(第 1 个)或 cabal.project
(第 2 个)文件中添加以下内容:
flag:
the-library:
arbitrary: true
constraints: the-library +arbitrary
但是有一个小问题……目前该库无法仅在其测试套件中依赖 +arbitrary
版本,除非它也定义了这样的标志。这可能是一个值得付出的代价。
注意:我还没有测试下游包装。
Ivan Milenovic's blog 作为初始资源很有用。
DerivingVia/Generic 个实例
可能还有另一种可能,现在GHC 8.6已经发布,DerivingVia
。 Blöndal, Löh & Scott (2018) 中有一个针对 Arbitrary
个实例的案例研究。
您将创建新类型包装器,并为这些新类型实施 Arbitrary
。
它并没有像现在这样完全避免问题。但是您可以为这些新类型实现 Generic
,使使用 generic-arbitrary
派生的实例与您想要的相匹配。
可能还有一些其他的选择。特别是,QuickCheck
的依赖性实际上并没有那么重。还有其他测试库。另外,请注意,已经有一些关于将类似 Arbitrary
的类型类分离到独立库中的讨论。
我也建议使用内部库,但这不允许其他包使用您的实例。
我不知道在哪里为我的数据类型定义 Arbitrary
实例。如果我把它 放在 包中,那么包就不必将 QuickCheck
作为依赖项。如果我把它 放在 测试中,那么其他包就不能使用这个实例。如果我把它放在一个单独的 test-utils 包中,那么测试 also 必须放在一个单独的包中,所以它是一个孤立实例并且 also stack test --coverage
不起作用。
还有哪些其他选择?
我通常会选择单独的包选项 — 但我不使用 stack test --coverage
。感谢您向我介绍它!
(编辑:我可能会这样做,然后仅对 运行 stack test --coverage --flag thepackage:arbitrary
使用测试标志选项,这样其他人就不必处理这些标志了。)
可能也值得在 stack
问题跟踪器上提出 --coverage
问题,因为在这种情况下覆盖率检查会起作用。
您要求其他选项 - 最好的可能是测试标志。
一个测试标志
可以在您的 cabal 文件中定义一个标志(默认为 false),如果选择该标志,它将只构建具有您的 QuickCheck 依赖项的模块。
将需要的代码放在目录arbitrary
中(例如)。然后将以下等效内容添加到 package.yaml
(第一个片段)或 the-library.cabal
(第二个片段)文件的相关部分:
flags:
arbitrary:
description: Compile with arbitrary instances
default: false
manual: true
library:
⁝
when:
- condition: flag(arbitrary)
dependencies:
- QuickCheck
source-dirs:
- arbitrary
flag arbitrary
description: Compile with arbitrary instances
manual: True
default: False
library
⁝
if flag(arbitrary)
hs-source-dirs:
arbitrary
build-depends:
QuickCheck
然后,想要使用这些实例的软件包应该在它们的 stack.yaml
(第 1 个)或 cabal.project
(第 2 个)文件中添加以下内容:
flag:
the-library:
arbitrary: true
constraints: the-library +arbitrary
但是有一个小问题……目前该库无法仅在其测试套件中依赖 +arbitrary
版本,除非它也定义了这样的标志。这可能是一个值得付出的代价。
注意:我还没有测试下游包装。
Ivan Milenovic's blog 作为初始资源很有用。
DerivingVia/Generic 个实例
可能还有另一种可能,现在GHC 8.6已经发布,DerivingVia
。 Blöndal, Löh & Scott (2018) 中有一个针对 Arbitrary
个实例的案例研究。
您将创建新类型包装器,并为这些新类型实施 Arbitrary
。
它并没有像现在这样完全避免问题。但是您可以为这些新类型实现 Generic
,使使用 generic-arbitrary
派生的实例与您想要的相匹配。
可能还有一些其他的选择。特别是,QuickCheck
的依赖性实际上并没有那么重。还有其他测试库。另外,请注意,已经有一些关于将类似 Arbitrary
的类型类分离到独立库中的讨论。
我也建议使用内部库,但这不允许其他包使用您的实例。