【问题标题】:Function in pytest file works only with hard coded valuespytest 文件中的函数仅适用于硬编码值
【发布时间】:2021-01-10 08:48:11
【问题描述】:

我有以下用于 pytest 的test_dss.py 文件:

import dataikuapi

import pytest
 

def setup_list():

    client = dataikuapi.DSSClient("{DSS_URL}", "{APY_KEY}")

    client._session.verify = False

    project = client.get_project("{DSS_PROJECT}")

    # Check that there is at least one scenario TEST_XXXXX & that all test scenarios pass

    scenarios = project.list_scenarios()

    scenarios_filter = [obj for obj in scenarios if obj["name"].startswith("TEST")]

    return scenarios_filter

 
def test_check_scenario_exist():

    assert len(setup_list()) > 0, "You need at least one test scenario (name starts with 'TEST_')"

 
@pytest.mark.parametrize("scenario", setup_list())

def test_scenario_run(scenario, params):

    client = dataikuapi.DSSClient(params['host'], params['api'])

    client._session.verify = False

    project = client.get_project(params['project'])

    scenario_id = scenario["id"]

    print("Executing scenario ", scenario["name"])

    scenario_result = project.get_scenario(scenario_id).run_and_wait()

    assert scenario_result.get_details()["scenarioRun"]["result"]["outcome"] == "SUCCESS", "test " + scenario[

    "name"] + " failed"

我的问题是 setup_list 函数,它只能获取 {DSS_URL}{APY_KEY}{PROJECT} 的硬编码值。我无法使用PARAMStest_scenario_run 中的其他方法 知道如何将PARAMS 也传递给这个函数吗?

【问题讨论】:

  • 我不确定我是否理解您在做什么,但我假设您想访问通过命令行在用于参数化的代码中传递的配置值。这可以通过使用 pytest_generate_tests 动态参数化测试来完成。
  • 我希望能够在函数setup_list 中使用参数,但它只能硬编码......
  • 你不能在函数中使用这些参数,因为函数对它们一无所知。正如我所写,如果您只需要用于参数化的函数,您可以在pytest_generate_tests 中执行此操作。对吗?
  • 正确。你能告诉我它在我的代码上的外观吗?
  • 如果我理解正确,请告诉我。我应该添加到conftest.pydef pytest_generate_tests(metafunc): metafunc.parametrize(host,api,project)test_dss.py 这个添加到函数中:def setup_list(host,api,project):

标签: pytest assert fixtures hardcoded parametrized-testing


【解决方案1】:

mark.parametrize 标记中的参数在加载时读取,此时有关配置参数的信息尚不可用。因此,您必须在运行时对测试进行参数化,您可以在其中访问配置。

这可以在pytest_generate_tests 中完成(可以存在于您的测试模块中):

@pytest.hookimpl
def pytest_generate_tests(metafunc):
    if "scenario" in metafunc.fixturenames:
        host = metafunc.config.getoption('--host')
        api = metafuc.config.getoption('--api')
        project = metafuc.config.getoption('--project')
        metafunc.parametrize("scenario", setup_list(host, api, project))

这意味着您的 setup_list 函数采用以下参数:

def setup_list(host, api, project):
    client = dataikuapi.DSSClient(host, api)
    client._session.verify = False
    project = client.get_project(project)
    ...

您的测试看起来像这样(没有parametrize 标记,因为参数化现在在pytest_generate_tests 中完成):

def test_scenario_run(scenario, params):
    scenario_id = scenario["id"]
    ...

参数化现在在运行时完成,因此它的行为与您在测试中放置 parametrize 标记相同。

而另一个测试 setup_list 的测试现在也必须使用 params 夹具来获取所需的参数:

def test_check_scenario_exist(params):
    assert len(setup_list(params["host"], params["api"], params["project"])) > 0,
 "You need at least ..."

【讨论】:

  • def test_scenario_run(scenario): 上方的一行我有:@pytest.mark.parametrize("scenario", setup_list())。我正在使用它,所以我可以在这个列表上循环运行,它从函数setup_list 和迭代器scenario 返回。我应该在那里修改什么?
  • 正如我在答案中所写 - 你不需要这个,因为你在运行时进行参数化。只需将其删除,如上所示。添加了另一个注释。
  • 但是我在scenario_id = scenario["id"] 之后有这一行:scenario_result = project.get_scenario(scenario_id).run_and_wait(),它会抛出错误:NameError: name 'project' is not defined
  • 好的,如果您需要该项目,您还必须使用params 夹具 - 我在您的问题中没有看到这一点。再次编辑答案...您在测试中和setup_list中使用相同的代码看起来有点奇怪。
  • 看起来更好(你可以用它来编辑你的答案)。现在剩下的唯一问题是 len assert 测试。:def test_check_scenario_exist(): > assert len(setup_list()) > 0, "You need at least one test scenario (name starts with 'TEST_')" E TypeError: setup_list() missing 3 required positional arguments: 'host', 'api', and 'project'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-02
  • 2016-04-15
  • 2013-07-08
  • 1970-01-01
  • 2016-11-24
  • 2022-01-02
  • 1970-01-01
相关资源
最近更新 更多