如何将命令行参数从 pytest 传递给代码

R71*_*R71 9 pytest argparse python-3.x

我正在尝试将参数从 pytest 测试用例传递给正在测试的模块。例如,使用Python 样板中的 main.py ,我可以从命令行运行它:

$ python3 main.py
usage: main.py [-h] [-f] [-n NAME] [-v] [--version] arg
main.py: error: the following arguments are required: arg
$ python3 main.py xx
hello world
Namespace(arg='xx', flag=False, name=None, verbose=0)
Run Code Online (Sandbox Code Playgroud)

现在我正在尝试对 pytest 做同样的事情,使用以下 test_sample.py

注意: main.py 需要命令行参数。但是这些参数需要在特定测试中进行硬编码,它们不应该是 pytest 的命令行参数。pytest 测试用例只需要将这些值作为命令行参数发送给 main。主要的()。)

import main
def test_case01():
    main.main()
    # I dont know how to pass 'xx' to main.py,
    # so for now I just have one test with no arguments
Run Code Online (Sandbox Code Playgroud)

并按以下方式运行测试:

pytest -vs test_sample.py
Run Code Online (Sandbox Code Playgroud)

这失败并显示错误消息。我试图查看其他答案以获得解决方案,但无法使用它们。例如,42778124建议创建一个单独的文件 run.py,这不是一个理想的做法。和4835995740880259似乎更多地处理命令行参数,而不是将命令行参数传递给主代码。

我不需要 pytest 来获取命令行参数,这些参数可以在特定测试中进行硬编码。但是这些参数需要作为参数传递给主代码。你能给我一个 test_sample.py,它用一些参数调用 main.main() 吗?

hoe*_*ing 8

如果不能修改main方法的签名,可以使用 monkeypatching技术临时用测试数据替换参数。示例:想象为以下程序编写测试:

import argparse


def main():
    parser = argparse.ArgumentParser(description='Greeter')
    parser.add_argument('name')
    args = parser.parse_args()
    return f'hello {args.name}'


if __name__ == '__main__':
    print(main())
Run Code Online (Sandbox Code Playgroud)

从命令行运行时:

$ python greeter.py world
hello world
Run Code Online (Sandbox Code Playgroud)

main使用一些自定义数据测试函数,monkeypatch sys.argv

import sys
import greeter

def test_greeter(monkeypatch):
    with monkeypatch.context() as m:
        m.setattr(sys, 'argv', ['greeter', 'spam'])
        assert greeter.main() == 'hello spam'
Run Code Online (Sandbox Code Playgroud)

当与参数化技术结合使用时,这允许在不修改测试函数的情况下轻松测试不同的参数:

import sys
import pytest
import greeter

@pytest.mark.parametrize('name', ['spam', 'eggs', 'bacon'])
def test_greeter(monkeypatch, name):
    with monkeypatch.context() as m:
        m.setattr(sys, 'argv', ['greeter', name])
        assert greeter.main() == 'hello ' + name
Run Code Online (Sandbox Code Playgroud)

现在你得到三个测试,每个参数一个:

import argparse


def main():
    parser = argparse.ArgumentParser(description='Greeter')
    parser.add_argument('name')
    args = parser.parse_args()
    return f'hello {args.name}'


if __name__ == '__main__':
    print(main())
Run Code Online (Sandbox Code Playgroud)


Blu*_*ken 2

一个好的做法可能是拥有这种代码,而不是从 main 方法中读取参数。

# main.py
def main(arg1):
    return arg1

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='My awesome script')
    parser.add_argument('word', help='a word')
    args = parser.parse_args()
    main(args.word)
Run Code Online (Sandbox Code Playgroud)

这样,您的 main 方法就可以轻松地在 pytest 中进行测试

import main
def test_case01():
    main.main(your_hardcoded_arg)
Run Code Online (Sandbox Code Playgroud)

我不确定你可以调用 python 脚本来测试,除非使用os模块,这可能不是一个好的做法