Pytest 根据参数生成测试
Pytest Generate Tests Based on Arguments
pytest 新手...
我在 conftest.py 中使用以下命令从命令行收集团队参数,并读入 yaml 配置文件:
import pytest
import yaml
def pytest_addoption(parser):
parser.addoption(
'--team',
action='store',
)
@pytest.fixture
def team(request):
return request.config.getoption('--team')
@pytest.fixture
def conf(request):
with open('config.yml', 'r') as f:
conf = yaml.load(f.read())
return conf
我想 运行 对 conf[team]['players'](列表)中的每个玩家进行测试。我可以在 test_players.py:
中这样做
def test_players(team, conf):
players = conf[team]['players']
for p in players:
assert p == something
这种方法可行,因为它遍历了玩家,但整个过程被视为单个测试。如果有任何失败,整个测试将被视为失败。我希望每个播放器都单独测试。
如果我手动输入播放器,我可以让它工作:
import pytest
class Test_Player():
@pytest.mark.parametrize(
'player', [
'player1',
'player2',
'player3',
],
)
def test_player(self, player):
assert player == something
所以我的问题是我不知道如何将 conf[team] 传递到 pytest.mark.parametrize。我试过这些,但在这两种情况下它都抱怨没有定义 conf。
import pytest
class Test_Player():
@pytest.mark.parametrize(
'player', conf[team]['players'],
)
def test_player(self, player):
assert player == something
和
import pytest
class Test_Player(team, conf):
@pytest.mark.parametrize(
'player', conf[team]['players'],
)
def test_player(self, player):
assert player == something
我在这里错过了什么?
您设置的问题是您想要在 conf[team]
上进行参数化,但是 conf
需要在 import 时间定义,因为那是装饰器执行。
因此,您必须使用 pytest 的 metafunc parametrization 功能以不同的方式进行此参数化。
.
├── conftest.py
├── teams.yml
└── test_bobs.py
在yaml文件中:
# teams.yml
bobs: [bob1, bob2, potato]
pauls: [paultato]
在测试模块中:
# test_bobs.py
def test_player(player):
assert 'bob' in player
在 pytest conf 中:
import pytest
import yaml
def pytest_addoption(parser):
parser.addoption('--team', action='store')
def pytest_generate_tests(metafunc):
if 'player' in metafunc.fixturenames:
team_name = metafunc.config.getoption('team')
# you can move this part out to module scope if you want
with open('./teams.yml') as f:
teams = yaml.load(f)
metafunc.parametrize("player", teams.get(team_name, []))
现在执行:
pytest --team bobs
您应该看到执行了三个测试:两个通过测试(bob1、bob2)和一个失败测试(potato)。使用 pytest --team pauls
将使一次测试失败。使用 pytest --team bogus
将导致跳过测试。例如,如果您想要不同的行为,请将 teams.get(team_name, [])
更改为 teams[team_name]
。
pytest 新手...
我在 conftest.py 中使用以下命令从命令行收集团队参数,并读入 yaml 配置文件:
import pytest
import yaml
def pytest_addoption(parser):
parser.addoption(
'--team',
action='store',
)
@pytest.fixture
def team(request):
return request.config.getoption('--team')
@pytest.fixture
def conf(request):
with open('config.yml', 'r') as f:
conf = yaml.load(f.read())
return conf
我想 运行 对 conf[team]['players'](列表)中的每个玩家进行测试。我可以在 test_players.py:
中这样做def test_players(team, conf):
players = conf[team]['players']
for p in players:
assert p == something
这种方法可行,因为它遍历了玩家,但整个过程被视为单个测试。如果有任何失败,整个测试将被视为失败。我希望每个播放器都单独测试。
如果我手动输入播放器,我可以让它工作:
import pytest
class Test_Player():
@pytest.mark.parametrize(
'player', [
'player1',
'player2',
'player3',
],
)
def test_player(self, player):
assert player == something
所以我的问题是我不知道如何将 conf[team] 传递到 pytest.mark.parametrize。我试过这些,但在这两种情况下它都抱怨没有定义 conf。
import pytest
class Test_Player():
@pytest.mark.parametrize(
'player', conf[team]['players'],
)
def test_player(self, player):
assert player == something
和
import pytest
class Test_Player(team, conf):
@pytest.mark.parametrize(
'player', conf[team]['players'],
)
def test_player(self, player):
assert player == something
我在这里错过了什么?
您设置的问题是您想要在 conf[team]
上进行参数化,但是 conf
需要在 import 时间定义,因为那是装饰器执行。
因此,您必须使用 pytest 的 metafunc parametrization 功能以不同的方式进行此参数化。
.
├── conftest.py
├── teams.yml
└── test_bobs.py
在yaml文件中:
# teams.yml
bobs: [bob1, bob2, potato]
pauls: [paultato]
在测试模块中:
# test_bobs.py
def test_player(player):
assert 'bob' in player
在 pytest conf 中:
import pytest
import yaml
def pytest_addoption(parser):
parser.addoption('--team', action='store')
def pytest_generate_tests(metafunc):
if 'player' in metafunc.fixturenames:
team_name = metafunc.config.getoption('team')
# you can move this part out to module scope if you want
with open('./teams.yml') as f:
teams = yaml.load(f)
metafunc.parametrize("player", teams.get(team_name, []))
现在执行:
pytest --team bobs
您应该看到执行了三个测试:两个通过测试(bob1、bob2)和一个失败测试(potato)。使用 pytest --team pauls
将使一次测试失败。使用 pytest --team bogus
将导致跳过测试。例如,如果您想要不同的行为,请将 teams.get(team_name, [])
更改为 teams[team_name]
。