我正在尝试使用需要睡眠的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)))))
Run Code Online (Sandbox Code Playgroud)
编辑:
当我测试前面的例子时,我的环境肯定有些奇怪.这个稍微改变的示例包含一个像我需要测试的后台进程,但失败了.我以交互方式测试它并使用命令:
emacs --batch -l example.el -f ert-run-tests-batch-and-exit
Run Code Online (Sandbox Code Playgroud)
(ert-deftest timetest ()
(let ((now (cadr (current-time))))
(start-process "echo" "*echo*" "echo" "hello world")
(sleep-for 5)
(should (< now (- (cadr (current-time)) 3)))))
Run Code Online (Sandbox Code Playgroud)
输出是:
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
Run Code Online (Sandbox Code Playgroud)
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)))))
Run Code Online (Sandbox Code Playgroud)
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)))))
Run Code Online (Sandbox Code Playgroud)
似乎很清楚,sleep-for不能依靠阻止.
我认为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)))))
Run Code Online (Sandbox Code Playgroud)
但是接下来的测试通过,因为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)))))
Run Code Online (Sandbox Code Playgroud)
所以我认为你可以写下面的测试
(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)))))
Run Code Online (Sandbox Code Playgroud)
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)))))
Run Code Online (Sandbox Code Playgroud)
请看文件
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)))))
Run Code Online (Sandbox Code Playgroud)