如何对clojure.core.async go宏进行单元测试? [英] How do I unit test clojure.core.async go macros?

查看:33
本文介绍了如何对clojure.core.async go宏进行单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用core.async go宏编写单元测试.如下这样天真地编写测试,似乎无法执行go块中的代码.

I'm trying to write unit tests when using core.async go macros. Writing the test naively, as follows, appears that the code inside the go blocks doesn't get executed.

(ns app.core-test
  (:require [clojure.test :refer :all]
            [clojure.core.async :as async]))

(deftest test1 []
  (let [chan (async/chan)]
    (async/go
     (is (= (async/<! chan) "Hello")))
    (async/go
     (async/>! chan "Hello"))))

我设法完成了以下工作,但操作非常笨拙.

I've managed to get the following working, but it's extremely hacky.

(deftest test1 []
  (let [result (async/chan)
        chan (async/chan)]
    (async/go
     (is (= (async/<! chan) "Hello"))
     (async/>! result true))
    (async/go
     (async/>! chan "Hello"))
    (async/alts!! [result (async/timeout 10000)])))

关于如何正确执行此操作的任何建议?

Any suggestions as how I can do this properly?

推荐答案

您的测试正在完成,然后失败.如果我入睡然后使它失败,则会更可靠地发生这种情况:

your test is finishing, and then failing. This happens more reliably if I put a sleep in and then make it fail:

user> (deftest test1 []
        (async/<!!
         (let [chan (async/chan)]
           (async/go
             (async/go
               (async/<! (async/timeout 1000))
               (is (= (async/<! chan) "WRONG")))
             (async/go
               (async/>! chan "Hello"))))))
#'user/test1
user> (clojure.test/run-tests)

Testing user

Ran 1 tests containing 0 assertions.
0 failures, 0 errors.
{:test 1, :pass 0, :fail 0, :error 0, :type :summary}
user> 
FAIL in (test1) (form-init8563497779572341831.clj:5)
expected: (= (async/<! chan) "WRONG")
  actual: (not (= "Hello" "WRONG"))

在这里我们可以看到它报告没有任何故障,然后打印出故障消息.我们可以通过明确协调测试的结束并完成动作来解决此问题,就像core.async中的大多数解决方案一样,再添加一个chan.

here we can see it report that nothing fails, then it prints the failure message. We can fix this by explicitly coordinating the end of the test and that action finishing by, like most solutions in core.async, adding one more chan.

user> (deftest test1 []
        (async/<!!
         (let [all-done-chan (async/chan)
               chan (async/chan)]
           (async/go
             (async/go
               (async/<! (async/timeout 1000))
               (is (= (async/<! chan) "WRONG"))
               (async/close! all-done-chan ))
             (async/go
               (async/>! chan "Hello"))
             (async/<! all-done-chan)))))
#'user/test1
user> (clojure.test/run-tests)

Testing user

FAIL in (test1) (form-init8563497779572341831.clj:6)
expected: (= (async/<! chan) "WRONG")
  actual: (not (= "Hello" "WRONG"))

Ran 1 tests containing 1 assertions.
1 failures, 0 errors.
{:test 1, :pass 0, :fail 1, :error 0, :type :summary}

与使用alt的解决方案等效.我认为您的解决方案不是hackey.使用异步代码,即使您有意识地决定忽略结果,也总是需要注意事情的完成时间.

Which is equivalent to your solution using alts. I don't think your solution is hackey. With asynchronous code it's always required to pay attention to when things finish, even if you conciously decide to ignore the result.

这篇关于如何对clojure.core.async go宏进行单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