Skip to content

Commit

Permalink
test transform frame using null transformation
Browse files Browse the repository at this point in the history
  • Loading branch information
KerstenBreuer committed Dec 7, 2023
1 parent 7d1a0ff commit f77a70a
Show file tree
Hide file tree
Showing 4 changed files with 426 additions and 0 deletions.
17 changes: 17 additions & 0 deletions tests/schemapack_/transform/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright 2021 - 2023 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
# for the German Human Genome-Phenome Archive (GHGA)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""Test the transform sub-package."""
221 changes: 221 additions & 0 deletions tests/schemapack_/transform/test_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
# Copyright 2021 - 2023 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
# for the German Human Genome-Phenome Archive (GHGA)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""Test the base module."""


import pytest
from pydantic import ValidationError

from metldata.schemapack_.builtin_transformations.null import NULL_TRANSFORMATION
from metldata.schemapack_.transform.base import (
WorkflowDefinition,
WorkflowStep,
)


def test_workflow_definition_invalid_step_refs():
"""Test that an invalid step reference raises an error."""
with pytest.raises(ValidationError):
WorkflowDefinition(
description="A workflow for testing.",
steps={
"step1": WorkflowStep(
description="A dummy step.",
transformation_definition=NULL_TRANSFORMATION,
input=None,
),
"step2": WorkflowStep(
description="Another dummy step.",
transformation_definition=NULL_TRANSFORMATION,
input="non_existing_step",
),
},
artifacts={
"step1_output": "step1",
"step2_output": "step2",
},
)


def test_workflow_definition_invalid_multiple_first_steps():
"""Test that specifing multiple steps without input raises an exeception."""
with pytest.raises(ValidationError):
WorkflowDefinition(
description="A workflow for testing.",
steps={
"step1": WorkflowStep(
description="A dummy step.",
transformation_definition=NULL_TRANSFORMATION,
input=None,
),
"step2": WorkflowStep(
description="Another dummy step.",
transformation_definition=NULL_TRANSFORMATION,
input=None,
),
},
artifacts={
"step1_output": "step1",
"step2_output": "step2",
},
)


def test_workflow_definition_invalid_artifacts():
"""Test that artifacts referencing non-existing steps raise an exception."""
with pytest.raises(ValidationError):
WorkflowDefinition(
description="A workflow for testing.",
steps={
"step1": WorkflowStep(
description="A dummy step.",
transformation_definition=NULL_TRANSFORMATION,
input=None,
),
"step2": WorkflowStep(
description="Another dummy step.",
transformation_definition=NULL_TRANSFORMATION,
input="step1",
),
},
artifacts={
"step1_output": "non_existing_step",
"step2_output": "step2",
},
)


def test_workflow_definition_step_order_happy():
"""Test that the step order is correctly inferred from the workflow definition."""

workflow_definition = WorkflowDefinition(
description="A workflow for testing.",
steps={
"step3": WorkflowStep(
description="A test step.",
transformation_definition=NULL_TRANSFORMATION,
input="step2",
),
"step2": WorkflowStep(
description="A test step.",
transformation_definition=NULL_TRANSFORMATION,
input="step1",
),
"step1": WorkflowStep(
description="A test step.",
transformation_definition=NULL_TRANSFORMATION,
input=None,
),
"step4": WorkflowStep(
description="A test step.",
transformation_definition=NULL_TRANSFORMATION,
input="step2",
),
},
artifacts={
"output3": "step3",
"output4": "step4",
},
)

assert workflow_definition.step_order in (
[
"step1",
"step2",
"step3",
"step4",
],
[
"step1",
"step2",
"step4",
"step3",
],
)


def test_workflow_definition_step_order_circular():
"""Test that initialization of a WorkflowDefinition with a circularly dependent
steps fails."""

workflow_definition = WorkflowDefinition(
description="A workflow for testing.",
steps={
"step1": WorkflowStep(
description="A test step.",
transformation_definition=NULL_TRANSFORMATION,
input=None,
),
"step2": WorkflowStep(
description="A test step.",
transformation_definition=NULL_TRANSFORMATION,
input="step4",
),
"step3": WorkflowStep(
description="A test step.",
transformation_definition=NULL_TRANSFORMATION,
input="step2",
),
"step4": WorkflowStep(
description="A test step.",
transformation_definition=NULL_TRANSFORMATION,
input="step3",
),
},
artifacts={
"output3": "step3",
"output4": "step4",
},
)

