我有一些测试用例,我在其中启动一个Web服务器进程,然后 运行一些 URL 测试以检查每个函数是否运行正常。
服务器进程启动时间取决于执行它的系统。这是几秒钟的问题,我现在使用 time.sleep(5(。 但老实说,我不是 sleep(( 的忠实粉丝,因为它可能适用于我的系统,但如果测试在服务器需要 6 秒才能启动的系统上运行怎么办......(所以走这条路从来都不是很安全的。 测试将无缘无故地失败。
所以问题是:有没有一种很好的方法来检查这个过程是否真的开始了。
我使用 python 多处理模块 例:
from multiprocessing import Process
import testapp.server
import requests
import testapp.config as cfg
import time
p = Process(target=testapp.server.main)
p.start()
time.sleep(5)
testurl=cfg.server_settings["protocol"] + cfg.server_settings["host"] + ":" +str(cfg.server_settings["port"]) + "/test/12"
r = requests.get(testurl)
p.terminate()
assert int(r.text)==12
因此,最好避免 sleep(( 并真正检查该过程何时开始......
您应该使用is_alive
(文档(,但在您启动进程start()
后,这几乎总是会返回 True。如果你想确保这个过程已经在做一些重要的事情,就无法绕过time.sleep
(至少从这一端来看,看看最后一段的另一个想法(
无论如何,您都可以实现如下is_alive
:
p = Process(target=testapp.server.main)
p.start()
while not p.is_alive():
time.sleep(0.1)
do_something_once_alive()
如您所见,我们仍然需要"睡眠"并再次检查(仅 0.1 秒(,但is_alive
返回True
之前可能不到 5 秒。
如果is_alive
和time.sleep
都不够准确,让你知道这个过程是否真的做了一些特定的事情,如果你也在控制另一个程序,你应该让它举起另一种标志,这样你就知道你很好。
我建议使用连接对象作为参数创建流程(其他同步原语可能有效(,并在子流程中使用send()
方法来通知父流程业务可以继续。在连接对象的父端使用recv()
方法。
import multiprocessing as mp
def worker(conn):
conn.send(0) # argument object must be pickable
# your worker is ready to do work and just signaled it to the parent
out_conn, in_conn = mp.Pipe()
process = mp.Process(target=worker,
args=(out_conn,))
process.start()
in_conn.recv() # Will block until something is received
# worker in child process signaled it is ready. Business can go on