Skip to content

Commit c63fe90

Browse files
author
Sylvain MARIE
committed
Improved test ids for the cases where fixture_ref is used in the parameters list in @pytest_parametrize_plus. Fixed #69
1 parent 121de3e commit c63fe90

File tree

5 files changed

+69
-47
lines changed

5 files changed

+69
-47
lines changed

pytest_cases/main_fixtures.py

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -820,8 +820,15 @@ def fixture_union(name,
820820
unpack_into=unpack_into, **kwargs)
821821

822822

823-
def _fixture_union(caller_module, name, fixtures, idstyle, scope="function", ids=fixture_alternative_to_str,
824-
unpack_into=None, autouse=False, **kwargs):
823+
def _fixture_union(caller_module,
824+
name, # type: str
825+
fixtures, # type: Iterable[Union[str, Callable]]
826+
idstyle, # type: Optional[IdStyle]
827+
scope="function", # type: str
828+
ids=fixture_alternative_to_str, # type: Union[Callable, List[str]]
829+
unpack_into=None, # type: Iterable[str]
830+
autouse=False, # type: bool
831+
**kwargs):
825832
"""
826833
Internal implementation for fixture_union
827834
@@ -1030,7 +1037,7 @@ def pytest_parametrize_plus(argnames, argvalues, indirect=False, ids=None, scope
10301037
# there are fixture references: we have to create a specific decorator
10311038
caller_module = get_caller_module()
10321039

1033-
def _create_param_fixture(from_i, to_i, p_fix_name):
1040+
def _create_param_fixture(from_i, to_i, p_names, test_func_name):
10341041
""" Routine that will be used to create a parameter fixture for argvalues between prev_i and i"""
10351042
selected_argvalues = argvalues[from_i:to_i]
10361043
try:
@@ -1046,18 +1053,22 @@ def _create_param_fixture(from_i, to_i, p_fix_name):
10461053
selected_ids = get_test_ids_from_param_values(all_param_names, selected_argvalues)
10471054

10481055
if to_i == from_i + 1:
1049-
p_fix_name = "%s_is_%s" % (p_fix_name, from_i)
1056+
p_names_with_idx = "%s_is_%s" % (p_names, from_i)
10501057
else:
1051-
p_fix_name = "%s_is_%sto%s" % (p_fix_name, from_i, to_i - 1)
1058+
p_names_with_idx = "%s_is_%sto%s" % (p_names, from_i, to_i - 1)
1059+
1060+
# now create a unique fixture name
1061+
p_fix_name = "%s_%s" % (test_func_name, p_names_with_idx)
10521062
p_fix_name = check_name_available(caller_module, p_fix_name, if_name_exists=CHANGE,
10531063
caller=pytest_parametrize_plus)
1064+
10541065
param_fix = _param_fixture(caller_module, argname=p_fix_name, argvalues=selected_argvalues,
10551066
ids=selected_ids)
1056-
return param_fix
1067+
return param_fix, p_names_with_idx
10571068

1058-
def _create_fixture_product(argvalue_i, fixture_ref_positions, base_name):
1069+
def _create_fixture_product(argvalue_i, fixture_ref_positions, param_names_str, test_func_name):
10591070
# do not use base name - we dont care if there is another in the same module, it will still be more readable
1060-
p_fix_name = "fixtureproduct__%s" % (argvalue_i, )
1071+
p_fix_name = "%s_%s__fixtureproduct__%s" % (test_func_name, param_names_str, argvalue_i)
10611072
p_fix_name = check_name_available(caller_module, p_fix_name, if_name_exists=CHANGE,
10621073
caller=pytest_parametrize_plus)
10631074
# unpack the fixture references
@@ -1082,11 +1093,13 @@ def parametrize_plus_decorate(test_func):
10821093
raise ValueError("parameter '%s' not found in test function signature '%s%s'"
10831094
"" % (p, test_func.__name__, old_sig))
10841095

1085-
# The base name for all fixtures that will be created below
1096+
# The name for the final "union" fixture
10861097
# style_template = "%s_param__%s"
1098+
param_names_str = argnames.replace(' ', '').replace(',', '_')
10871099
style_template = "%s_%s"
1088-
base_name = style_template % (test_func.__name__, argnames.replace(' ', '').replace(',', '_'))
1089-
base_name = check_name_available(caller_module, base_name, if_name_exists=CHANGE, caller=pytest_parametrize_plus)
1100+
fixture_union_name = style_template % (test_func.__name__, param_names_str)
1101+
fixture_union_name = check_name_available(caller_module, fixture_union_name, if_name_exists=CHANGE,
1102+
caller=pytest_parametrize_plus)
10901103

10911104
# Retrieve (if ref) or create (for normal argvalues) the fixtures that we will union
10921105
# TODO important note: we could either wish to create one fixture for parameter value or to create one for
@@ -1099,35 +1112,36 @@ def parametrize_plus_decorate(test_func):
10991112
if i > prev_i + 1:
11001113
# there was a non-empty group of 'normal' parameters before this fixture_ref.
11011114
# create a new fixture parametrized with all of that consecutive group.
1102-
param_fix = _create_param_fixture(prev_i + 1, i, base_name)
1115+
param_fix, _id_for_fix = _create_param_fixture(prev_i + 1, i, param_names_str, test_func.__name__)
11031116
fixtures_to_union.append(param_fix)
1104-
fixtures_to_union_names_for_ids.append(get_fixture_name(param_fix))
1117+
fixtures_to_union_names_for_ids.append(_id_for_fix)
11051118

11061119
if j_list is None:
11071120
# add the fixture referenced with `fixture_ref`
11081121
referenced_fixture = argvalues[i].fixture
11091122
fixtures_to_union.append(referenced_fixture)
1110-
id_for_fixture = apply_id_style(get_fixture_name(referenced_fixture), base_name, IdStyle.explicit)
1123+
id_for_fixture = apply_id_style(get_fixture_name(referenced_fixture), param_names_str, IdStyle.explicit)
11111124
fixtures_to_union_names_for_ids.append(id_for_fixture)
11121125
else:
11131126
# create a fixture refering to all the fixtures required in the tuple
1114-
prod_fix = _create_fixture_product(i, j_list, base_name)
1127+
prod_fix = _create_fixture_product(i, j_list, param_names_str, test_func.__name__)
11151128
fixtures_to_union.append(prod_fix)
1116-
id_for_fixture = apply_id_style(get_fixture_name(prod_fix), base_name, IdStyle.explicit)
1129+
_id_product = "fixtureproduct__%s" % i
1130+
id_for_fixture = apply_id_style(_id_product, param_names_str, IdStyle.explicit)
11171131
fixtures_to_union_names_for_ids.append(id_for_fixture)
11181132
prev_i = i
11191133

11201134
# handle last consecutive group of normal parameters, if any
11211135
i = len(argvalues)
11221136
if i > prev_i + 1:
1123-
param_fix = _create_param_fixture(prev_i + 1, i, base_name)
1137+
param_fix, _id_for_fix = _create_param_fixture(prev_i + 1, i, param_names_str, test_func.__name__)
11241138
fixtures_to_union.append(param_fix)
1125-
fixtures_to_union_names_for_ids.append(get_fixture_name(param_fix))
1139+
fixtures_to_union_names_for_ids.append(_id_for_fix)
11261140

11271141
# Finally create a "main" fixture with a unique name for this test function
11281142
# note: the function automatically registers it in the module
11291143
# note 2: idstyle is set to None because we provide an explicit enough list of ids
1130-
big_param_fixture = _fixture_union(caller_module, base_name, fixtures_to_union, idstyle=None,
1144+
big_param_fixture = _fixture_union(caller_module, fixture_union_name, fixtures_to_union, idstyle=None,
11311145
ids=fixtures_to_union_names_for_ids)
11321146

11331147
# --create the new test function's signature that we want to expose to pytest
@@ -1141,12 +1155,12 @@ def parametrize_plus_decorate(test_func):
11411155
# finally insert the new fixture in that position. Indeed we can not insert first or last, because
11421156
# 'self' arg (case of test class methods) should stay first and exec order should be preserved when possible
11431157
new_sig = add_signature_parameters(new_sig, custom_idx=_first_idx,
1144-
custom=Parameter(base_name, kind=Parameter.POSITIONAL_OR_KEYWORD))
1158+
custom=Parameter(fixture_union_name, kind=Parameter.POSITIONAL_OR_KEYWORD))
11451159

11461160
# --Finally create the fixture function, a wrapper of user-provided fixture with the new signature
11471161
def replace_paramfixture_with_values(kwargs):
11481162
# remove the created fixture value
1149-
encompassing_fixture = kwargs.pop(base_name)
1163+
encompassing_fixture = kwargs.pop(fixture_union_name)
11501164
# and add instead the parameter values
11511165
if nb_params > 1:
11521166
for i, p in enumerate(all_param_names):
@@ -1160,7 +1174,7 @@ def replace_paramfixture_with_values(kwargs):
11601174
# normal test function with return statement
11611175
@wraps(test_func, new_sig=new_sig)
11621176
def wrapped_test_func(*args, **kwargs):
1163-
if kwargs.get(base_name, None) is NOT_USED:
1177+
if kwargs.get(fixture_union_name, None) is NOT_USED:
11641178
return NOT_USED
11651179
else:
11661180
replace_paramfixture_with_values(kwargs)
@@ -1170,7 +1184,7 @@ def wrapped_test_func(*args, **kwargs):
11701184
# generator test function (with one or several yield statement)
11711185
@wraps(test_func, new_sig=new_sig)
11721186
def wrapped_test_func(*args, **kwargs):
1173-
if kwargs.get(base_name, None) is NOT_USED:
1187+
if kwargs.get(fixture_union_name, None) is NOT_USED:
11741188
yield NOT_USED
11751189
else:
11761190
replace_paramfixture_with_values(kwargs)

pytest_cases/tests/fixtures/test_fixture_in_parametrize.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ def test_foo(arg, bar):
3131

3232

3333
def test_synthesis(module_results_dct):
34-
assert list(module_results_dct) == ['test_foo[test_foo_arg_is_0-z-bar]',
35-
'test_foo[test_foo_arg_is_a-bar]',
36-
'test_foo[test_foo_arg_is_b-b_second_letter_is_a-bar]',
37-
'test_foo[test_foo_arg_is_b-b_second_letter_is_1-o-bar]',
38-
'test_foo[test_foo_arg_is_3-o-bar]']
34+
assert list(module_results_dct) == ['test_foo[arg_is_0-z-bar]',
35+
'test_foo[arg_is_a-bar]',
36+
'test_foo[arg_is_b-second_letter_is_a-bar]',
37+
'test_foo[arg_is_b-second_letter_is_1-o-bar]',
38+
'test_foo[arg_is_3-o-bar]']

pytest_cases/tests/fixtures/test_fixture_in_parametrize_basic.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ def test_prints(main_msg, ending):
2020

2121

2222
def test_synthesis(module_results_dct):
23-
assert list(module_results_dct) == ['test_prints[test_prints_main_msg_is_0-nothing-?]',
24-
'test_prints[test_prints_main_msg_is_0-nothing-!]',
25-
'test_prints[test_prints_main_msg_is_world_str-?]',
26-
'test_prints[test_prints_main_msg_is_world_str-!]',
27-
'test_prints[test_prints_main_msg_is_greetings-greetings_who_is_world_str-?]',
28-
'test_prints[test_prints_main_msg_is_greetings-greetings_who_is_world_str-!]',
29-
'test_prints[test_prints_main_msg_is_greetings-greetings_who_is_1-you-?]',
30-
'test_prints[test_prints_main_msg_is_greetings-greetings_who_is_1-you-!]']
23+
assert list(module_results_dct) == ['test_prints[main_msg_is_0-nothing-?]',
24+
'test_prints[main_msg_is_0-nothing-!]',
25+
'test_prints[main_msg_is_world_str-?]',
26+
'test_prints[main_msg_is_world_str-!]',
27+
'test_prints[main_msg_is_greetings-who_is_world_str-?]',
28+
'test_prints[main_msg_is_greetings-who_is_world_str-!]',
29+
'test_prints[main_msg_is_greetings-who_is_1-you-?]',
30+
'test_prints[main_msg_is_greetings-who_is_1-you-!]']

pytest_cases/tests/fixtures/test_fixture_in_parametrize_tuple.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ def test_prints(p, q):
3131

3232

3333
def test_synthesis(module_results_dct):
34-
assert list(module_results_dct) == ['test_prints[test_prints_p_q_is_0-a-1]',
35-
'test_prints[test_prints_p_q_is_fixtureproduct__1-b]',
36-
'test_prints[test_prints_p_q_is_fixtureproduct__1-c]',
37-
'test_prints[test_prints_p_q_is_fixtureproduct__2-b-0]',
38-
'test_prints[test_prints_p_q_is_fixtureproduct__2-b--1]',
39-
'test_prints[test_prints_p_q_is_fixtureproduct__2-c-0]',
40-
'test_prints[test_prints_p_q_is_fixtureproduct__2-c--1]',
41-
'test_prints[test_prints_p_q_is_fixtureproduct__3-b]',
42-
'test_prints[test_prints_p_q_is_fixtureproduct__3-c]',
43-
"test_prints[test_prints_p_q_is_my_tuple-('d', 3)]",
44-
"test_prints[test_prints_p_q_is_my_tuple-('e', 4)]"
34+
assert list(module_results_dct) == ['test_prints[p_q_is_0-a-1]',
35+
'test_prints[p_q_is_fixtureproduct__1-b]',
36+
'test_prints[p_q_is_fixtureproduct__1-c]',
37+
'test_prints[p_q_is_fixtureproduct__2-b-0]',
38+
'test_prints[p_q_is_fixtureproduct__2-b--1]',
39+
'test_prints[p_q_is_fixtureproduct__2-c-0]',
40+
'test_prints[p_q_is_fixtureproduct__2-c--1]',
41+
'test_prints[p_q_is_fixtureproduct__3-b]',
42+
'test_prints[p_q_is_fixtureproduct__3-c]',
43+
"test_prints[p_q_is_my_tuple-('d', 3)]",
44+
"test_prints[p_q_is_my_tuple-('e', 4)]"
4545
]

pytest_cases/tests/issues/test_issue_pytest_70.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,11 @@ def book2():
2121
])
2222
def test_get_or_create_book(name):
2323
print(name)
24+
25+
26+
def test_synthesis(module_results_dct):
27+
assert list(module_results_dct) == ['test_get_or_create_book[name_is_book1-A]',
28+
'test_get_or_create_book[name_is_book1-B]',
29+
'test_get_or_create_book[name_is_1to2-hi]',
30+
'test_get_or_create_book[name_is_1to2-ih]',
31+
'test_get_or_create_book[name_is_book2]']

0 commit comments

Comments
 (0)