diff --git a/.github/workflows/tests-on-push.yml b/.github/workflows/tests-on-push.yml index d97ee208f..02be5e766 100644 --- a/.github/workflows/tests-on-push.yml +++ b/.github/workflows/tests-on-push.yml @@ -55,6 +55,16 @@ jobs: uses: ./.github/actions/setup - name: unittests run: poetry exec unittests + + integration-tests: + runs-on: ubuntu-latest + steps: + - name: Checkout dsp-tools repo + uses: actions/checkout@v4 + - name: Install poetry, python, and dependencies + uses: ./.github/actions/setup + - name: integration-tests + run: poetry exec integration-tests benchmarking: diff --git a/pyproject.toml b/pyproject.toml index 01578de43..77a2147a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -99,6 +99,7 @@ ruff-check-github = """ ruff-format = "ruff format ." mypy = "mypy ." unittests = "pytest test/unittests/" +integration-tests = "pytest test/integration/" e2e-tests = "pytest test/e2e/" bump-version = """ # get current version, append ".postN" (N=no. of commits since last release), write back into pyproject.toml diff --git a/test/integration/__init__.py b/test/integration/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/integration/commands/__init__.py b/test/integration/commands/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/integration/commands/excel2json/__init__.py b/test/integration/commands/excel2json/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/unittests/commands/excel2json/test_lists.py b/test/integration/commands/excel2json/test_lists.py similarity index 100% rename from test/unittests/commands/excel2json/test_lists.py rename to test/integration/commands/excel2json/test_lists.py diff --git a/test/unittests/commands/excel2json/test_project.py b/test/integration/commands/excel2json/test_project.py similarity index 100% rename from test/unittests/commands/excel2json/test_project.py rename to test/integration/commands/excel2json/test_project.py diff --git a/test/integration/commands/excel2json/test_properties.py b/test/integration/commands/excel2json/test_properties.py new file mode 100644 index 000000000..445542c12 --- /dev/null +++ b/test/integration/commands/excel2json/test_properties.py @@ -0,0 +1,369 @@ +import re +import unittest + +import jsonpath_ng +import pytest + +from dsp_tools.commands.excel2json import properties as e2j +from dsp_tools.models.exceptions import InputError + +excelfile = "testdata/excel2json/excel2json_files/test-name (test_label)/properties.xlsx" +output_from_method, _ = e2j.excel2properties(excelfile, None) + + +# ruff: noqa: PT009 (pytest-unittest-assertion) (remove this line when pytest is used instead of unittest) +class TestValidateProperties: + # it is not possible to call the method to be tested directly. + # So let's make a reference to it, so that it can be found by the usage search + lambda _: e2j._validate_properties_section_in_json([], "file") + + def test_invalid_super(self) -> None: + expected_msg = re.escape( + "\nThe Excel file " + "'testdata/invalid-testdata/excel2json/properties-invalid-super.xlsx' did not pass validation.\n" + " Section of the problem: 'Properties'\n" + " Problematic property: 'hasGeoname'\n" + " Located at: Column 'super' | Row 3\n" + " Original Error Message:\n'GeonameValue' is not valid under any of the given schemas" + ) + with pytest.raises(InputError, match=expected_msg): + e2j.excel2properties( + excelfile="testdata/invalid-testdata/excel2json/properties-invalid-super.xlsx", path_to_output_file="" + ) + + def test_invalid_object(self) -> None: + expected_msg = re.escape( + "\nThe Excel file " + "'testdata/invalid-testdata/excel2json/properties-invalid-object.xlsx' did not pass validation.\n" + " Section of the problem: 'Properties'\n" + " Problematic property: 'hasBoolean'\n" + " Located at: Column 'object' | Row 2\n" + " Original Error Message:\n'hasValue' is not valid under any of the given schemas" + ) + with pytest.raises(InputError, match=expected_msg): + e2j.excel2properties( + excelfile="testdata/invalid-testdata/excel2json/properties-invalid-object.xlsx", path_to_output_file="" + ) + + def test_invalid_gui_element(self) -> None: + expected_msg = re.escape( + "\nThe Excel file " + "'testdata/invalid-testdata/excel2json/properties-invalid-gui_element.xlsx' did not pass validation.\n" + " Section of the problem: 'Properties'\n" + " Problematic property: 'hasInterval'\n" + " Located at: Column 'gui_element' | Row 4\n" + " Original Error Message:\n'Interval' was expected" + ) + with pytest.raises(InputError, match=expected_msg): + e2j.excel2properties( + excelfile="testdata/invalid-testdata/excel2json/properties-invalid-gui_element.xlsx", + path_to_output_file="", + ) + + def test_invalid_gui_attrib_values(self) -> None: + expected_msg = re.escape( + "\nThe Excel file " + "'testdata/invalid-testdata/excel2json/properties-invalid-gui_attribute_values.xlsx' " + "did not pass validation.\n" + " Section of the problem: 'Properties'\n" + " Problematic property: 'hasInteger'\n" + " Located at: Column 'gui_attributes' | Row 4\n" + " Original Error Message:\nAdditional properties are not allowed ('rows' was unexpected)" + ) + with pytest.raises(InputError, match=expected_msg): + e2j.excel2properties( + excelfile="testdata/invalid-testdata/excel2json/properties-invalid-gui_attribute_values.xlsx", + path_to_output_file="", + ) + + +def test_excel2properties_invalid_gui_attrib_format() -> None: + expected_msg = re.escape( + "There is a problem with the excel file: " + "'testdata/invalid-testdata/excel2json/properties-invalid-gui_attribute_format.xlsx'\n" + "There is invalid content in the excel.\n" + "Located at: Column 'gui_attributes' | Row 4\n" + "Expected Content: attribute: value, attribute: value\n" + "Actual Content: max=10, min=5" + ) + with pytest.raises(InputError, match=expected_msg): + e2j.excel2properties("testdata/invalid-testdata/excel2json/properties-invalid-gui_attribute_format.xlsx", "") + + +class TestExcelToProperties(unittest.TestCase): + def test_names(self) -> None: + excel_names = [ + "correspondsToGenericAnthroponym", + "hasAnthroponym", + "hasGender", + "isDesignatedAs", + "hasTitle", + "hasStatus", + "hasLifeYearAmount", + "hasBirthDate", + "hasRepresentation", + "hasRemarks", + "hasTerminusPostQuem", + "hasGND", + "hasColor", + "hasDecimal", + "hasTime", + "hasInterval", + "hasBoolean", + "hasGeoname", + "partOfDocument", + "linkstoRegion", + "hasLinkToImage", + "hasLinkToResource", + "hasLinkToArchiveRepresentation", + "hasLinkToMovingImageRepesentation", + "hasLinkToAudioRepesentation", + ] + json_names = [match.value for match in jsonpath_ng.parse("$[*].name").find(output_from_method)] + self.assertListEqual(excel_names, json_names) + + def test_supers(self) -> None: + excel_supers = [ + ["hasLinkTo"], + ["hasValue", "dcterms:creator"], + ["hasValue"], + ["hasValue"], + ["hasLinkTo"], + ["hasValue"], + ["hasValue"], + ["hasValue"], + ["hasRepresentation"], + ["hasValue", "dcterms:description"], + ["hasValue"], + ["hasValue"], + ["hasColor"], + ["hasValue"], + ["hasValue"], + ["hasSequenceBounds"], + ["hasValue"], + ["hasValue"], + ["isPartOf"], + ["hasLinkTo"], + ["hasLinkTo"], + ["hasLinkTo"], + ["hasLinkTo"], + ["hasLinkTo"], + ["hasLinkTo"], + ] + json_supers = [match.value for match in jsonpath_ng.parse("$[*].super").find(output_from_method)] + self.assertListEqual(excel_supers, json_supers) + + def test_objects(self) -> None: + excel_objects = [ + ":GenericAnthroponym", + "TextValue", + "ListValue", + "ListValue", + ":Titles", + "ListValue", + "IntValue", + "DateValue", + "Representation", + "TextValue", + "DateValue", + "UriValue", + "ColorValue", + "DecimalValue", + "TimeValue", + "IntervalValue", + "BooleanValue", + "GeonameValue", + ":Documents", + "Region", + "StillImageRepresentation", + "Resource", + "ArchiveRepresentation", + "MovingImageRepresentation", + "AudioRepresentation", + ] + json_objects = [match.value for match in jsonpath_ng.parse("$[*].object").find(output_from_method)] + self.assertListEqual(excel_objects, json_objects) + + def test_labels(self) -> None: + excel_labels = { + "de": [ + "", + "only German", + "", + "", + "", + "", + "", + "", + "hat eine Multimediadatei", + "", + "", + "GND", + "Farbe", + "Dezimalzahl", + "Zeit", + "Zeitintervall", + "Bool'sche Variable", + "Link zu Geonames", + "ist Teil eines Dokuments", + "", + "", + "", + "", + "", + "", + ], + "it": [ + "", + "", + "", + "only Italian", + "", + "", + "", + "", + "", + "", + "", + "GND", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ], + } # there are also labels in other languages, but they are not tested + json_labels_all = [match.value for match in jsonpath_ng.parse("$[*].labels").find(output_from_method)] + json_labels = {lang: [label.get(lang, "").strip() for label in json_labels_all] for lang in ["de", "it"]} + self.assertDictEqual(excel_labels, json_labels) + + def test_comments(self) -> None: + excel_comments = { + "comment_fr": [ + "J'avais déjà examiné plusieurs propriétés quand, un jour, le notaire, qui me " + "donnait des indications nécessaires pour une de mes explorations, me dit :", + "Un étrange hasard m'a mis en possession de ce journal.", + "Je n'en sais rien du tout ; mais si vous voulez la voir, monsieur, voici les " + "indications précises pour la trouver.", + "Vous devrez arranger l'affaire avec le curé du village de --.\"", + "Un étrange hasard m'a mis en possession de ce journal.", + "", + "", + "only French", + "", + "", + "J'avais déjà examiné plusieurs propriétés quand, un jour, le notaire, qui me " + "donnait des indications nécessaires pour une de mes explorations, me dit :", + "Gemeinsame Normdatei", + "", + "Chiffre décimale", + "Temps", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ], + "comment_it": [ + "Avevo già visto diverse proprietà quando un giorno il notaio,", + "Uno strano caso mi mise in possesso di questo diario.", + "Non ne so nulla; ma se volete vederla, signore, eccovi le indicazioni precise per trovarla.", + "Dovrete organizzare l'affare con il curato del villaggio di --\".", + "Uno strano caso mi mise in possesso di questo diario.", + "", + "", + "", + "", + "", + "Avevo già visto diverse proprietà quando un giorno il notaio,", + "Gemeinsame Normdatei", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ], + } # there are also comments in other languages, but they are not tested + json_comments = { + f"comment_{lang}": [resource.get("comments", {}).get(lang, "").strip() for resource in output_from_method] + for lang in ["fr", "it"] + } + self.assertDictEqual(excel_comments, json_comments) + + def test_gui_elements(self) -> None: + excel_gui_elements = [ + "Searchbox", + "Richtext", + "List", + "Radio", + "Searchbox", + "List", + "Spinbox", + "Date", + "Searchbox", + "Textarea", + "Date", + "SimpleText", + "Colorpicker", + "Spinbox", + "TimeStamp", + "Interval", + "Checkbox", + "Geonames", + "Searchbox", + "Searchbox", + "Searchbox", + "Searchbox", + "Searchbox", + "Searchbox", + "Searchbox", + ] + + json_gui_elements = [match.value for match in jsonpath_ng.parse("$[*].gui_element").find(output_from_method)] + self.assertListEqual(excel_gui_elements, json_gui_elements) + + def test_gui_attributes_hasGender(self) -> None: + excel_gui_attributes_hasGender = {"hlist": "gender"} + json_gui_attributes_hasGender = ( + jsonpath_ng.ext.parse("$[?name='hasGender'].gui_attributes").find(output_from_method)[0].value + ) + self.assertDictEqual(excel_gui_attributes_hasGender, json_gui_attributes_hasGender) + + def test_gui_attributes_hasGND(self) -> None: + excel_gui_attributes_hasGND = {"size": 100} + json_gui_attributes_hasGND = ( + jsonpath_ng.ext.parse("$[?name='hasGND'].gui_attributes").find(output_from_method)[0].value + ) + self.assertDictEqual(excel_gui_attributes_hasGND, json_gui_attributes_hasGND) + + def test_gui_attributes_hasDecimal(self) -> None: + excel_gui_attributes_hasDecimal = {"min": 0.0, "max": 100.0} + json_gui_attributes_hasDecimal = ( + jsonpath_ng.ext.parse("$[?name='hasDecimal'].gui_attributes").find(output_from_method)[0].value + ) + self.assertDictEqual(excel_gui_attributes_hasDecimal, json_gui_attributes_hasDecimal) + + +if __name__ == "__main__": + pytest.main([__file__]) diff --git a/test/unittests/commands/excel2json/test_resources_high_level.py b/test/integration/commands/excel2json/test_resources.py similarity index 100% rename from test/unittests/commands/excel2json/test_resources_high_level.py rename to test/integration/commands/excel2json/test_resources.py diff --git a/test/integration/utils/__init__.py b/test/integration/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/unittests/commands/excel2json/test_properties.py b/test/unittests/commands/excel2json/test_properties.py index bffbd1ba8..30390f9ff 100644 --- a/test/unittests/commands/excel2json/test_properties.py +++ b/test/unittests/commands/excel2json/test_properties.py @@ -1,12 +1,8 @@ -"""unit tests for excel to properties""" - import re import unittest from typing import Any from typing import cast -import jsonpath_ng -import jsonpath_ng.ext import pandas as pd import pytest from pandas.testing import assert_frame_equal @@ -18,285 +14,6 @@ # ruff: noqa: PT009 (pytest-unittest-assertion) (remove this line when pytest is used instead of unittest) -excelfile = "testdata/excel2json/excel2json_files/test-name (test_label)/properties.xlsx" -output_from_method, _ = e2j.excel2properties(excelfile, None) - - -class TestExcelToProperties(unittest.TestCase): - def test_names(self) -> None: - excel_names = [ - "correspondsToGenericAnthroponym", - "hasAnthroponym", - "hasGender", - "isDesignatedAs", - "hasTitle", - "hasStatus", - "hasLifeYearAmount", - "hasBirthDate", - "hasRepresentation", - "hasRemarks", - "hasTerminusPostQuem", - "hasGND", - "hasColor", - "hasDecimal", - "hasTime", - "hasInterval", - "hasBoolean", - "hasGeoname", - "partOfDocument", - "linkstoRegion", - "hasLinkToImage", - "hasLinkToResource", - "hasLinkToArchiveRepresentation", - "hasLinkToMovingImageRepesentation", - "hasLinkToAudioRepesentation", - ] - json_names = [match.value for match in jsonpath_ng.parse("$[*].name").find(output_from_method)] - self.assertListEqual(excel_names, json_names) - - def test_supers(self) -> None: - excel_supers = [ - ["hasLinkTo"], - ["hasValue", "dcterms:creator"], - ["hasValue"], - ["hasValue"], - ["hasLinkTo"], - ["hasValue"], - ["hasValue"], - ["hasValue"], - ["hasRepresentation"], - ["hasValue", "dcterms:description"], - ["hasValue"], - ["hasValue"], - ["hasColor"], - ["hasValue"], - ["hasValue"], - ["hasSequenceBounds"], - ["hasValue"], - ["hasValue"], - ["isPartOf"], - ["hasLinkTo"], - ["hasLinkTo"], - ["hasLinkTo"], - ["hasLinkTo"], - ["hasLinkTo"], - ["hasLinkTo"], - ] - json_supers = [match.value for match in jsonpath_ng.parse("$[*].super").find(output_from_method)] - self.assertListEqual(excel_supers, json_supers) - - def test_objects(self) -> None: - excel_objects = [ - ":GenericAnthroponym", - "TextValue", - "ListValue", - "ListValue", - ":Titles", - "ListValue", - "IntValue", - "DateValue", - "Representation", - "TextValue", - "DateValue", - "UriValue", - "ColorValue", - "DecimalValue", - "TimeValue", - "IntervalValue", - "BooleanValue", - "GeonameValue", - ":Documents", - "Region", - "StillImageRepresentation", - "Resource", - "ArchiveRepresentation", - "MovingImageRepresentation", - "AudioRepresentation", - ] - json_objects = [match.value for match in jsonpath_ng.parse("$[*].object").find(output_from_method)] - self.assertListEqual(excel_objects, json_objects) - - def test_labels(self) -> None: - excel_labels = { - "de": [ - "", - "only German", - "", - "", - "", - "", - "", - "", - "hat eine Multimediadatei", - "", - "", - "GND", - "Farbe", - "Dezimalzahl", - "Zeit", - "Zeitintervall", - "Bool'sche Variable", - "Link zu Geonames", - "ist Teil eines Dokuments", - "", - "", - "", - "", - "", - "", - ], - "it": [ - "", - "", - "", - "only Italian", - "", - "", - "", - "", - "", - "", - "", - "GND", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - ], - } # there are also labels in other languages, but they are not tested - json_labels_all = [match.value for match in jsonpath_ng.parse("$[*].labels").find(output_from_method)] - json_labels = {lang: [label.get(lang, "").strip() for label in json_labels_all] for lang in ["de", "it"]} - self.assertDictEqual(excel_labels, json_labels) - - def test_comments(self) -> None: - excel_comments = { - "comment_fr": [ - "J'avais déjà examiné plusieurs propriétés quand, un jour, le notaire, qui me " - "donnait des indications nécessaires pour une de mes explorations, me dit :", - "Un étrange hasard m'a mis en possession de ce journal.", - "Je n'en sais rien du tout ; mais si vous voulez la voir, monsieur, voici les " - "indications précises pour la trouver.", - "Vous devrez arranger l'affaire avec le curé du village de --.\"", - "Un étrange hasard m'a mis en possession de ce journal.", - "", - "", - "only French", - "", - "", - "J'avais déjà examiné plusieurs propriétés quand, un jour, le notaire, qui me " - "donnait des indications nécessaires pour une de mes explorations, me dit :", - "Gemeinsame Normdatei", - "", - "Chiffre décimale", - "Temps", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - ], - "comment_it": [ - "Avevo già visto diverse proprietà quando un giorno il notaio,", - "Uno strano caso mi mise in possesso di questo diario.", - "Non ne so nulla; ma se volete vederla, signore, eccovi le indicazioni precise per trovarla.", - "Dovrete organizzare l'affare con il curato del villaggio di --\".", - "Uno strano caso mi mise in possesso di questo diario.", - "", - "", - "", - "", - "", - "Avevo già visto diverse proprietà quando un giorno il notaio,", - "Gemeinsame Normdatei", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - ], - } # there are also comments in other languages, but they are not tested - json_comments = { - f"comment_{lang}": [resource.get("comments", {}).get(lang, "").strip() for resource in output_from_method] - for lang in ["fr", "it"] - } - self.assertDictEqual(excel_comments, json_comments) - - def test_gui_elements(self) -> None: - excel_gui_elements = [ - "Searchbox", - "Richtext", - "List", - "Radio", - "Searchbox", - "List", - "Spinbox", - "Date", - "Searchbox", - "Textarea", - "Date", - "SimpleText", - "Colorpicker", - "Spinbox", - "TimeStamp", - "Interval", - "Checkbox", - "Geonames", - "Searchbox", - "Searchbox", - "Searchbox", - "Searchbox", - "Searchbox", - "Searchbox", - "Searchbox", - ] - - json_gui_elements = [match.value for match in jsonpath_ng.parse("$[*].gui_element").find(output_from_method)] - self.assertListEqual(excel_gui_elements, json_gui_elements) - - def test_gui_attributes_hasGender(self) -> None: - excel_gui_attributes_hasGender = {"hlist": "gender"} - json_gui_attributes_hasGender = ( - jsonpath_ng.ext.parse("$[?name='hasGender'].gui_attributes").find(output_from_method)[0].value - ) - self.assertDictEqual(excel_gui_attributes_hasGender, json_gui_attributes_hasGender) - - def test_gui_attributes_hasGND(self) -> None: - excel_gui_attributes_hasGND = {"size": 100} - json_gui_attributes_hasGND = ( - jsonpath_ng.ext.parse("$[?name='hasGND'].gui_attributes").find(output_from_method)[0].value - ) - self.assertDictEqual(excel_gui_attributes_hasGND, json_gui_attributes_hasGND) - - def test_gui_attributes_hasDecimal(self) -> None: - excel_gui_attributes_hasDecimal = {"min": 0.0, "max": 100.0} - json_gui_attributes_hasDecimal = ( - jsonpath_ng.ext.parse("$[?name='hasDecimal'].gui_attributes").find(output_from_method)[0].value - ) - self.assertDictEqual(excel_gui_attributes_hasDecimal, json_gui_attributes_hasDecimal) - - class TestFunctions(unittest.TestCase): @pytest.mark.filterwarnings("ignore::UserWarning") def test_rename_deprecated_lang_cols(self) -> None: @@ -550,132 +267,55 @@ def test_row2prop(self) -> None: } self.assertDictEqual(expected_dict, returned_dict) - def test_excel2properties_invalid_gui_attrib_format(self) -> None: - expected_msg = re.escape( - "There is a problem with the excel file: " - "'testdata/invalid-testdata/excel2json/properties-invalid-gui_attribute_format.xlsx'\n" - "There is invalid content in the excel.\n" - "Located at: Column 'gui_attributes' | Row 4\n" - "Expected Content: attribute: value, attribute: value\n" - "Actual Content: max=10, min=5" - ) - with pytest.raises(InputError, match=expected_msg): - e2j.excel2properties( - "testdata/invalid-testdata/excel2json/properties-invalid-gui_attribute_format.xlsx", "" - ) - - -class TestValidateProperties: - # it is not possible to call the method to be tested directly. - # So let's make a reference to it, so that it can be found by the usage search - lambda _: e2j._validate_properties_section_in_json([], "file") - def test_invalid_super(self) -> None: - expected_msg = re.escape( - "\nThe Excel file " - "'testdata/invalid-testdata/excel2json/properties-invalid-super.xlsx' did not pass validation.\n" - " Section of the problem: 'Properties'\n" - " Problematic property: 'hasGeoname'\n" - " Located at: Column 'super' | Row 3\n" - " Original Error Message:\n'GeonameValue' is not valid under any of the given schemas" - ) - with pytest.raises(InputError, match=expected_msg): - e2j.excel2properties( - excelfile="testdata/invalid-testdata/excel2json/properties-invalid-super.xlsx", path_to_output_file="" - ) - - def test_invalid_object(self) -> None: - expected_msg = re.escape( - "\nThe Excel file " - "'testdata/invalid-testdata/excel2json/properties-invalid-object.xlsx' did not pass validation.\n" - " Section of the problem: 'Properties'\n" - " Problematic property: 'hasBoolean'\n" - " Located at: Column 'object' | Row 2\n" - " Original Error Message:\n'hasValue' is not valid under any of the given schemas" - ) - with pytest.raises(InputError, match=expected_msg): - e2j.excel2properties( - excelfile="testdata/invalid-testdata/excel2json/properties-invalid-object.xlsx", path_to_output_file="" - ) - - def test_invalid_gui_element(self) -> None: - expected_msg = re.escape( - "\nThe Excel file " - "'testdata/invalid-testdata/excel2json/properties-invalid-gui_element.xlsx' did not pass validation.\n" - " Section of the problem: 'Properties'\n" - " Problematic property: 'hasInterval'\n" - " Located at: Column 'gui_element' | Row 4\n" - " Original Error Message:\n'Interval' was expected" - ) - with pytest.raises(InputError, match=expected_msg): - e2j.excel2properties( - excelfile="testdata/invalid-testdata/excel2json/properties-invalid-gui_element.xlsx", - path_to_output_file="", - ) - - def test_invalid_gui_attrib_values(self) -> None: - expected_msg = re.escape( - "\nThe Excel file " - "'testdata/invalid-testdata/excel2json/properties-invalid-gui_attribute_values.xlsx' " - "did not pass validation.\n" - " Section of the problem: 'Properties'\n" - " Problematic property: 'hasInteger'\n" - " Located at: Column 'gui_attributes' | Row 4\n" - " Original Error Message:\nAdditional properties are not allowed ('rows' was unexpected)" - ) - with pytest.raises(InputError, match=expected_msg): - e2j.excel2properties( - excelfile="testdata/invalid-testdata/excel2json/properties-invalid-gui_attribute_values.xlsx", - path_to_output_file="", - ) - - def test_add_optional_columns_with_missing_cols(self) -> None: - original_df = pd.DataFrame( - { - "comment_en": ["text_en", pd.NA], - "comment_it": ["text_it", pd.NA], - "comment_rm": [pd.NA, pd.NA], - } - ) - expected_df = pd.DataFrame( - { - "comment_de": [pd.NA, pd.NA], - "comment_en": ["text_en", pd.NA], - "comment_fr": [pd.NA, pd.NA], - "comment_it": ["text_it", pd.NA], - "comment_rm": [pd.NA, pd.NA], - "label_de": [pd.NA, pd.NA], - "label_en": [pd.NA, pd.NA], - "label_fr": [pd.NA, pd.NA], - "label_it": [pd.NA, pd.NA], - "label_rm": [pd.NA, pd.NA], - "subject": [pd.NA, pd.NA], - } - ) - returned_df = e2j._add_optional_columns(df=original_df) - # as the columns are extracted via a set, they are not sorted and may appear in any order, - # this would cause the validation to fail - returned_df = returned_df.sort_index(axis=1) - assert_frame_equal(expected_df, returned_df) - - def test_add_optional_columns_no_missing_cols(self) -> None: - expected_df = pd.DataFrame( - { - "comment_de": [pd.NA, pd.NA], - "comment_en": ["text_en", pd.NA], - "comment_fr": [pd.NA, pd.NA], - "comment_it": ["text_it", pd.NA], - "comment_rm": [pd.NA, pd.NA], - "label_de": [pd.NA, pd.NA], - "label_en": [pd.NA, pd.NA], - "label_fr": [pd.NA, pd.NA], - "label_it": [pd.NA, pd.NA], - "label_rm": [pd.NA, pd.NA], - "subject": [pd.NA, pd.NA], - } - ) - unchanged_df = e2j._add_optional_columns(df=expected_df) - assert_frame_equal(expected_df, unchanged_df) +def test_add_optional_columns_with_missing_cols() -> None: + original_df = pd.DataFrame( + { + "comment_en": ["text_en", pd.NA], + "comment_it": ["text_it", pd.NA], + "comment_rm": [pd.NA, pd.NA], + } + ) + expected_df = pd.DataFrame( + { + "comment_de": [pd.NA, pd.NA], + "comment_en": ["text_en", pd.NA], + "comment_fr": [pd.NA, pd.NA], + "comment_it": ["text_it", pd.NA], + "comment_rm": [pd.NA, pd.NA], + "label_de": [pd.NA, pd.NA], + "label_en": [pd.NA, pd.NA], + "label_fr": [pd.NA, pd.NA], + "label_it": [pd.NA, pd.NA], + "label_rm": [pd.NA, pd.NA], + "subject": [pd.NA, pd.NA], + } + ) + returned_df = e2j._add_optional_columns(df=original_df) + # as the columns are extracted via a set, they are not sorted and may appear in any order, + # this would cause the validation to fail + returned_df = returned_df.sort_index(axis=1) + assert_frame_equal(expected_df, returned_df) + + +def test_add_optional_columns_no_missing_cols() -> None: + expected_df = pd.DataFrame( + { + "comment_de": [pd.NA, pd.NA], + "comment_en": ["text_en", pd.NA], + "comment_fr": [pd.NA, pd.NA], + "comment_it": ["text_it", pd.NA], + "comment_rm": [pd.NA, pd.NA], + "label_de": [pd.NA, pd.NA], + "label_en": [pd.NA, pd.NA], + "label_fr": [pd.NA, pd.NA], + "label_it": [pd.NA, pd.NA], + "label_rm": [pd.NA, pd.NA], + "subject": [pd.NA, pd.NA], + } + ) + unchanged_df = e2j._add_optional_columns(df=expected_df) + assert_frame_equal(expected_df, unchanged_df) if __name__ == "__main__": diff --git a/test/unittests/commands/excel2json/test_resources_low_level.py b/test/unittests/commands/excel2json/test_resources.py similarity index 100% rename from test/unittests/commands/excel2json/test_resources_low_level.py rename to test/unittests/commands/excel2json/test_resources.py