我正在尝试使用ert设置一些测试,这些测试需要休眠才能使后台进程继续进行。我尝试过使用sleep-for和accept-process-output。两者都不可靠。这里有一个小例子。
此测试仅休眠5秒,然后检查是否至少已过3秒。使用sleep-for,它会立即结束,但会失败。如果shell-command未被注释,则花费预期的5秒并成功!这里发生什么事情?
(ert-deftest timetest ()
(let ((now (cadr (current-time))))
;(shell-command "sleep 5")
(sleep-for 5)
(should (< now (- (cadr (current-time)) 3)))))编辑:
当我测试前面的示例时,我的环境中一定有一些奇怪的东西。这个稍微修改过的示例包含一个后台进程,与我需要测试的进程类似,但失败了。我以交互方式和使用命令对其进行了测试:
emacs --batch -l example.el -f ert-run-tests-batch-and-exit(ert-deftest timetest ()
(let ((now (cadr (current-time))))
(start-process "echo" "*echo*" "echo" "hello world")
(sleep-for 5)
(should (< now (- (cadr (current-time)) 3)))))输出为:
Test timetest condition:
(ert-test-failed
((should
(< now
(- ... 3)))
:form
(< 55177 55174)
:value nil))
FAILED 1/1 timetest
Ran 1 tests, 0 results as expected, 1 unexpected (2013-02-05 09:57:29+0000)
1 unexpected results:
FAILED timetestEDIT2:
新版本似乎表明进程输出足以中断sleep-for
(ert-deftest timetest ()
(let ((now (cadr (current-time))))
(start-process "yes" "*yes*" "yes")
(sleep-for 1) ;; This sleep-for may be interrupted by process *output*
(sleep-for 5) ;; This sleep-for is also interrupted
(should (< now (- (cadr (current-time)) 3)))))EDIT3:
怀着沉重的心情,我发布了另一个版本:
(ert-deftest timetest ()
(let ((now (cadr (current-time)))
(process-connection-type nil))
(start-process "tmp" "*tmp*" "bash" "-c" "sleep 1; echo hi")
(sleep-for 5)
(should (< now (- (cadr (current-time)) 3)))))似乎很明显,不能依赖sleep-for来阻止。
发布于 2013-02-06 09:26:23
我认为当进程退出时,sleep-for会中断。
后续测试失败,2秒后sleep-for中断
(ert-deftest timetest ()
(let ((now (cadr (current-time))))
(start-process "sleep" "*sleep*" "sleep" "2") ;; Fail
(sleep-for 5)
(should (< now (- (cadr (current-time)) 3)))))但是下面的测试通过了,因为sleep-for在4秒后就中断了。
(ert-deftest timetest ()
(let ((now (cadr (current-time))))
(start-process "sleep" "*sleep*" "sleep" "4") ;; Success
(sleep-for 5)
(should (< now (- (cadr (current-time)) 3)))))所以我认为你可以像下面这样写测试
(ert-deftest timetest ()
(let ((now (cadr (current-time))))
(start-process "echo" "*echo*" "echo" "hello world")
(sleep-for 1) ;; This sleep-for may be interrupted by process exited
(sleep-for 5) ;; This sleep-for can sleep 5 seconds
(should (< now (- (cadr (current-time)) 3)))))EDIT1
将process-connection-type设置为nil即可通过第二个测试。(但我不能理解这种行为)
(ert-deftest timetest ()
(let ((now (cadr (current-time)))
(process-connection-type nil))
(start-process "yes" "*yes*" "yes")
(sleep-for 5)
(should (< now (- (cadr (current-time)) 3)))))请参阅document
EDIT2
在第三个测试中,我们需要3个sleep-for,因为sleep-for被中断了2次,但这是脆弱的。因此,我编写了如下测试。如果sleep-for中断次数相同,则可以通过此测试。我使用float-time而不是current-time,因为current-time的第二个元素可能会换行。
(ert-deftest timetest ()
(let ((now (float-time))
(process-connection-type nil))
(start-process "tmp" "*tmp*" "bash" "-c" "sleep 1; echo hi")
(while (< (- (float-time) now) 5)
(sleep-for 1))
(should (< now (- (float-time) 3)))))发布于 2013-02-05 13:33:11
我只是复制到*scratch*中,并使用ert-run-tests-interactively运行该测试。我不能复制你的问题。你是否有一个旧版本的测试在内存中徘徊?
编辑:我在OS X 10.8上使用Emacs 24.2.1
更新:运行更新后的代码。发生了一些非常奇怪的事情。我大约有1/4的跑步是成功的。
更新:我可以验证@syohex的答案:添加第二个调用sleep-for对我有效。
发布于 2013-12-01 10:18:14
此错误将在下一个Emacs (25.1? 24.6??)中修复。请参阅2015年6月的this commit。(不过,我还没有真正尝试过。)
在它得到修复之前,使用
(call-process "/usr/bin/sleep" nil nil nil "<seconds>")而不是“睡眠”。这是可靠的。
在报告修复的original (#15990)和duplicate (#20935)中可以找到错误报告。
https://stackoverflow.com/questions/14698081
复制相似问题