【问题标题】:how to test python file with pytest having if __name__ == '__main__': with arguments如何使用 pytest 测试 python 文件 if __name__ == '__main__': with arguments
【发布时间】:2022-01-11 03:13:17
【问题描述】:

我想用 pytest 测试一个包含 if __name__ == '__main__': 的 python 文件 它还解析了参数。 代码是这样的:

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Execute job.')

    parser.add_argument('--env', required=True, choices=['qa', 'staging', 'prod'])

    args = parser.parse_args()

    # some logic

这里的限制是我不能添加main() 方法并将逻辑包装在if __name__ == '__main__': 中并从那里运行它! 该代码是旧代码,无法更改!

我想用 pytest 对此进行测试,我想知道如何在我的测试中运行这个带有一些参数的 python 文件?

【问题讨论】:

  • 如果您的测试发现错误怎么办?你不能解决它吗?
  • 这能回答你的问题吗? stackoverflow.com/q/18668947/3141234
  • 然后将缺少main 函数视为错误,并修复它。
  • 你也许可以用 with open("script.py") as f: exec(f.read()) 做点什么,但我宁愿修复文件也不要弄乱exec
  • 这回答了你的问题——stackoverflow.com/a/51736889/13261176

标签: python pytest


【解决方案1】:

命令行参数是一种输入/输出机制,与其他任何机制一样。关键是将其隔离在“边界层”中,并且让您的主程序不直接依赖它们。

在这种情况下,不要让您的程序直接访问sys.argv(本质上是一个全局变量),而是让您的程序被包装在一个“入口点”函数(例如“main”)中,该函数将 args 作为显式参数。

如果您不向ArgumentParser.parse_args 传递任何参数,则默认为您访问sys.argv。相反,只需传递您的 args 参数即可。

它可能看起来像:

def main(args):
    # some logic
    pass

if __name__ == '__main__':
    main(sys.arv)

您的单元测试可以调用这个入口点函数并传入他们想要的任何参数:

def test_main_does_foo_when_bar():
   result = main(["bar"])
   assert "foo" == result

【讨论】:

  • 那么测试覆盖率呢? (在if __name__ == '__main__': 线上)
  • 问题是我无法更改此 python 文件,它是遗留代码的一部分,无法更改!
  • 好点@Tibebes.M,应该有办法为这部分代码添加覆盖测试!
【解决方案2】:

通常我会创建一个main 函数,它总是接受参数并在需要时使用命令行参数调用它。

def main(args):
    # parser : argparse.ArgumentParser
    args = parser.parse_args(args)
    pass

if __name__ == '__main__':
    main(sys.argv[1:])

当从命令行运行时,它将使用命令行参数调用。可随时直接拨打main调用。

【讨论】:

  • 问题是我无法更改文件以包含 main() 方法并从我的测试代码中调用此方法
猜你喜欢
  • 1970-01-01
  • 2020-05-16
  • 2011-08-16
  • 2021-05-12
  • 2015-04-04
  • 2011-06-09
  • 1970-01-01
  • 1970-01-01
  • 2018-11-22
相关资源
最近更新 更多