with pytest.raises(RuntimeError):
_ = workflow_definition.step_order


def test_workflow_definition_config_cls():
"""Test that the config_cls of the WorkflowDefinition generates a concatenated
config class correctly."""

null_workflow = WorkflowDefinition(
description="A workflow for testing.",
steps={
"step1": WorkflowStep(
description="A dummy step.",
transformation_definition=NULL_TRANSFORMATION,
input=None,
),
"step2": WorkflowStep(
description="Another dummy step.",
transformation_definition=NULL_TRANSFORMATION,
input="step1",
),
},
artifacts={
"step1_output": "step1",
"step2_output": "step2",
},
)

config_fields = null_workflow.config_cls.model_fields

assert "step1" in config_fields
assert "step2" in config_fields
assert (
config_fields["step1"].annotation
== config_fields["step2"].annotation
== NULL_TRANSFORMATION.config_cls
)
94 changes: 94 additions & 0 deletions tests/schemapack_/transform/test_handling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Copyright 2021 - 2023 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
# for the German Human Genome-Phenome Archive (GHGA)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""Test the handling module. Only edge cases that are not covered by tests
with builtin transformations are tested here."""

import pytest

from metldata.builtin_transformations.infer_references.main import (
REFERENCE_INFERENCE_TRANSFORMATION,
ReferenceInferenceConfig,
)
from metldata.model_utils.essentials import MetadataModel
from metldata.transform.base import (
MetadataModelAssumptionError,
MetadataModelTransformationError,
TransformationDefinition,
)
from metldata.transform.handling import TransformationHandler
from tests.fixtures.metadata_models import VALID_ADVANCED_METADATA_MODEL

VALID_EXAMPLE_CONFIG = ReferenceInferenceConfig(
inferred_ref_map={
"Experiment": {
"files": { # type: ignore
"path": "Experiment(samples)>Sample(files)>File",
"multivalued": True,
}
}
}
)


def test_transformation_handler_assumption_error():
"""Test using the TransformationHandling when model assumptions are not met."""

# make transformation definition always raise an MetadataModelAssumptionError:
def always_failing_assumptions(
model: MetadataModel, config: ReferenceInferenceConfig
):
"""A function that always raises a MetadataModelAssumptionError."""
raise MetadataModelAssumptionError

transformation = TransformationDefinition(
config_cls=REFERENCE_INFERENCE_TRANSFORMATION.config_cls,
check_model_assumptions=always_failing_assumptions,
transform_model=REFERENCE_INFERENCE_TRANSFORMATION.transform_model,
metadata_transformer_factory=REFERENCE_INFERENCE_TRANSFORMATION.metadata_transformer_factory,
)

with pytest.raises(MetadataModelAssumptionError):
_ = TransformationHandler(
transformation_definition=transformation,
transformation_config=VALID_EXAMPLE_CONFIG,
original_model=VALID_ADVANCED_METADATA_MODEL,
)


def test_transformation_handler_model_transformation_error():
"""Test using the TransformationHandling when model transformation fails."""

# make transformation definition always raise an MetadataModelAssumptionError:
def always_failing_transformation(
original_model: MetadataModel, config: ReferenceInferenceConfig
):
"""A function that always raises a MetadataModelTransformationError."""
raise MetadataModelTransformationError

transformation = TransformationDefinition(
config_cls=REFERENCE_INFERENCE_TRANSFORMATION.config_cls,
check_model_assumptions=REFERENCE_INFERENCE_TRANSFORMATION.check_model_assumptions,
transform_model=always_failing_transformation,
metadata_transformer_factory=REFERENCE_INFERENCE_TRANSFORMATION.metadata_transformer_factory,
)

with pytest.raises(MetadataModelTransformationError):
_ = TransformationHandler(
transformation_definition=transformation,
transformation_config=VALID_EXAMPLE_CONFIG,
original_model=VALID_ADVANCED_METADATA_MODEL,
)
Loading

0 comments on commit f77a70a

Please sign in to comment.