haskell - Servant Quickcheck - 您如何查看导致测试失败的路由?
问题描述
我正在用 Servant 构建一个 API,它似乎工作得很好。根据最佳实践,我正在为它编写一些测试,遵循此处的官方指南。但我在使用 Servant-Quickcheck 的部分苦苦挣扎。
我正在尝试使用它来测试我的 API 没有给出任何 500 错误,如下所示:
quickCheckSpec :: Spec
quickCheckSpec = describe "QuickCheck global tests for public API -" $ do
it "API never gives 500 error" $
withServantServer publicAPI (return server) $ \burl ->
serverSatisfies publicAPI burl args (not500 <%> mempty)
但不幸的是,测试失败了。这让我很惊讶,因为我在手动测试时没有遇到过这样的错误——但是嘿,这就是我们进行自动化测试的原因,对吧?尤其是像 QuickCheck 这样的工具,据我所知,它应该在您可能不认为手动测试的“边缘情况”上归零。(这实际上是我第一次以任何形式使用 QuickCheck。)
问题在于,除非您知道失败的原因,否则测试失败是没有用的。而这正是 Servant-QuickCheck 似乎不想告诉我的。我得到的关于测试失败的唯一输出是:
API never gives 500 error FAILED [1]
Failures:
src\\Servant\\QuickCheck\\Internal\\QuickCheck.hs:146:11:
1) QuickCheck global tests for public API - API never gives 500 error
Nothing
To rerun use: --match "/QuickCheck global tests for public API -/API never gives 500 error/"
Randomized with seed 1712537046
Finished in 10.8513 seconds
4 examples, 1 failure
(之前运行了一些单元测试,都通过了 - 10 秒并不是上面测试的全部!)
这相当令人困惑,因为如您所见,没有任何迹象表明失败是如何发生的。由于它正在测试一个 API,并且据我所知,它会随机选择有效的路由进行测试,它应该告诉我它在哪个路由上遇到了 500 错误。然而,正如你所看到的,那里什么也没有。
(我正在使用 Stack btw 开发项目,在上面说的下面一点Logs printed to console
,所以我不相信我遗漏了任何埋在某处可以启发我的日志文件。我找不到任何在我的.stack-work
文件夹中。)
我什至更改了我的字段args
,以便将chatty
字段设置为True
,但我仍然只得到上述内容。
我得到的唯一与 QuickCheck 无关的线索是我的 API 使用 Persistent 并将数据库查询记录到终端,因此我可以看到已运行的查询——我可以反过来将其与路由相关联. 但是我并不特别相信这一点,因为运行显示的查询的路由肯定在手动测试中工作。(而且它失败时并不总是相同的查询。)还有一些简单的路由不查询数据库,所以失败不一定与打印的最后一个数据库查询有关(尽管不用说,我'已经手动测试了这些路线,他们很好)。
我什至想知道问题是否可能不是 QuickCheck 连续多次访问我的本地主机服务器以至于它根本无法应对并出错,但在这种情况下,我希望这是一个常见问题,评论说在教程中。(并且数据库日志输出表明它实际上总是在第一次“命中”时失败。)
无论如何,这只是猜测,我意识到,我的 API 可能无法通过测试由我自己来决定,因为我认为分享我的实际 API 的任何细节都无关紧要。
我真正要问的是:为什么不告诉我测试了哪些路线,哪些路线通过/失败了,以便我至少确切地知道要调查哪些路线?有什么方法可以让 Servant-Quickcheck 向我显示这些信息?
对此的任何答案将不胜感激。
更多信息:我已经尝试过以下@MarkusBarthlen 的建议,但它没有给我更多信息。但是,它确实指出Nothing
您可以在我的控制台输出中看到的可能是其中的关键,因为在 Markus 的示例中,他获得了一个Just
保存请求信息的值。查看失败消息中引用的源文件的第 146 行,显然x
那里显然是一个Maybe
值。但我无法弄清楚它实际上是什么类型,以及它Nothing
在我的情况下的意义是什么。不幸的是,代码超出了我自己的 Haskell 经验/理解能力 - 我可以看到x
从MVar
,它以某种方式填充了测试结果,但正如我所说,我无法理解细节。但我真的需要知道,不仅是为什么我的测试失败了,而且为什么这个特定x
的值Nothing
对我来说是这样的,以及这对测试意味着什么。我真的很感激能以我能理解的方式解释这一点的答案。
解决方案
据我所知,您可以在https://github.com/haskell-servant/servant-quickcheck/blob/master/src/Servant/QuickCheck/Internal/Predicates.hs 中编写一个 RequestPredicate,例如 notLongerThan。
我用它测试过
not200b :: RequestPredicate
not200b = RequestPredicate $ \req mgr -> do
resp <- httpLbs req mgr
when (responseStatus resp == status200) $ throw $ PredicateFailure "not200b" (Just req) resp
return []
产生的响应
失败:
src/Servant/QuickCheck/Internal/QuickCheck.hs:146:11: 1) 公共 API 的 QuickCheck 全局测试 - API 从不给出 200 失败:只是谓词失败 谓词:not200b 请求:方法:“GET” 路径:/users 标题:正文:响应:状态代码:200 标头:“传输编码”:“分块”“日期”:“2019 年 11 月 22 日星期五 21:32:07 GMT”“服务器”:“Warp/3.2.28”“内容-类型": "application/json;charset=utf-8" 正文: [{"userId":1,"userFirstName":"Isaac","userLastName":"Newton"},{"userId":2,"userFirstName":"Albert","userLastName":"Einstein"}]
重新运行使用:--match "/QuickCheck global tests for public API -/API never give 200/"
随机种子 1026627332
在 0.0226 秒内完成 1 个示例,1 个失败
推荐阅读
- global-variables - 使用路由代理创建多个流时,如何存储用户变量?
- numpy - 在 Julia 中从 python 替代 np.meshgrid()?
- python - 单独的csv列,而一行单元格具有不同数量的元素
- sql - VBA和SQL如何根据excel中的范围选择特定值?
- c# - 如何在 C# 中从 Windows 服务调用 Winform 方法
- javascript - 脚本文件外部的 JS 访问方法
- flowable - 有没有办法使用可流动的java代码或任何动态方式设置任务的跳过表达式来设置任务的跳过表达式
- python - Python如何以相反的顺序打印数字输出?
- windows - 外部命令提示符中的命令有效,但不适用于 VS Code 内部命令提示符
- java - 如何停止将我的 DatabaseHelper 测试添加到应用程序的实际数据库中?