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

时间:2019-01-07 09:07:01

标签: python-3.x pytest argparse

我试图将参数从pytest测试用例传递到要测试的模块。例如,使用Python boilerplate中的main.py,我可以在命令行中以如下方式运行它:

[√] Flutter (Channel beta, v1.0.0, on Microsoft Windows [Version 10.0.17134.472], locale ko-KR)
    • Flutter version 1.0.0 at C:\flutter
    • Framework revision 5391447fae (5 weeks ago), 2018-11-29 19:41:26 -0800
    • Engine revision 7375a0f414
    • Dart version 2.1.0 (build 2.1.0-dev.9.4 f9ebf21297)

[√] Android toolchain - develop for Android devices (Android SDK 28.0.3)
    • Android SDK at C:\AndroidSDK
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-28, build-tools 28.0.3
    • ANDROID_HOME = C:\AndroidSDK
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06)
    • All Android licenses accepted.

[√] Android Studio (version 3.2)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 31.3.1
    • Dart plugin version 181.5656
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06)

[!] IntelliJ IDEA Community Edition (version 2018.2)
    • IntelliJ at C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2018.2
    X Flutter plugin not installed; this adds Flutter specific functionality.
    X Dart plugin not installed; this adds Dart specific functionality.
    • For information about installing plugins, see
      https://flutter.io/intellij-setup/#installing-the-plugins

[!] VS Code, 64-bit edition (version 1.30.1)
    • VS Code at C:\Program Files\Microsoft VS Code
    • Flutter extension not installed; install from
      https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[√] Connected device (1 available)
    • Android SDK built for x86 • emulator-5554 • android-x86 • Android 9 (API 28) (emulator)

现在,我尝试使用以下test_sample.py

对pytest进行相同操作

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

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

并以以下方式运行测试:

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

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

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

2 个答案:

答案 0 :(得分:2)

如果您无法修改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())

从命令行运行时:

$ python greeter.py world
hello world

要使用某些自定义数据测试main函数,请猴子补丁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'

parametrizing技术结合使用时,可以轻松测试不同的参数而无需修改测试函数:

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

现在您将获得三个测试,每个参数一个:

$ 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

答案 1 :(得分:0)

一个好的实践可能是拥有这种代码,而不是从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)

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

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

除了使用os模块外,我不确定是否可以调用python脚本进行测试,