def test_material_attachment(): """Test that a material can be attached to a measurement, and the connection survives serde.""" cake = MaterialRun('Final Cake') mass = MeasurementRun('Weigh cake', material=cake) mass_data = mass.dump() mass_copy = MeasurementRun.build(mass_data) assert mass_copy == mass
def test_soft_measurement_material_attachment(): """Test that soft attachments are formed from materials to measurements.""" cake = MaterialRun("A cake") smell_test = MeasurementRun("use your nose", material=cake, properties=[ Property( name="Smell", value=DiscreteCategorical("yummy")) ]) taste_test = MeasurementRun("taste", material=cake) assert cake.measurements == [smell_test, taste_test]
def test_simple_deserialization(valid_data): """Ensure that a deserialized Measurement Run looks sane.""" measurement_run: MeasurementRun = MeasurementRun.build(valid_data) assert measurement_run.uids == {'id': valid_data['uids']['id']} assert measurement_run.name == 'Taste test' assert measurement_run.notes is None assert measurement_run.tags == [] assert measurement_run.conditions == [] assert measurement_run.parameters == [] assert measurement_run.properties[0] == Property('sweetness', origin="measured", value=NominalInteger(7)) assert measurement_run.properties[1] == Property('fluffiness', origin="measured", value=NominalInteger(10)) assert measurement_run.file_links == [] assert measurement_run.template is None assert measurement_run.material == MaterialRun( 'sponge cake', uids={'id': valid_data['material']['uids']['id']}, sample_type='experimental') assert measurement_run.material.audit_info == AuditInfo( **valid_data['material']['audit_info']) assert measurement_run.material.dataset == UUID( valid_data['material']['dataset']) assert measurement_run.spec is None assert measurement_run.typ == 'measurement_run' assert measurement_run.audit_info == AuditInfo(**valid_data['audit_info']) assert measurement_run.dataset == UUID(valid_data['dataset'])
def test_serialization(valid_data): """Ensure that a serialized Measurement Run looks sane.""" measurement_run: MeasurementRun = MeasurementRun.build(valid_data) serialized = measurement_run.dump() valid_data['material'].pop('audit_info') valid_data['material'].pop('dataset') valid_data.pop('audit_info') valid_data.pop('dataset') assert serialized == valid_data
def test_list_validation(): """Test that lists are validated by gemd.""" with pytest.raises(ValueError): # labels must be a list of string, but contains an int IngredientSpec(labels=["Label 1", 17], name="foo") ingredient = IngredientSpec(labels=["Label 1", "label 2"], name="foo") with pytest.raises(TypeError): # cannot append an int to a list of strings ingredient.labels.append(17) with pytest.raises(ValueError): # list of conditions cannot contain a property MeasurementRun("A measurement", conditions=[Property("not a condition")])
def test_register_data_concepts(dataset): """Check that register routes to the correct collections""" expected = { MaterialTemplateCollection: MaterialTemplate("foo"), MaterialSpecCollection: MaterialSpec("foo"), MaterialRunCollection: MaterialRun("foo"), ProcessTemplateCollection: ProcessTemplate("foo"), ProcessSpecCollection: ProcessSpec("foo"), ProcessRunCollection: ProcessRun("foo"), MeasurementTemplateCollection: MeasurementTemplate("foo"), MeasurementSpecCollection: MeasurementSpec("foo"), MeasurementRunCollection: MeasurementRun("foo"), IngredientSpecCollection: IngredientSpec("foo"), IngredientRunCollection: IngredientRun(), PropertyTemplateCollection: PropertyTemplate("bar", bounds=IntegerBounds(0, 1)), ParameterTemplateCollection: ParameterTemplate("bar", bounds=IntegerBounds(0, 1)), ConditionTemplateCollection: ConditionTemplate("bar", bounds=IntegerBounds(0, 1)) } for collection, obj in expected.items(): assert len(obj.uids) == 0 registered = dataset.register(obj) assert len(obj.uids) == 1 assert len(registered.uids) == 1 assert basename(dataset.session.calls[-1].path) == basename( collection._path_template) for pair in obj.uids.items(): assert pair[1] == registered.uids[pair[0]]
def test_register_all_data_concepts(dataset): """Check that register_all registers everything and routes to all collections""" bounds = IntegerBounds(0, 1) property_template = PropertyTemplate("bar", bounds=bounds) parameter_template = ParameterTemplate("bar", bounds=bounds) condition_template = ConditionTemplate("bar", bounds=bounds) foo_process_template = ProcessTemplate( "foo", conditions=[[condition_template, bounds]], parameters=[[parameter_template, bounds]]) foo_process_spec = ProcessSpec("foo", template=foo_process_template) foo_process_run = ProcessRun("foo", spec=foo_process_spec) foo_material_template = MaterialTemplate( "foo", properties=[[property_template, bounds]]) foo_material_spec = MaterialSpec("foo", template=foo_material_template, process=foo_process_spec) foo_material_run = MaterialRun("foo", spec=foo_material_spec, process=foo_process_run) baz_template = MaterialTemplate("baz") foo_measurement_template = MeasurementTemplate( "foo", conditions=[[condition_template, bounds]], parameters=[[parameter_template, bounds]], properties=[[property_template, bounds]]) foo_measurement_spec = MeasurementSpec("foo", template=foo_measurement_template) foo_measurement_run = MeasurementRun("foo", spec=foo_measurement_spec, material=foo_material_run) foo_ingredient_spec = IngredientSpec("foo", material=foo_material_spec, process=foo_process_spec) foo_ingredient_run = IngredientRun(spec=foo_ingredient_spec, material=foo_material_run, process=foo_process_run) baz_run = MeasurementRun("baz") # worst order possible expected = { foo_ingredient_run: IngredientRunCollection, foo_ingredient_spec: IngredientSpecCollection, foo_measurement_run: MeasurementRunCollection, foo_measurement_spec: MeasurementSpecCollection, foo_measurement_template: MeasurementTemplateCollection, foo_material_run: MaterialRunCollection, foo_material_spec: MaterialSpecCollection, foo_material_template: MaterialTemplateCollection, foo_process_run: ProcessRunCollection, foo_process_spec: ProcessSpecCollection, foo_process_template: ProcessTemplateCollection, baz_template: MaterialTemplateCollection, baz_run: MeasurementRunCollection, property_template: PropertyTemplateCollection, parameter_template: ParameterTemplateCollection, condition_template: ConditionTemplateCollection } for obj in expected: assert len(obj.uids) == 0 # All should be without ids registered = dataset.register_all(expected.keys()) assert len(registered) == len(expected) seen_ids = set() for obj in expected: assert len(obj.uids) == 1 # All should now have exactly 1 id for pair in obj.uids.items(): assert pair not in seen_ids # All ids are different seen_ids.add(pair) for obj in registered: for pair in obj.uids.items(): assert pair in seen_ids # registered items have the same ids call_basenames = [ call.path.split('/')[-2] for call in dataset.session.calls ] collection_basenames = [ basename(collection._path_template) for collection in expected.values() ] assert set(call_basenames) == set(collection_basenames) assert len(set(call_basenames)) == len( call_basenames) # calls are batched internally # spot check order. Does not check every constraint assert call_basenames.index( basename( IngredientRunCollection._path_template)) > call_basenames.index( basename(IngredientSpecCollection._path_template)) assert call_basenames.index(basename( MaterialRunCollection._path_template)) > call_basenames.index( basename(MaterialSpecCollection._path_template)) assert call_basenames.index( basename( MeasurementRunCollection._path_template)) > call_basenames.index( basename(MeasurementSpecCollection._path_template)) assert call_basenames.index(basename( ProcessRunCollection._path_template)) > call_basenames.index( basename(ProcessSpecCollection._path_template)) assert call_basenames.index(basename( MaterialSpecCollection._path_template)) > call_basenames.index( basename(MaterialTemplateCollection._path_template)) assert call_basenames.index( basename( MeasurementSpecCollection._path_template)) > call_basenames.index( basename(MeasurementTemplateCollection._path_template)) assert call_basenames.index(basename( ProcessSpecCollection._path_template)) > call_basenames.index( basename(ProcessTemplateCollection._path_template)) assert call_basenames.index(basename( MaterialSpecCollection._path_template)) > call_basenames.index( basename(ProcessSpecCollection._path_template)) assert call_basenames.index(basename( MaterialSpecCollection._path_template)) > call_basenames.index( basename(MeasurementSpecCollection._path_template)) assert call_basenames.index( basename(MeasurementTemplateCollection._path_template) ) > call_basenames.index( basename(ConditionTemplateCollection._path_template)) assert call_basenames.index( basename(MeasurementTemplateCollection._path_template) ) > call_basenames.index( basename(ParameterTemplateCollection._path_template)) assert call_basenames.index( basename( MaterialTemplateCollection._path_template)) > call_basenames.index( basename(PropertyTemplateCollection._path_template))
def test_serialization(valid_data): """Ensure that a serialized Measurement Run looks sane.""" measurement_run: MeasurementRun = MeasurementRun.build(valid_data) serialized = measurement_run.dump() assert serialized == valid_data
def test_object_validation(): """Test that an object pointing to another object is validated.""" meas = MeasurementRun("A measurement") with pytest.raises(TypeError): MaterialRun("A cake", process=meas)