如何使用具有 if __name__ == '__main__': with arguments 的 pytest 测试 python 文件

how to test python file with pytest having if __name__ == '__main__': with arguments

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

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 文件在我的测试中包含一些参数?

命令行参数是一种与其他任何机制一样的 input/output 机制。关键是把它隔离在一个“边界层”,让你的主程序不直接依赖它们。

在这种情况下,与其让您的程序直接访问 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

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

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

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

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