3

我正在使用Thrift编写服务,需要应用一些测试以确保它按预期运行/响应。要做到这一点,最稳健的方法似乎是使用该unittest模块。

我想直接在单元测试的setUp方法中以“测试”模式启动服务(在特定的“测试”端口上启动,使用“测试”数据等),但此时调用serve()块等待连接。

启动服务的最佳方法是什么,以便可以执行测试并使用该tearDown方法干净地关闭服务?

4

3 回答 3

7

提供的“完全隔离”unittest非常适用于单元测试(它的设计目的),但不一定适用于集成测试——我看到重用unittest这些测试的吸引力,我自己这样做是为了利用我们拥有的特殊测试运行器&c周围,​​但是,意识到它是一种适合unittest用于集成测试的力量,我尝试通过编码而不是编写单元测试来进行补偿。

当我必须在集成测试中生成服务器时,我倾向于在模块的开头,在一个单独的进程中进行生成——通过subprocess,或者通过其他适合你的安装的方式,如果你想在一个单独的环境中运行它节点或其他任何东西 - 并向atexit注册终止代码,当我的测试模块全部完成时,该代码将向该服务器发送终止请求。这不像单元测试所要求的那样“完全分离”,但我发现它对于集成测试来说已经足够好了,并且分摊了启动和初始化服务器的开销,这在多个测试中确实可能非常高。

即使您热衷于使用setUpand tearDown,我仍然建议您使用单独的进程(和单独的节点,如果您在“持续构建农场”等中有很多人的话)。正如@Ned 的回答所暗示的那样,在同一进程中使用不同的线程让我觉得有风险——可能很容易在服务器和测试之间产生不需要的交互,隐藏一些错误或导致其他错误。

如果我理解正确,您不仅要在同一进程上运行服务器,而且还要在与测试相同的线程中运行服务器,这对我来说绝对是个坏主意-当然它会阻止一切,除非服务器编码确实非常特别!-)

于 2010-03-06T17:49:58.903 回答
1

您可以创建一个上下文管理器来在服务器在后台运行时启动您的测试。

if __name__ == '__main__':
    with background_server():
        print('Server loaded, launching the tests...')
        unittest.main(exit=False)

我用于的代码background_server

@contextlib.contextmanager
def background_server():
    # Launching the server
    pid_server = os.fork()
    if not pid_server:  # Child code
        launch_server()  # Blocking call (until signal.SIGINT)
        print('Interuption detected, server closed...')
        sys.exit()  # Closing the process

    # HACK: Wait for the server to be launched
    while True:
        try:
            requests.get("http://localhost:5000/", timeout=0.5)
            break
        except requests.exceptions.ConnectionError:
            pass
        time.sleep(0.3)

    try:
        yield
    finally:
        # Closing the server
        os.kill(pid_server, signal.SIGINT)
于 2017-02-01T23:24:05.327 回答
0

如果serve()阻塞,那么你最好的选择是产生一个线程setUp来调用serve()。然后你必须弄清楚如何在tearDown方法中停止 Thrift。

于 2010-03-06T14:31:31.513 回答