def test_constructor_with_impossible_val(self): good_input = 1 good_center_input = [1, 2, 3] zero_value = 0 negative_value = -0.0000001 negative_int = -1 negative_string = "-1" # Check it handles zero with assertRaisesRegex(self, ValueError, "The value set for height was: 0"): sample_details.SampleDetails(height=zero_value, radius=good_input, center=good_center_input) # Very small negative with assertRaisesRegex(self, ValueError, "which is impossible for a physical object"): sample_details.SampleDetails(height=good_input, radius=negative_value, center=good_center_input) # Integer negative with assertRaisesRegex(self, ValueError, "The value set for height was: -1"): sample_details.SampleDetails(height=negative_int, radius=good_input, center=good_center_input) # String negative with assertRaisesRegex(self, ValueError, "The value set for radius was: -1"): sample_details.SampleDetails(height=good_input, radius=negative_string, center=good_center_input)
def test_rebin_workspace_list_defaults(self): new_bin_width = 0.5 number_of_ws = 10 ws_bin_widths = [new_bin_width] * number_of_ws ws_list = [] for i in range(number_of_ws): out_name = "test_rebin_workspace_list_defaults_" + str(i) ws_list.append(mantid.CreateSampleWorkspace(OutputWorkspace=out_name, Function='Flat background', NumBanks=1, BankPixelWidth=1, XMax=10, BinWidth=1)) # What if the item passed in is not a list err_msg_not_list = "was not a list" with assertRaisesRegex(self, RuntimeError, err_msg_not_list): common.rebin_workspace_list(workspace_list=ws_list, bin_width_list=None) with assertRaisesRegex(self, RuntimeError, err_msg_not_list): common.rebin_workspace_list(workspace_list=None, bin_width_list=[]) # What about if the lists aren't the same length with assertRaisesRegex(self, ValueError, "does not match the number of banks"): incorrect_number_bin_widths = [1] * (number_of_ws - 1) common.rebin_workspace_list(workspace_list=ws_list, bin_width_list=incorrect_number_bin_widths) # Does it return all the workspaces as a list - another unit test checks the implementation output = common.rebin_workspace_list(workspace_list=ws_list, bin_width_list=ws_bin_widths) self.assertEqual(len(output), number_of_ws) for ws in output: mantid.DeleteWorkspace(ws)
def test_rebin_workspace_list_x_start_end(self): new_start_x = 1 new_end_x = 5 new_bin_width = 0.5 number_of_ws = 10 ws_bin_widths = [new_bin_width] * number_of_ws start_x_list = [new_start_x] * number_of_ws end_x_list = [new_end_x] * number_of_ws ws_list = [] for i in range(number_of_ws): out_name = "test_rebin_workspace_list_defaults_" + str(i) ws_list.append(mantid.CreateSampleWorkspace(OutputWorkspace=out_name, Function='Flat background', NumBanks=1, BankPixelWidth=1, XMax=10, BinWidth=1)) # Are the lengths checked incorrect_length = [1] * (number_of_ws - 1) with assertRaisesRegex(self, ValueError, "The number of starting bin values"): common.rebin_workspace_list(workspace_list=ws_list, bin_width_list=ws_bin_widths, start_x_list=incorrect_length, end_x_list=end_x_list) with assertRaisesRegex(self, ValueError, "The number of ending bin values"): common.rebin_workspace_list(workspace_list=ws_list, bin_width_list=ws_bin_widths, start_x_list=start_x_list, end_x_list=incorrect_length) output_list = common.rebin_workspace_list(workspace_list=ws_list, bin_width_list=ws_bin_widths, start_x_list=start_x_list, end_x_list=end_x_list) self.assertEqual(len(output_list), number_of_ws) for ws in output_list: self.assertEqual(ws.readX(0)[0], new_start_x) self.assertEqual(ws.readX(0)[-1], new_end_x) mantid.DeleteWorkspace(ws)
def test_run_number_not_found_gives_sane_err(self): expected_val = "yamlParserTest" file_handle = self.get_temp_file_handle() file_handle.write("10-20:\n") file_handle.write(" test_key: '" + expected_val + "'\n") file_handle.write("21-:\n") file_handle.write(" test_key: '" + expected_val + "'\n") file_path = file_handle.name file_handle.close() # Test a value in the middle of 1-10 with assertRaisesRegex(self, ValueError, "Run number 5 not recognised in cycle mapping file"): yaml_parser.get_run_dictionary(run_number_string="5", file_path=file_path) # Check on edge of invalid numbers with assertRaisesRegex(self, ValueError, "Run number 9 not recognised in cycle mapping file"): yaml_parser.get_run_dictionary(run_number_string=9, file_path=file_path) # What about a range of numbers with assertRaisesRegex(self, ValueError, "Run number 2 not recognised in cycle mapping file"): yaml_parser.get_run_dictionary(run_number_string="2-8", file_path=file_path) # Check valid number still works returned_dict = yaml_parser.get_run_dictionary(run_number_string="10", file_path=file_path) self.assertEqual(returned_dict["test_key"], expected_val)
def test_cal_map_dict_helper(self): missing_key_name = "wrong_key" correct_key_name = "right_key" expected_val = 123 dict_with_key = {correct_key_name: expected_val} # Check it correctly raises with assertRaisesRegex(self, KeyError, "The field '" + missing_key_name + "' is required"): common.cal_map_dictionary_key_helper(dictionary=dict_with_key, key=missing_key_name) # Check it correctly appends the passed error message when raising appended_e_msg = "test append message" with assertRaisesRegex(self, KeyError, appended_e_msg): common.cal_map_dictionary_key_helper(dictionary=dict_with_key, key=missing_key_name, append_to_error_message=appended_e_msg) # Check that it correctly returns the key value where it exists self.assertEqual(common.cal_map_dictionary_key_helper(dictionary=dict_with_key, key=correct_key_name), expected_val) # Check it is not case sensitive different_case_name = "tEsT_key" dict_with_mixed_key = {different_case_name: expected_val} try: self.assertEqual(common.cal_map_dictionary_key_helper(dictionary=dict_with_mixed_key, key=different_case_name.lower()), expected_val) except KeyError: # It tried to use the key without accounting for the case difference self.fail("cal_map_dictionary_key_helper attempted to use a key without accounting for case")
def test_missing_property_is_detected(self): sample_properties = { "cylinder_sample_height": 4.0, "cylinder_sample_radius": 0.25, "cylinder_position": [0., 0., 0.], "chemical_formula": "V" } ws = mantid.CreateSampleWorkspace(Function='Flat background', NumBanks=1, BankPixelWidth=1, XMax=2, BinWidth=1) # Test each key one at a time for blacklisted_key in iterkeys(sample_properties): # Force python to make a shallow copy modified_dict = sample_properties.copy() modified_dict.pop(blacklisted_key) # Check that is raises an error with assertRaisesRegex( self, KeyError, "The following key was not found in the advanced configuration" ): ws = absorb_corrections.create_vanadium_sample_details_obj( config_dict=modified_dict) # Then check the error actually has the key name in it with assertRaisesRegex(self, KeyError, blacklisted_key): ws = absorb_corrections.create_vanadium_sample_details_obj( config_dict=modified_dict)
def test_generate_run_numbers_fails(self): run_input_sting = "text-string" with assertRaisesRegex(self, ValueError, "Could not generate run numbers from this input"): common.generate_run_numbers(run_number_string=run_input_sting) # Check it says what the actual string was with assertRaisesRegex(self, ValueError, run_input_sting): common.generate_run_numbers(run_number_string=run_input_sting)
def test_crop_banks_using_crop_list(self): bank_list = [] cropping_value = (0, 1000 ) # Crop to 0-1000 microseconds for unit tests cropping_value_list = [] expected_number_of_bins = cropping_value[-1] - cropping_value[0] for i in range(0, 3): out_name = "crop_banks_in_tof-" + str(i) cropping_value_list.append(cropping_value) bank_list.append( mantid.CreateSampleWorkspace(OutputWorkspace=out_name, XMin=0, XMax=1100, BinWidth=1)) # Check a list of WS and single cropping value is detected with assertRaisesRegex(self, ValueError, "The cropping values were not in a list type"): common.crop_banks_using_crop_list(bank_list=bank_list, crop_values_list=cropping_value) # Check a list of cropping values and a single workspace is detected with assertRaisesRegex(self, RuntimeError, "Attempting to use list based cropping"): common.crop_banks_using_crop_list( bank_list=bank_list[0], crop_values_list=cropping_value_list) # What about a mismatch between the number of cropping values and workspaces with assertRaisesRegex( self, RuntimeError, "The number of TOF cropping values does not match"): common.crop_banks_using_crop_list( bank_list=bank_list[1:], crop_values_list=cropping_value_list) # Check we can crop a single workspace from the list cropped_single_ws_list = common.crop_banks_using_crop_list( bank_list=[bank_list[0]], crop_values_list=[cropping_value]) self.assertEqual(cropped_single_ws_list[0].blocksize(), expected_number_of_bins) mantid.DeleteWorkspace(Workspace=cropped_single_ws_list[0]) # Check we can crop a whole list cropped_ws_list = common.crop_banks_using_crop_list( bank_list=bank_list[1:], crop_values_list=cropping_value_list[1:]) for ws in cropped_ws_list[1:]: self.assertEqual(ws.blocksize(), expected_number_of_bins) mantid.DeleteWorkspace(Workspace=ws)
def test_material_set_properties(self): bad_absorb = '-1' bad_scattering = 0 good_absorb = '1' good_scattering = 2.0 material_obj = sample_details._Material(chemical_formula='V') with assertRaisesRegex( self, ValueError, "absorption_cross_section was: -1 which is impossible for a physical " "object"): material_obj.set_material_properties( abs_cross_sect=bad_absorb, scattering_cross_sect=good_scattering) # Check the immutability flag has not been set on a failure self.assertFalse(material_obj._is_material_props_set) with assertRaisesRegex(self, ValueError, "scattering_cross_section was: 0"): material_obj.set_material_properties( abs_cross_sect=good_absorb, scattering_cross_sect=bad_scattering) # Check nothing has been set yet self.assertIsNone(material_obj.absorption_cross_section) self.assertIsNone(material_obj.scattering_cross_section) # Set the object this time material_obj.set_material_properties( abs_cross_sect=good_absorb, scattering_cross_sect=good_scattering) self.assertTrue(material_obj._is_material_props_set) self.assertEqual(material_obj.absorption_cross_section, float(good_absorb)) self.assertEqual(material_obj.scattering_cross_section, float(good_scattering)) # Check we cannot set it twice and fields do not change with assertRaisesRegex( self, RuntimeError, "The material properties have already been set"): material_obj.set_material_properties(abs_cross_sect=999, scattering_cross_sect=999) self.assertEqual(material_obj.absorption_cross_section, float(good_absorb)) self.assertEqual(material_obj.scattering_cross_section, float(good_scattering))
def test_check_enum_check_and_set_works(self): param_entry = param_map_entry.ParamMapEntry( ext_name="user_facing_name", int_name="script_facing_name", enum_class=SampleEnum) # First test we cannot set it to a different value incorrect_value_dict = {"user_facing_name": "wrong"} with assertRaisesRegex(self, ValueError, "The user specified value: 'wrong' is unknown"): instrument_settings.InstrumentSettings( param_map=[param_entry], adv_conf_dict=incorrect_value_dict) # Check that we can set a known good enum good_value_dict = {"user_facing_name": SampleEnum.a_bar} inst_obj = instrument_settings.InstrumentSettings( param_map=[param_entry], adv_conf_dict=good_value_dict) self.assertEqual(inst_obj.script_facing_name, SampleEnum.a_bar) # Next check it passes on mixed case and converts it back to the correct case different_case_dict = {"user_facing_name": SampleEnum.a_bar.lower()} inst_obj = instrument_settings.InstrumentSettings( param_map=[param_entry], adv_conf_dict=different_case_dict) self.assertEqual(inst_obj.script_facing_name, SampleEnum.a_bar, "Case is not being converted correctly")
def test_constructor_non_number_input(self): good_input = 1.0 good_center_input = [1.0, 2.0, 3.0] empty_input_value = '' char_input_value = 'a' # Check it handles empty input with assertRaisesRegex(self, ValueError, "Could not convert the height to a number"): sample_details.SampleDetails(height=empty_input_value, radius=good_input, center=good_center_input) # Does it handle bad input and tell us what we put in with assertRaisesRegex( self, ValueError, ".*to a number. The input was: '" + char_input_value + "'"): sample_details.SampleDetails(height=char_input_value, radius=good_input, center=good_center_input) # Does it indicate which field was incorrect with assertRaisesRegex(self, ValueError, "radius"): sample_details.SampleDetails(height=good_input, radius=char_input_value, center=good_center_input) # Can it handle bad center values with assertRaisesRegex(self, ValueError, "center"): sample_details.SampleDetails(height=good_input, radius=good_input, center=["", 2, 3]) # Does it throw if were not using a list for the input with assertRaisesRegex(self, ValueError, "must be specified as a list of X, Y, Z"): sample_details.SampleDetails(height=good_input, radius=good_input, center=1) # Does it throw if we are using a list of incorrect length (e.g. not 3D) with assertRaisesRegex(self, ValueError, "must have three values corresponding to"): sample_details.SampleDetails(height=good_input, radius=good_input, center=[]) with assertRaisesRegex(self, ValueError, "must have three values corresponding to"): sample_details.SampleDetails(height=good_input, radius=good_input, center=[1, 2]) with assertRaisesRegex(self, ValueError, "must have three values corresponding to"): sample_details.SampleDetails(height=good_input, radius=good_input, center=[1, 2, 3, 4])
def test_user_missing_attribute_is_detected(self): param_entry = param_map_entry.ParamMapEntry(ext_name="user_facing_name", int_name="script_facing_name") inst_settings_obj = instrument_settings.InstrumentSettings(param_map=[param_entry]) with assertRaisesRegex(self, AttributeError, "is required but was not set or passed"): foo = inst_settings_obj.script_facing_name del foo
def test_developer_missing_attribute_is_detected(self): param_entry = param_map_entry.ParamMapEntry(ext_name="user_facing_name", int_name="script_facing_name") inst_settings_obj = instrument_settings.InstrumentSettings(param_map=[param_entry]) with assertRaisesRegex(self, AttributeError, "Please contact the development team"): foo = inst_settings_obj.not_known del foo
def test_blank_file_gives_sane_err(self): file_handle = self.get_temp_file_handle() # Write nothing and close file_path = file_handle.name file_handle.close() with assertRaisesRegex(self, ValueError, "YAML files appears to be empty at"): yaml_parser.get_run_dictionary(run_number_string=1, file_path=file_path)
def test_user_missing_attribute_prints_enum_values(self): param_entry = param_map_entry.ParamMapEntry(ext_name="user_facing_name", int_name="script_facing_name", enum_class=SampleEnum) inst_settings_obj = instrument_settings.InstrumentSettings(param_map=[param_entry]) # Check it still prints the acceptable values when it fails with assertRaisesRegex(self, AttributeError, "A BAR"): foo = inst_settings_obj.script_facing_name del foo
def test_param_map_rejects_enum_missing_friendly_name(self): # Check that is the friendly name is not set it is correctly detected with assertRaisesRegex( self, RuntimeError, "'enum_friendly_name' was not set. Please contact development team." ): param_map_entry.ParamMapEntry(ext_name="user_facing_name", int_name="script_facing_name", enum_class=BadSampleEnum)
def test_yaml_sanity_check_picks_up_two_unbounded(self): # Check we can detect two unbounded ranges file_handle = self.get_temp_file_handle() file_handle.write("10-:\n") file_handle.write("20-:\n") file_path = file_handle.name file_handle.close() with assertRaisesRegex(self, ValueError, "Seen multiple unbounded keys in mapping file"): yaml_parser.get_run_dictionary(run_number_string="11", file_path=file_path)
def test_user_missing_attribute_is_detected(self): param_entry = param_map_entry.ParamMapEntry( ext_name="user_facing_name", int_name="script_facing_name") inst_settings_obj = instrument_settings.InstrumentSettings( param_map=[param_entry]) with assertRaisesRegex(self, AttributeError, "is required but was not set or passed"): foo = inst_settings_obj.script_facing_name del foo
def test_developer_missing_attribute_is_detected(self): param_entry = param_map_entry.ParamMapEntry( ext_name="user_facing_name", int_name="script_facing_name") inst_settings_obj = instrument_settings.InstrumentSettings( param_map=[param_entry]) with assertRaisesRegex(self, AttributeError, "Please contact the development team"): foo = inst_settings_obj.not_known del foo
def test_yaml_sanity_detects_val_larger_than_unbound(self): # If we have a value that is larger the the unbounded range can we detect this file_handle = self.get_temp_file_handle() file_handle.write("30-:\n") file_handle.write("35:\n") file_path = file_handle.name file_handle.close() with assertRaisesRegex(self, ValueError, "Found a run range in calibration mapping overlaps an unbounded run " "range"): yaml_parser.get_run_dictionary(run_number_string="32", file_path=file_path)
def test_subtract_summed_runs_throw_on_tof_mismatch(self): # Create a sample workspace which will have mismatched TOF range sample_ws = mantid.CreateSampleWorkspace() ws_file_name = "100" # Load POL100 # This should throw as the TOF ranges do not match with assertRaisesRegex(self, ValueError, "specified for this file do not have matching binning. Do the "): common.subtract_summed_runs(ws_to_correct=sample_ws, instrument=ISISPowderMockInst(), empty_sample_ws_string=ws_file_name) mantid.DeleteWorkspace(sample_ws)
def test_user_missing_attribute_prints_enum_values(self): param_entry = param_map_entry.ParamMapEntry( ext_name="user_facing_name", int_name="script_facing_name", enum_class=SampleEnum) inst_settings_obj = instrument_settings.InstrumentSettings( param_map=[param_entry]) # Check it still prints the acceptable values when it fails with assertRaisesRegex(self, AttributeError, "A BAR"): foo = inst_settings_obj.script_facing_name del foo
def test_file_not_found_gives_sane_err(self): # Create a file then delete it so we know it cannot exist at that path file_handle = tempfile.NamedTemporaryFile(delete=False) file_path = file_handle.name file_handle.close() os.remove(file_path) if os.path.exists(file_path): self.fail("File exists after deleting cannot continue this test") # Check the error message is there with assertRaisesRegex(self, ValueError, "Config file not found at path"): yaml_parser.get_run_dictionary(run_number_string="1", file_path=file_path)
def test_yaml_sanity_detects_val_larger_than_unbound(self): # If we have a value that is larger the the unbounded range can we detect this file_handle = self.get_temp_file_handle() file_handle.write("30-:\n") file_handle.write("35:\n") file_path = file_handle.name file_handle.close() with assertRaisesRegex( self, ValueError, "Found a run range in calibration mapping overlaps an unbounded run " "range"): yaml_parser.get_run_dictionary(run_number_string="32", file_path=file_path)
def test_dictionary_key_helper(self): good_key_name = "key_exists" bad_key_name = "key_does_not_exist" test_dictionary = {good_key_name: 123} e_msg = "test message" with self.assertRaises(KeyError): common.dictionary_key_helper(dictionary=test_dictionary, key=bad_key_name) with assertRaisesRegex(self, KeyError, e_msg): common.dictionary_key_helper(dictionary=test_dictionary, key=bad_key_name, exception_msg=e_msg) self.assertEqual(common.dictionary_key_helper(dictionary=test_dictionary, key=good_key_name), 123)
def test_run_number_not_found_gives_sane_err(self): expected_val = "yamlParserTest" file_handle = self.get_temp_file_handle() file_handle.write("10-20:\n") file_handle.write(" test_key: '" + expected_val + "'\n") file_handle.write("21-:\n") file_handle.write(" test_key: '" + expected_val + "'\n") file_path = file_handle.name file_handle.close() # Test a value in the middle of 1-10 with assertRaisesRegex( self, ValueError, "Run number 5 not recognised in cycle mapping file"): yaml_parser.get_run_dictionary(run_number_string="5", file_path=file_path) # Check on edge of invalid numbers with assertRaisesRegex( self, ValueError, "Run number 9 not recognised in cycle mapping file"): yaml_parser.get_run_dictionary(run_number_string=9, file_path=file_path) # What about a range of numbers with assertRaisesRegex( self, ValueError, "Run number 2 not recognised in cycle mapping file"): yaml_parser.get_run_dictionary(run_number_string="2-8", file_path=file_path) # Check valid number still works returned_dict = yaml_parser.get_run_dictionary(run_number_string="10", file_path=file_path) self.assertEqual(returned_dict["test_key"], expected_val)
def test_material_constructor(self): chemical_formula_one_char_element = 'V' chemical_formula_two_char_element = 'Si' chemical_formula_complex = 'V Si' # Yes, this isn't a sensible input but for our tests it will do number_density_sample = 1.234 material_obj_one_char = sample_details._Material( chemical_formula=chemical_formula_one_char_element) self.assertIsNotNone(material_obj_one_char) self.assertEqual(material_obj_one_char.chemical_formula, chemical_formula_one_char_element) self.assertIsNone(material_obj_one_char.number_density) # Also check that the absorption and scattering X sections have not been set self.assertIsNone(material_obj_one_char.absorption_cross_section) self.assertIsNone(material_obj_one_char.scattering_cross_section) self.assertFalse(material_obj_one_char._is_material_props_set) # Check if it accepts two character elements without number density material_obj_two_char = sample_details._Material( chemical_formula=chemical_formula_two_char_element) self.assertIsNotNone(material_obj_two_char) self.assertEqual(material_obj_two_char.chemical_formula, chemical_formula_two_char_element) self.assertIsNone(material_obj_two_char.number_density) # Check it stores number density if passed material_obj_number_density = sample_details._Material( chemical_formula=chemical_formula_two_char_element, number_density=number_density_sample) self.assertEqual(material_obj_number_density.number_density, number_density_sample) # Check that it raises an error if we have a non-elemental formula without number density with assertRaisesRegex( self, ValueError, "A number density formula must be set on a chemical formula"): sample_details._Material(chemical_formula=chemical_formula_complex) # Check it constructs if it is given the number density too material_obj_num_complex_formula = sample_details._Material( chemical_formula=chemical_formula_complex, number_density=number_density_sample) self.assertEqual(material_obj_num_complex_formula.chemical_formula, chemical_formula_complex) self.assertEqual(material_obj_num_complex_formula.number_density, number_density_sample)
def test_set_material_properties(self): sample_details_obj = sample_details.SampleDetails(height=1.0, radius=1.0, center=[2, 3, 5]) self.assertIsNone(sample_details_obj.material_object) # Check we cannot set a material property without setting the underlying material with assertRaisesRegex(self, RuntimeError, "The material has not been set"): sample_details_obj.set_material_properties( absorption_cross_section=1.0, scattering_cross_section=2.0) # Check that with a material object we are allowed to set material properties sample_details_obj.set_material(chemical_formula='V') # We will test the immutability of the underlying object elsewhere sample_details_obj.set_material_properties( scattering_cross_section=2.0, absorption_cross_section=3.0)
def test_check_enum_check_and_set_works(self): param_entry = param_map_entry.ParamMapEntry(ext_name="user_facing_name", int_name="script_facing_name", enum_class=SampleEnum) # First test we cannot set it to a different value incorrect_value_dict = {"user_facing_name": "wrong"} with assertRaisesRegex(self, ValueError, "The user specified value: 'wrong' is unknown"): instrument_settings.InstrumentSettings(param_map=[param_entry], adv_conf_dict=incorrect_value_dict) # Check that we can set a known good enum good_value_dict = {"user_facing_name": SampleEnum.a_bar} inst_obj = instrument_settings.InstrumentSettings(param_map=[param_entry], adv_conf_dict=good_value_dict) self.assertEqual(inst_obj.script_facing_name, SampleEnum.a_bar) # Next check it passes on mixed case and converts it back to the correct case different_case_dict = {"user_facing_name": SampleEnum.a_bar.lower()} inst_obj = instrument_settings.InstrumentSettings(param_map=[param_entry], adv_conf_dict=different_case_dict) self.assertEqual(inst_obj.script_facing_name, SampleEnum.a_bar, "Case is not being converted correctly")
def test_set_material(self): sample_details_obj = sample_details.SampleDetails(height=1.0, radius=1.0, center=[2, 3, 4]) # Check that we can only set a material once. We will test the underlying class elsewhere sample_details_obj.set_material(chemical_formula='V') self.assertIsNotNone(sample_details_obj.material_object) # Check that the material is now immutable with assertRaisesRegex( self, RuntimeError, "The material has already been set to the above details"): sample_details_obj.set_material(chemical_formula='V') # Check resetting it works sample_details_obj.reset_sample_material() self.assertIsNone(sample_details_obj.material_object) # And ensure setting it for a second time works sample_details_obj.set_material(chemical_formula='V') self.assertIsNotNone(sample_details_obj.material_object)
def test_param_map_rejects_enum_missing_friendly_name(self): # Check that is the friendly name is not set it is correctly detected with assertRaisesRegex(self, RuntimeError, "'enum_friendly_name' was not set. Please contact development team."): param_map_entry.ParamMapEntry(ext_name="user_facing_name", int_name="script_facing_name", enum_class=BadSampleEnum)