我尝试使用需要睡眠的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 timetest
EDIT2:
似乎表明进程输出的新版本足以中断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
不能依赖于阻止。
答案 0 :(得分:6)
我认为当进程退出时sleep-for
会被中断。
以下测试失败,因为sleep-for
在2秒后中断。
(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次测试中,我们需要3 sleep-for
,因为sleep-for
被中断了2次,
但这很脆弱。所以我写测试如下。这个测试可以通过
如果sleep-for
被中断多次。
我使用float-time
代替current-time
因为current-time
的第二个元素可以包裹arround。
(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)))))
答案 1 :(得分:2)
我刚刚复制到* scratch *并使用ert-run-tests-interactively
运行该测试。我无法重现你的问题。你有一个旧版本的测试在内存中挥之不去吗?
编辑:我在OS X 10.8上使用Emacs 24.2.1
更新:运行更新的代码。一些非常奇怪的事情正在发生。我的跑步中大约有四分之一在进行。
更新:我可以验证@ syohex的答案:添加第二个电话sleep-for
对我有效。
答案 2 :(得分:2)
此错误将在下一个Emacs(25.1?24.6 ??)中修复。请参阅2015年6月的this commit。(我实际上并没有尝试过。)
在修复之前,请使用
(call-process "/usr/bin/sleep" nil nil nil "<seconds>")
而不是'sleep-for'。这很可靠。
答案 3 :(得分:0)
查看https://github.com/rejeep/ert-async.el
然后你可以这样做:
(ert-deftest-async timetest (done)
(call-async-command done))