2525from  typing  import  Any 
2626from  typing  import  final 
2727from  typing  import  Literal 
28+ from  typing  import  NoReturn 
2829from  typing  import  TYPE_CHECKING 
2930import  warnings 
3031
5657from  _pytest .fixtures  import  get_scope_node 
5758from  _pytest .main  import  Session 
5859from  _pytest .mark  import  ParameterSet 
60+ from  _pytest .mark .structures  import  _HiddenParam 
5961from  _pytest .mark .structures  import  get_unpacked_marks 
62+ from  _pytest .mark .structures  import  HIDDEN_PARAM 
6063from  _pytest .mark .structures  import  Mark 
6164from  _pytest .mark .structures  import  MarkDecorator 
6265from  _pytest .mark .structures  import  normalize_mark_list 
@@ -473,7 +476,7 @@ def _genfunctions(self, name: str, funcobj) -> Iterator[Function]:
473476 fixtureinfo .prune_dependency_tree ()
474477
475478 for  callspec  in  metafunc ._calls :
476-  subname  =  f"{ name }  [{ callspec .id }  ]" 
479+  subname  =  f"{ name }  [{ callspec .id }  ]"   if   callspec . _idlist   else   name 
477480 yield  Function .from_parent (
478481 self ,
479482 name = subname ,
@@ -884,7 +887,7 @@ class IdMaker:
884887 # Used only for clearer error messages. 
885888 func_name : str  |  None 
886889
887-  def  make_unique_parameterset_ids (self ) ->  list [str ]:
890+  def  make_unique_parameterset_ids (self ) ->  list [str   |   _HiddenParam ]:
888891 """Make a unique identifier for each ParameterSet, that may be used to 
889892 identify the parametrization in a node ID. 
890893
@@ -905,6 +908,8 @@ def make_unique_parameterset_ids(self) -> list[str]:
905908 # Suffix non-unique IDs to make them unique. 
906909 for  index , id  in  enumerate (resolved_ids ):
907910 if  id_counts [id ] >  1 :
911+  if  id  is  HIDDEN_PARAM :
912+  self ._complain_multiple_hidden_parameter_sets ()
908913 suffix  =  "" 
909914 if  id  and  id [- 1 ].isdigit ():
910915 suffix  =  "_" 
@@ -919,15 +924,21 @@ def make_unique_parameterset_ids(self) -> list[str]:
919924 )
920925 return  resolved_ids 
921926
922-  def  _resolve_ids (self ) ->  Iterable [str ]:
927+  def  _resolve_ids (self ) ->  Iterable [str   |   _HiddenParam ]:
923928 """Resolve IDs for all ParameterSets (may contain duplicates).""" 
924929 for  idx , parameterset  in  enumerate (self .parametersets ):
925930 if  parameterset .id  is  not   None :
926931 # ID provided directly - pytest.param(..., id="...") 
927-  yield  _ascii_escaped_by_config (parameterset .id , self .config )
932+  if  parameterset .id  is  HIDDEN_PARAM :
933+  yield  HIDDEN_PARAM 
934+  else :
935+  yield  _ascii_escaped_by_config (parameterset .id , self .config )
928936 elif  self .ids  and  idx  <  len (self .ids ) and  self .ids [idx ] is  not   None :
929937 # ID provided in the IDs list - parametrize(..., ids=[...]). 
930-  yield  self ._idval_from_value_required (self .ids [idx ], idx )
938+  if  self .ids [idx ] is  HIDDEN_PARAM :
939+  yield  HIDDEN_PARAM 
940+  else :
941+  yield  self ._idval_from_value_required (self .ids [idx ], idx )
931942 else :
932943 # ID not provided - generate it. 
933944 yield  "-" .join (
@@ -1001,12 +1012,7 @@ def _idval_from_value_required(self, val: object, idx: int) -> str:
10011012 return  id 
10021013
10031014 # Fail. 
1004-  if  self .func_name  is  not   None :
1005-  prefix  =  f"In { self .func_name }  : " 
1006-  elif  self .nodeid  is  not   None :
1007-  prefix  =  f"In { self .nodeid }  : " 
1008-  else :
1009-  prefix  =  "" 
1015+  prefix  =  self ._make_error_prefix ()
10101016 msg  =  (
10111017 f"{ prefix }  ids contains unsupported value { saferepr (val )}   (type: { type (val )!r}  ) at index { idx }  . " 
10121018 "Supported types are: str, bytes, int, float, complex, bool, enum, regex or anything with a __name__." 
@@ -1019,6 +1025,21 @@ def _idval_from_argname(argname: str, idx: int) -> str:
10191025 and the index of the ParameterSet.""" 
10201026 return  str (argname ) +  str (idx )
10211027
1028+  def  _complain_multiple_hidden_parameter_sets (self ) ->  NoReturn :
1029+  fail (
1030+  f"{ self ._make_error_prefix ()}  multiple instances of HIDDEN_PARAM " 
1031+  "cannot be used in the same parametrize call, " 
1032+  "because the tests names need to be unique." 
1033+  )
1034+ 
1035+  def  _make_error_prefix (self ) ->  str :
1036+  if  self .func_name  is  not   None :
1037+  return  f"In { self .func_name }  : " 
1038+  elif  self .nodeid  is  not   None :
1039+  return  f"In { self .nodeid }  : " 
1040+  else :
1041+  return  "" 
1042+ 
10221043
10231044@final  
10241045@dataclasses .dataclass (frozen = True ) 
@@ -1047,7 +1068,7 @@ def setmulti(
10471068 * ,
10481069 argnames : Iterable [str ],
10491070 valset : Iterable [object ],
1050-  id : str ,
1071+  id : str   |   _HiddenParam ,
10511072 marks : Iterable [Mark  |  MarkDecorator ],
10521073 scope : Scope ,
10531074 param_index : int ,
@@ -1065,7 +1086,7 @@ def setmulti(
10651086 params = params ,
10661087 indices = indices ,
10671088 _arg2scope = arg2scope ,
1068-  _idlist = [* self ._idlist , id ],
1089+  _idlist = self . _idlist   if   id   is   HIDDEN_PARAM   else   [* self ._idlist , id ],
10691090 marks = [* self .marks , * normalize_mark_list (marks )],
10701091 )
10711092
@@ -1190,6 +1211,11 @@ def parametrize(
11901211 They are mapped to the corresponding index in ``argvalues``. 
11911212 ``None`` means to use the auto-generated id. 
11921213
1214+  .. versionadded:: 8.4 
1215+  :ref:`hidden-param` means to hide the parameter set 
1216+  from the test name. Can only be used at most 1 time, as 
1217+  test names need to be unique. 
1218+ 
11931219 If it is a callable it will be called for each entry in 
11941220 ``argvalues``, and the return value is used as part of the 
11951221 auto-generated id for the whole set (where parts are joined with 
@@ -1322,7 +1348,7 @@ def _resolve_parameter_set_ids(
13221348 ids : Iterable [object  |  None ] |  Callable [[Any ], object  |  None ] |  None ,
13231349 parametersets : Sequence [ParameterSet ],
13241350 nodeid : str ,
1325-  ) ->  list [str ]:
1351+  ) ->  list [str   |   _HiddenParam ]:
13261352 """Resolve the actual ids for the given parameter sets. 
13271353
13281354 :param argnames: 
0 commit comments