在pytest中通过python传递命令行参数

11

当运行时,我可以传递命令行参数。

python <filename>.py arg1

但是当我尝试传递命令行参数运行pytest时,它会失败并显示以下错误。请问您有什么建议?

pytest <filename>.py arg1
ERROR: file not found: arg1

编辑:

例如,我考虑这样使用它,假设我已经传递了一个参数,并通过sys.argv读取它:

import sys
arg = sys.argv[3]
def f():
    return 3

def test_function():
    assert f() == arg

你需要它做什么? - Klaus D.
我想将数据传递并存储到脚本中的变量中。这是否可能?谢谢。 - anukb
你不应该这样参数化你的测试。测试应该尽可能自包含。如果你必须测试应用程序的 argv,请模拟它们。 - Klaus D.
感谢同意。我只是想尝试一下是否可以以那种方式传递参数。如果有可能的话,请告诉我任何方法。 - anukb
根据pytest文档,在这里找到了一个有帮助的解决方案:https://dev59.com/drLma4cB1Zd3GeqPeKrf#76813725 - Arthur knn
3个回答

8

您的pytest <filename>.py arg1命令试图在两个模块<filename>.pyarg1上调用pytest,但是没有arg1模块。

如果您想在运行pytest之前传递一些参数,则可以在提取变量后从python脚本中运行pytest。

正如其他人建议的那样,您可能希望以其他方式对测试进行参数化,请尝试:参数化pytest

# run.py
import pytest
import sys

def main():
    # extract your arg here
    print('Extracted arg is ==> %s' % sys.argv[2])
    pytest.main([sys.argv[1]])

if __name__ == '__main__':
    main()

使用python run.py 文件名.py 参数1来调用此函数。


1
很不幸,我得到了和之前一样的错误 - 错误:文件未找到。 - anukb
你能告诉我你所说的“在这里提取参数”的意思吗? - anukb
@anukb 我已经更新了代码,但我不确定你会传递多少个参数。你可以查看https://dev59.com/ZW855IYBdhLWcg3w1oE8获取有关sys arg的更多详细信息。 - Kashif Siddiqui

5

我从阅读参数化pytest文档和一段时间的探索中制定了以下方法...我不知道它的整体稳定性或优劣如何,因为我只是让它工作了。但是,我确认这种方法可以生成HTML覆盖率报告。

# this is just so we can pass --server and --port from the pytest command-line
def pytest_addoption(parser):
    ''' attaches optional cmd-line args to the pytest machinery '''
    parser.addoption("--server", action="append", default=[], help="real server hostname/IP")
    parser.addoption("--port", action="append", default=[], help="real server port number")
def pytest_generate_tests(metafunc):
    ''' just to attach the cmd-line args to a test-class that needs them '''
    server_from_cmd_line = metafunc.config.getoption("server")
    port_from_cmd_line = metafunc.config.getoption("port")
    print('command line passed for --server ({})'.format(server_from_cmd_line))
    print('command line passed for --port ({})'.format(port_from_cmd_line))
    # check if this function is in a test-class that needs the cmd-line args
    if server_from_cmd_line and port_from_cmd_line and hasattr(metafunc.cls, 'real_server'):
        # now set the cmd-line args to the test class
        metafunc.cls.real_server = server_from_cmd_line[0]
        metafunc.cls.real_port = int(port_from_cmd_line[0])


class TestServerCode(object):
    ''' test-class that might benefit from optional cmd-line args '''
    real_server=None
    real_port = None

    def test_valid_string(self):
        assert self.real_server!=None
        assert self.real_port!=None

    def test_other(self):
        from mypackage import my_server_code
        if self.real_server !=  None:
            assert "couldn\'t find host" not in my_server_code.version(self.real_server, self.real_port)
  • 然后使用以下命令运行(例如使用HTML覆盖率):

    • pytest tests\test_junk.py --server="abc" --port=123 --cov-report html --cov=mypackage

好的提示,谢谢。我使用了这种方法来允许在运行测试时通过命令行传递用户名/密码。以前,我不得不在源代码中硬编码凭据,这真的很讨厌。一个负面影响是,在执行测试时,用户名/密码会被打印到终端上。我不喜欢这个,但考虑到控制台已经在执行Pytest时具有附加选项(用户名、密码)可见凭据,这是可以接受的。 - Jeff Wright
添加一个虚拟账户?那么密码泄露就不会成为问题了。 - Abdur-Rahmaan Janhangeer

2

看起来monkeypatch也可以使用。

例子:

import sys

def test_example(monkeypatch):
    monkeypatch.setattr(sys, 'argv', ['/path/to/binary', 'opt1', '...'])
    assert f() == '...'

def test_another():
    # sys.argv is not modified here
    assert f() != '...'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接