简体   繁体   English

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

[英]how to pass command line argument from pytest to code

I am trying to pass arguments from a pytest testcase to a module being tested.我正在尝试将参数从 pytest 测试用例传递给正在测试的模块。 For example, using the main.py from Python boilerplate , I can run it from the command line as:例如,使用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)

Now I am trying to do the same with pytest, with the following test_sample.py现在我正在尝试对 pytest 做同样的事情,使用以下 test_sample.py

( NOTE: the main.py requires command line arguments. But these arguments need to be hardcoded in a specific test, they should not be command line arguments to pytest. The pytest testcase only needs to send these values as command line arguments to main.main().) 注意: 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

and running the test as:并按以下方式运行测试:

pytest -vs test_sample.py

This fails with error messages.这失败并显示错误消息。 I tried to look at other answers for a solution but could not use them.我试图查看其他答案以寻求解决方案,但无法使用它们。 For example, 42778124 suggests to create a separate file run.py which is not a desirable thing to do.例如, 42778124建议创建一个单独的文件 run.py,这不是一个理想的做法。 And 48359957 and 40880259 seem to deal more with command line arguments for pytest, instead of passing command line arguments to the main code.4835995740880259似乎更多地处理pytest 的命令行参数,而不是将命令行参数传递给主代码。

I dont need the pytest to take command line arguments, the arguments can be hardcoded inside a specific test.我不需要 pytest 来获取命令行参数,这些参数可以在特定测试中进行硬编码。 But these arguments need to be passed as arguments to the main code.但是这些参数需要作为参数传递给主代码。 Can you give me a test_sample.py, that calls main.main() with some arguments?你能给我一个 test_sample.py,它用一些参数调用 main.main() 吗?

If you can't modify the signature of the main method, you can use the monkeypatching technique to temporarily replace the arguments with the test data.如果不能修改main方法的签名,可以使用monkeypatching技术临时用测试数据替换参数。 Example: imagine writing tests for the following program:示例:想象为以下程序编写测试:

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())

When running it from the command line:从命令行运行时:

$ python greeter.py world
hello world

To test the main function with some custom data, monkeypatch sys.argv :要使用一些自定义数据测试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'

When combined with the parametrizing technique, this allows to easily test different arguments without modifying the test function:当与参数化技术结合使用时,这允许在不修改测试函数的情况下轻松测试不同的参数:

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

Now you get three tests, one for each of the arguments:现在你得到三个测试,每个参数一个:

$ pytest -v test_greeter.py

...

test_greeter.py::test_greeter[spam] PASSED
test_greeter.py::test_greeter[eggs] PASSED
test_greeter.py::test_greeter[bacon] PASSED

A good practice might to have this kind of code, instead of reading arguments from main method.一个好的做法可能是拥有这种代码,而不是从 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)

This way, your main method can easily be tested in pytest这样,您的主要方法可以轻松地在 pytest 中进行测试

import main
def test_case01():
    main.main(your_hardcoded_arg)

I am not sure you can call a python script to test except by using os module, which might be not a good practice我不确定您是否可以调用 python 脚本进行测试,除非使用os模块,这可能不是一个好习惯

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM