@@ -142,8 +142,25 @@ def test_short_definition_raises_config_error(tmp_path):
142142 {"name" : "KEY10" , "distribution" : {"name" : "const" , "value" : 10 }},
143143 {"key" : "KEY10" , "function" : "CONST" , "parameters" : {"VALUE" : 10 }},
144144 ),
145+ (
146+ {
147+ "name" : "KEY11" ,
148+ "distribution" : {
149+ "name" : "pert" ,
150+ "min" : 0 ,
151+ "mode" : 1 ,
152+ "max" : 2 ,
153+ "scale" : 4 ,
154+ },
155+ },
156+ {
157+ "key" : "KEY11" ,
158+ "function" : "PERT" ,
159+ "parameters" : {"MIN" : 0 , "MODE" : 1 , "MAX" : 2 , "SCALE" : 4 },
160+ },
161+ ),
145162 ],
146- ids = [f"KEY{ i } " for i in range (1 , 11 )],
163+ ids = [f"KEY{ i } " for i in range (1 , 12 )],
147164)
148165def test_gen_kw_config_get_priors (spec , expected ):
149166 cfg = GenKwConfig (** spec )
@@ -187,6 +204,7 @@ def test_gen_kw_config_get_priors(spec, expected):
187204 ("ERRF 1 2 0.1 0.1" , False , r"KW_NAME:MY_KEYWORD " + number_regex ),
188205 ("DERRF 10 1 2 0.1 0.1" , False , r"KW_NAME:MY_KEYWORD " + number_regex ),
189206 ("TRIANGULAR 0 0.5 1" , False , r"KW_NAME:MY_KEYWORD " + number_regex ),
207+ ("PERT 0 0.5 1" , False , r"KW_NAME:MY_KEYWORD " + number_regex ),
190208 ],
191209)
192210async def test_gen_kw_is_log_or_not (
@@ -403,6 +421,74 @@ def test_gen_kw_params_parsing(tmpdir, params, error):
403421 )
404422
405423
424+ @pytest .mark .parametrize (
425+ ("values" , "expected_scale" ),
426+ [
427+ (["0" , "0.5" , "1" ], 4.0 ),
428+ (["0" , "0.5" , "1" , "2" ], 2.0 ),
429+ ],
430+ )
431+ def test_that_pert_uses_default_or_explicit_scale (values , expected_scale ):
432+ distribution = GenKwConfig ._parse_distribution ("MYNAME" , "PERT" , values )
433+
434+ assert distribution .model_dump () == {
435+ "name" : "pert" ,
436+ "min" : 0.0 ,
437+ "mode" : 0.5 ,
438+ "max" : 1.0 ,
439+ "scale" : expected_scale ,
440+ }
441+
442+
443+ @pytest .mark .parametrize (
444+ "values" ,
445+ [
446+ ["0" , "0.5" ],
447+ ["0" , "0.5" , "1" , "4" , "5" ],
448+ ],
449+ )
450+ def test_that_pert_rejects_parameter_counts_other_than_three_or_four (values ):
451+ with pytest .raises (ConfigValidationError , match = "Incorrect number of values" ):
452+ GenKwConfig ._parse_distribution ("MYNAME" , "PERT" , values )
453+
454+
455+ def test_that_pert_requires_minimum_strictly_less_than_maximum ():
456+ with pytest .raises (
457+ ConfigValidationError ,
458+ match = r"Minimum .* must be strictly less than the maximum" ,
459+ ):
460+ GenKwConfig ._parse_distribution ("MYNAME" , "PERT" , ["1" , "1" , "1" ])
461+
462+
463+ @pytest .mark .parametrize ("mode" , ["-1" , "0" , "1" , "2" ])
464+ def test_that_pert_requires_mode_strictly_between_bounds (mode ):
465+ with pytest .raises (ConfigValidationError , match = "must be strictly between" ):
466+ GenKwConfig ._parse_distribution ("MYNAME" , "PERT" , ["0" , mode , "1" ])
467+
468+
469+ @pytest .mark .parametrize (
470+ "parameter_index" ,
471+ range (4 ),
472+ ids = ["minimum" , "mode" , "maximum" , "scale" ],
473+ )
474+ @pytest .mark .parametrize ("value" , ["nan" , "inf" , "-inf" ])
475+ def test_that_pert_requires_finite_parameters (parameter_index , value ):
476+ values = ["0" , "0.5" , "1" , "4" ]
477+ values [parameter_index ] = value
478+
479+ with pytest .raises (ConfigValidationError , match = "finite" ):
480+ GenKwConfig ._parse_distribution ("MYNAME" , "PERT" , values )
481+
482+
483+ @pytest .mark .parametrize ("scale" , ["0" , "-1" ])
484+ def test_that_pert_requires_positive_scale (scale ):
485+ with pytest .raises (
486+ ConfigValidationError ,
487+ match = r"strictly greater than 0" ,
488+ ):
489+ GenKwConfig ._parse_distribution ("MYNAME" , "PERT" , ["0" , "0.5" , "1" , scale ])
490+
491+
406492@pytest .mark .parametrize (
407493 ("params" , "xinput" , "expected" ),
408494 [
0 commit comments