首页 > 解决方案 > 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 经验/理解能力 - 我可以看到xMVar,它以某种方式填充了测试结果,但正如我所说,我无法理解细节。但我真的需要知道,不仅是为什么我的测试失败了,而且为什么这个特定x的值Nothing对我来说是这样的,以及这对测试意味着什么。我真的很感激能以我能理解的方式解释这一点的答案。

标签: haskellquickcheckservant

解决方案


据我所知,您可以在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 个失败


推荐阅读