def test_full_round_trip(): """ This test makes sure that it can read a full record, save it as JSON, and then read it back again """ record = ExxonDataReader.read_excel_file( example_dir / "Crude_Oil_HOOPS_Blend_assay_xls.xlsx") assert record[0][0] == "ExxonMobil" oil = ExxonMapper(('HOOPS Blend Example', record)) assert oil.metadata.name == 'HOOPS Blend Example' print(oil.oil_id) filename = example_dir / "ExampleOutput.json" oil.to_file(filename) oil2 = Oil.from_file(filename) for bc2, bc in zip(oil2.sub_samples[0].bulk_composition, oil.sub_samples[0].bulk_composition): assert bc2 == bc assert oil2.sub_samples[0].bulk_composition == oil.sub_samples[ 0].bulk_composition assert oil2.sub_samples[0].industry_properties == oil.sub_samples[ 0].industry_properties assert oil2 == oil
def test_industry_properties_units(self, prop, unit, unit_type): """ Data points that are classified in industry properties: - Total Acid Number (Neutralization Number) - Reid Vapor Pressure - Aniline Point - Cetane Index - Vanadium - Cloud Point - Smoke Point - Conradson Carbon Residue - Conradson Residuum (Vacuum Residue) - Gel Point (Freeze Point) """ # just check the zeroth one: print("testing:", prop) for sample in ExxonMapper(self.record).sub_samples: print(sample.industry_properties) for p in sample.industry_properties: print(f"\n{p.name=}") print(f"{prop=}") if p.name == prop: measurement = p.measurement print("checking units of:", prop) assert measurement.unit == unit assert measurement.unit_type == unit_type return continue assert False
def test_save_to_json(self): """ Save an example .json file. This is not so much a test, but a job to provide sample data that people can look at. """ mapper = ExxonMapper(self.record) py_json = mapper.py_json() py_json['status'] = [] filename = 'EX-Example-Record.json' file_path = os.path.sep.join( adios_db.__file__.split(os.path.sep)[:-3] + ['examples', filename]) print(f'saving to: {file_path}') with open(file_path, 'w', encoding="utf-8") as fd: json.dump(py_json, fd, indent=4, sort_keys=True)
def test_dist_cuts(self, samp_ind, cut_index, fraction, temp_f): samples = ExxonMapper(self.record).sub_samples cut = samples[samp_ind].distillation_data.cuts[cut_index] assert cut.fraction.value == fraction assert isclose(cut.vapor_temp.value, sigfigs(uc.convert("F", "C", temp_f), 5), rel_tol=1e-4)
def test_dist_end_point(self, sample_idx, expected): samples = ExxonMapper(self.record).sub_samples if expected is None: assert samples[sample_idx].distillation_data.end_point is None else: expected_c = sigfigs(uc.convert("F", "C", expected), 5) end_point = samples[sample_idx].distillation_data.end_point assert isclose(end_point.value, expected_c, rel_tol=1e-4) assert end_point.unit == 'C'
def test_kinematic_viscosities(self, sample_idx, viscosity_idx, expected): samples = ExxonMapper(self.record).sub_samples sample = samples[sample_idx] phys = sample.physical_properties viscosity = phys.kinematic_viscosities[viscosity_idx] # viscosity tests # whole oil assert viscosity.viscosity.value == expected assert viscosity.viscosity.unit == "cSt" for sample in samples: assert len(sample.physical_properties.dynamic_viscosities) == 0
def test_bulk_composition(self, attr, indexes, values): """ Data points that are classified in bulk composition: - Sulphur - Naphthenes - Paraffins - Nickel - Vanadium - Carbon - Hydrogen - Mercaptan Sulfur - Nitrogen - Calcium - Hydrogen Sulfide - Salt content Notes: - These values are now kept in a list of compounds held by the bulk_composition attribute - Ideally, the name & groups of each compound would have the original field text from the datasheet. This is not the case at present. """ samples = ExxonMapper(self.record).sub_samples for i, val in zip(indexes, values): filter_list = [ c for c in samples[i].bulk_composition if c.name == attr ] if val is None: assert len(filter_list) == 0 else: assert len(filter_list) == 1 compound = filter_list[0] assert isclose(compound.measurement.value, values[i], rel_tol=1e-4)
def test_sara(self, attr, indexes, values): """ Test the sara attributes: - Aromatics - Asphaltenes Note: saturates and resins are not found in the Exxon Assays Note: We have decided that instead of C7 asphaltenes & aromatics going into SARA, we will put them into the bulk_composition list. """ samples = ExxonMapper(self.record).sub_samples for i, val in zip(indexes, values): sara = samples[i].SARA if val is None: assert getattr(sara, attr) is None else: sara_attr = getattr(sara, attr) assert isclose(sara_attr.value, values[i], rel_tol=1e-4)
def test_industry_properties(self, attr, indexes, values): """ Data points that are classified in industry properties: - Total Acid Number (Neutralization Number) - Reid Vapor Pressure - Aniline Point - Cetane Index - Vanadium - Cloud Point - Smoke Point - Conradson Carbon Residue - Conradson Residuum (Vacuum Residue) - Gel Point (Freeze Point) Notes: - These values are kept in a list of attributes held by the industry_properties attribute - Ideally, the name & groups of each compound would have the original field text from the datasheet. This is not the case at present. """ samples = ExxonMapper(self.record).sub_samples for i, val in zip(indexes, values): filter_list = [ c for c in samples[i].industry_properties if c.name == attr ] if val is None: assert len(filter_list) == 0 else: assert len(filter_list) == 1 compound = filter_list[0] assert isclose(compound.measurement.value, values[i], rel_tol=1e-4)
def test_header(self): oil = ExxonMapper(self.record) assert oil.metadata.name == 'HOOPS Blend' assert oil.metadata.reference.reference.startswith("ExxonMobil") assert oil.metadata.API == 35.2
def test_init(self): with pytest.raises(TypeError): _mapper = ExxonMapper()
def test_sample_ids(self, index, expected): samples = ExxonMapper(self.record).sub_samples assert len(samples) == 8 assert samples[index].metadata.name == expected['name'] assert samples[index].metadata.short_name == expected['short_name']
def test_no_cuts_in_butane(self): assert (ExxonMapper( self.record).sub_samples[1].distillation_data.cuts == [])
def test_dist_type(self): for sample in ExxonMapper(self.record).sub_samples: assert sample.distillation_data.type == 'volume fraction'
def test_boiling_point_range(self, index, expected): samples = ExxonMapper(self.record).sub_samples assert len(samples) == 8 assert samples[index].metadata.boiling_point_range == expected
def test_dist_cuts_units(self): for sample in ExxonMapper(self.record).sub_samples: for cut in sample.distillation_data.cuts: assert cut.vapor_temp.unit == "C" assert cut.fraction.unit == "%"
def test_cut_volume(self, index, expected): samples = ExxonMapper(self.record).sub_samples assert samples[index].cut_volume == expected
def test_densities(self, sample_idx, density_idx, expected): samples = ExxonMapper(self.record).sub_samples sample = samples[sample_idx] density = sample.physical_properties.densities[density_idx] assert isclose(density.density.value, expected, rel_tol=1e-3)
def test_init_invalid(self): with pytest.raises(TypeError): _mapper = ExxonMapper(None)
def test_dynamic_viscosities(self): samples = ExxonMapper(self.record).sub_samples for sample in samples: # no dynamic viscosities in the Exxon Assays assert len(sample.physical_properties.dynamic_viscosities) == 0