【问题标题】:Unit testing __main__.py单元测试__main__.py
【发布时间】:2018-08-30 22:46:48
【问题描述】:

我有一个 Python 包(Python 3.6,如果它有所不同的话),我设计为以 'python -m package arguments' 和 I' 运行想为 __main__.py 模块编写单元测试。我特别想验证它是否正确设置了退出代码。是否可以使用 runpy.run_module 执行我的 __main__.py 并测试退出代码?如果是这样,我如何检索退出代码?

更清楚地说,我的 __main__.py 模块非常简单。它只是调用一个已经过广泛单元测试的函数。但是当我最初编写 __main__.py 时,我忘记将该函数的结果传递给 exit(),所以我希望在单元测试中模拟主函数以确保正确设置退出代码。我的单元测试看起来像:

@patch('my_module.__main__.my_main', return_value=2)
def test_rc2(self, _):
    """Test that rc 2 is the exit code."""
    sys.argv = ['arg0', 'arg1', 'arg2', …]
    runpy.run_module('my_module')
    self.assertEqual(mod_rc, 2)

我的问题是,我如何才能得到我在这里写的“mod_rc”?

谢谢。

【问题讨论】:

  • 你能告诉我们你到目前为止做了什么吗?请将您的代码添加到您的问题中
  • 并不是 Stack Overflow 上的每个问题都必须与特定代码相关。这个问题有足够的细节来确定足够的答案,并且只问一个问题。因此,我建议重新打开它。

标签: python python-unittest runpy


【解决方案1】:

Misko Hevery 之前说过(我相信是在 Clean Code Talks: Don't Look for Things 但我可能错了)他不知道如何有效地对主要方法进行单元测试,所以他的解决方案是让它们变得如此简单以至于你可以证明如果您假设他们调用的(经过单元测试的)代码的正确性,它们在逻辑上就可以工作。

例如,如果您有一个离散的、经过测试的单元来解析命令行参数;做实际工作的图书馆;以及一个离散的、经过测试的单元,用于将完成的工作渲染为输出,然后一个按顺序调用所有这三个的 main 方法肯定会起作用。

使用该架构,您基本上可以只进行一项大型系统测试,该测试预计会产生除“默认”输出之外的其他内容,并且它会崩溃(因为您连接不正确)或正常工作(因为它是正确接线,所有单个部件都可以工作)。


在这一点上,我放弃所有假装知道我在说什么。几乎可以肯定有更好的方法来做到这一点,但坦率地说,你可以写一个 shell 脚本:

python -m package args
test $? -eq [expected exit code]

这将退出错误iff您的程序输出不正确,TravisCI 或类似的将视为构建失败。

【讨论】:

  • 谢谢。自从你写这篇文章以来,我已经澄清了我的问题。我希望能够运行带有一些模拟模块的代码,因此从 shell 进行测试并不能完全满足我的要求。
【解决方案2】:

__main__.py 仍然受制于正常的__main__ 全局行为——也就是说,你可以像这样实现你的__main__.py

def main():
  # Your stuff

if __name__ == "__main__":
  main()

然后您就可以在您喜欢的任何测试框架中使用您的__main__ 进行测试

from your_package.__main__ import main

顺便说一句,如果您使用的是argparse,您可能会想要:

def main(arg_strings=None):
  # …
  args = parser.parse_args(arg_strings)
  # …

if __name__ == "__main__":
  main()

然后您可以简单地覆盖单元测试中的 arg 字符串

from your_package.__main__ import main

def test_main():
  assert main(["x", "y", "z"]) == …

或您的测试框架中的类似习语。

【讨论】:

    【解决方案3】:

    使用 pytest,我能够做到:

    import mypkgname.__main__ as rtmain

    其中 mypkgname 是您将应用命名为包/模块的名称。然后正常运行 pytest 即可。我希望这可以帮助其他一些可怜的人。

    【讨论】:

      猜你喜欢
      • 2017-05-15
      • 2011-05-01
      • 2019-07-19
      • 2015-09-28
      • 1970-01-01
      • 1970-01-01
      • 2017-12-12
      • 1970-01-01
      相关资源
      最近更新 更多