From 65baa9d99d1c6f94da44f02d3e479489ff5c6be3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5ns=20Magnusson?= Date: Wed, 1 Jul 2020 14:37:50 +0200 Subject: [PATCH] Adatps validation behaviour to marshmallow > 3.0. Adds tests --- tests/mip/test_mip_config.py | 149 +++++++++++++++++++++++++++++++++++ trailblazer/mip/config.py | 14 +++- 2 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 tests/mip/test_mip_config.py diff --git a/tests/mip/test_mip_config.py b/tests/mip/test_mip_config.py new file mode 100644 index 00000000..8eef6757 --- /dev/null +++ b/tests/mip/test_mip_config.py @@ -0,0 +1,149 @@ +"""Tests for the config functionality""" +import pytest + +from trailblazer.mip import config as tb_config +from trailblazer.exc import ConfigError + +def test_validate_config(): + """Test to validate a correct config""" + # GIVEN a correct config + sample = dict( + sample_id = "sample", + analysis_type = 'wes', + father = '0', + mother = '0', + phenotype = 'affected', + sex = 'male', + expected_coverage = 15, + capture_kit = 'agilent_sureselect_cre.v1', + ) + + config = dict( + case = "a_case", + default_gene_panels = ["a_panel"], + samples = [sample], + ) + + # WHEN validating the config + errors = tb_config.ConfigHandler.validate_config(config) + + # THEN assert the errors is a dict + assert isinstance(errors, dict) + + # THEN assert there where no errors + assert errors == {} + +def test_validate_config_invalid_analysis_type(): + """Test to validate a invalid config with wrong analysis type""" + # GIVEN a correct config + sample = dict( + sample_id = "sample", + analysis_type = 'nonexisting', + father = '0', + mother = '0', + phenotype = 'affected', + sex = 'male', + expected_coverage = 15, + capture_kit = 'agilent_sureselect_cre.v1', + ) + + config = dict( + case = "a_case", + default_gene_panels = ["a_panel"], + samples = [sample], + ) + + # WHEN validating the config + with pytest.raises(ConfigError): + # THEN assert a config error is raised + tb_config.ConfigHandler.validate_config(config) + +def test_validate_config_unknown_field(): + """Test to validate a config with a unspecified field. + + This should work since we allow unspecified fields + """ + # GIVEN a correct config with a extra field + sample = dict( + sample_id = "sample", + sample_display_name = "ASAMPLENAME", + analysis_type = 'wes', + father = '0', + mother = '0', + phenotype = 'affected', + sex = 'male', + expected_coverage = 15, + capture_kit = 'agilent_sureselect_cre.v1', + ) + + config = dict( + case = "a_case", + default_gene_panels = ["a_panel"], + samples = [sample], + ) + + # WHEN validating the config + errors = tb_config.ConfigHandler.validate_config(config) + + # THEN assert the errors is a dict + assert isinstance(errors, dict) + + # THEN assert there where one error that could pass + assert len(errors) == 1 + +def test_validate_config_unknown_field_and_missing_sample_id(): + """Test to validate a config with a unspecified field and a missing mandatory field. + + This should raise exception since we do not allow missing mandatory fields + """ + # GIVEN a config with missing sample_id and an extra field + sample = dict( + sample_display_name = "ASAMPLENAME", + analysis_type = 'wes', + father = '0', + mother = '0', + phenotype = 'affected', + sex = 'male', + expected_coverage = 15, + capture_kit = 'agilent_sureselect_cre.v1', + ) + + config = dict( + case = "a_case", + default_gene_panels = ["a_panel"], + samples = [sample], + ) + + # WHEN validating the config + with pytest.raises(ConfigError): + # THEN assert a config error is raised + tb_config.ConfigHandler.validate_config(config) + +def test_validate_config_unknown_field_and_invalid_analysis_type(): + """Test to validate a config with a unspecified field and a missing mandatory field. + + This should raise exception since we do not allow wrong analysis types + """ + # GIVEN a config with wrong analysis type and an extra field + sample = dict( + sample_id = "sample", + sample_display_name = "ASAMPLENAME", + analysis_type = 'nonexisting', + father = '0', + mother = '0', + phenotype = 'affected', + sex = 'male', + expected_coverage = 15, + capture_kit = 'agilent_sureselect_cre.v1', + ) + + config = dict( + case = "a_case", + default_gene_panels = ["a_panel"], + samples = [sample], + ) + + # WHEN validating the config + with pytest.raises(ConfigError): + # THEN assert a config error is raised + tb_config.ConfigHandler.validate_config(config) diff --git a/trailblazer/mip/config.py b/trailblazer/mip/config.py index 4ddf7480..5cfc0f35 100644 --- a/trailblazer/mip/config.py +++ b/trailblazer/mip/config.py @@ -80,15 +80,25 @@ def validate_config(data: dict, pipeline: str = None) -> dict: else: errors = ConfigSchema().validate(data) if errors: + hard_error = False for field, messages in errors.items(): if isinstance(messages, dict): for level, sample_errors in messages.items(): - sample_id = data['samples'][level]['sample_id'] + try: + sample_id = data['samples'][level]['sample_id'] + except KeyError: + raise ConfigError('missing sample id') + for sub_field, sub_messages in sample_errors.items(): + if sub_messages != ["Unknown field."]: + hard_error = True LOG.error(f"{sample_id} -> {sub_field}: {', '.join(sub_messages)}") else: + hard_error = True LOG.error(f"{field}: {', '.join(messages)}") - raise ConfigError('invalid config input', errors=errors) + if hard_error: + raise ConfigError('invalid config input', errors=errors) + return errors @staticmethod def prepare_config(data: dict) -> dict: