This is an automated email from the ASF dual-hosted git repository. hutcheb pushed a commit to branch feat/plc4py/test_runner in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit e1d83f329435db74b02b7044aee749c788a85838 Author: hutcheb <[email protected]> AuthorDate: Wed Aug 21 20:48:11 2024 +0800 feat(plc4py): Test cases are automatically generated from parser serializer test files --- .../utils/ParserSerializerTestSuiteRunner.py | 56 ++++--------------- plc4py/plc4py/utils/XmlTestSuiteLoader.py | 64 ++++------------------ plc4py/plc4py/utils/generated/__init__.py | 16 ++++++ .../{ => utils/generated}/driver_testsuite.py | 17 ++++++ plc4py/setup.py | 1 + plc4py/tests/unit/plc4py/utils/TestSuiteTest.py | 28 ++++------ 6 files changed, 68 insertions(+), 114 deletions(-) diff --git a/plc4py/plc4py/utils/ParserSerializerTestSuiteRunner.py b/plc4py/plc4py/utils/ParserSerializerTestSuiteRunner.py index 7cee49d8b5..83b109b4bb 100644 --- a/plc4py/plc4py/utils/ParserSerializerTestSuiteRunner.py +++ b/plc4py/plc4py/utils/ParserSerializerTestSuiteRunner.py @@ -18,15 +18,13 @@ import logging import unittest from dataclasses import dataclass, field from typing import Iterator, List -from driver_testsuite import DriverTestsuite +from utils.generated.driver_testsuite import DriverTestsuite from xsdata.formats.dataclass.parsers import XmlParser from api.exceptions.exceptions import ParseException from utils.XmlTestSuiteLoader import ( ParserSerializerTestSuite, - TestCase, - TestCaseBuilder, - XmlTestSuiteLoader, + XmlTestSuiteLoader, ParserSerializerTestCase, ) logger = logging.getLogger(__name__) @@ -39,52 +37,22 @@ class ParserSerializerTestsuiteRunner(XmlTestSuiteLoader): ignored_test_cases: List[str] = field(default_factory=list) @property - def test_suite_tests(self) -> Iterator[unittest.case]: + def test_suite_tests(self) -> List[unittest.case]: parser = XmlParser() - test_suite = parser.parse(self.test_suite_document, DriverTestsuite) + test_suite_xml = parser.parse(self.test_suite_document, DriverTestsuite) - test_suite = self._parse_test_suite() dynamic_tests: List[unittest.case] = [] - for test_case in test_suite: - if not test_case.__name__ in self.ignored_test_cases: - dynamic_tests.append(test_case) + for test_case in test_suite_xml.testcase: + if not test_case.name in self.ignored_test_cases: + test_suite = ParserSerializerTestCase() + test_suite.add_test_case(test_case) + test_suite.name = test_suite_xml.name + " - " + test_case.name + dynamic_tests.append(test_suite) - return iter(dynamic_tests) - - def _parse_test_suite(self): - root = self.test_suite_document_xml.__next__() - byte_order = root[1].attrib.get("byteOrder", "LITTLE_ENDIAN") - test_suite_name = None - protocol_name = None - output_flavor = None - driver_name = None - found_header = False - test_cases: List[TestCase] = [] - - for name, element in self.test_suite_document_xml: - if element.tag == "name": - test_suite_name = element.text - elif element.tag == "protocolName": - protocol_name = element.text - elif element.tag == "outputFlavor": - output_flavor = element.text - elif element.tag == "driver-name": - driver_name = element.text - elif element.tag == "testcase": - test_cases.append(TestCaseBuilder(element).build()) - found_header = ( - test_suite_name is not None - and protocol_name is not None - and output_flavor is not None - and driver_name is not None - ) - - if not found_header: - raise ParseException() - pass + return dynamic_tests def run( - self, test_suite: ParserSerializerTestSuite, test_case: TestCase + self, test_suite: ParserSerializerTestSuite, test_case: ParserSerializerTestCase ) -> Iterator[unittest.TestResult]: return self.test_suite_document_xml is not None diff --git a/plc4py/plc4py/utils/XmlTestSuiteLoader.py b/plc4py/plc4py/utils/XmlTestSuiteLoader.py index 587526bd1a..08f6bb7d78 100644 --- a/plc4py/plc4py/utils/XmlTestSuiteLoader.py +++ b/plc4py/plc4py/utils/XmlTestSuiteLoader.py @@ -18,6 +18,7 @@ import unittest from abc import ABC, abstractmethod from dataclasses import dataclass, field from typing import Any, Iterator +from unittest import TestCase from xml.etree import ElementTree from xml.etree.ElementTree import XMLParser @@ -27,62 +28,19 @@ class ParserSerializerTestSuite: pass -class TestCase: - # TODO:- Do something with this - pass - - -@dataclass -class TestCaseBuilder: - element: ElementTree +class ParserSerializerTestCase(TestCase): - def build(self) -> TestCase: - name = None - description = None - raw = None - root_type = None - parser_arguments = None - for element in self.element: - if element.tag == "name": - name = element.text - elif element.tag == "description": - description = element.text - elif element.tag == "raw": - raw = element.text - elif element.tag == "root-type": - root_type = element.text - elif element.tag == "parser-arguments": - parser_arguments = element.text - elif element.tag == "parser-raw": - parser_raw = element.text + def __init__(self, methodName='runTest'): + super().__init__(methodName) + self.name = None + self.test_case = None - return TestCase() + def add_test_case(self, test_case): + self.test_case = test_case + self.name = test_case.name - # Element descriptionElement = testcaseXml.element(new QName("description")); - # Element rawElement = testcaseXml.element(new QName("raw")); - # Element rootTypeElement = testcaseXml.element(new QName("root-type")); - # Element parserArgumentsElement = testcaseXml.element(new QName("parser-arguments")); - # Element xmlElement = testcaseXml.element(new QName("xml")); - # - # String name = nameElement.getTextTrim(); - # String description = (descriptionElement != null) ? descriptionElement.getTextTrim() : null; - # byte[] raw = Hex.decodeHex(rawElement.getTextTrim()); - # String rootType = rootTypeElement.getTextTrim(); - # - # // Parse additional parser arguments. - # List<String> parserArguments = new LinkedList<>(); - # if (parserArgumentsElement != null) { - # for (Element element : parserArgumentsElement.elements()) { - # parserArguments.add(element.getTextTrim()); - # } - # } - # Testcase testcase = new Testcase(testsuiteName, protocolName, outputFlavor, name, description, raw, rootType, parserArguments, xmlElement); - # if (testcaseXml instanceof LocationAwareElement) { - # // pass source location to test - # testcase.setLocation(((LocationAwareElement) testcaseXml).getLocation()); - # } - # testcases.add(testcase); - # } + def runTest(self): + pass @dataclass diff --git a/plc4py/plc4py/utils/generated/__init__.py b/plc4py/plc4py/utils/generated/__init__.py new file mode 100644 index 0000000000..a67d5ea255 --- /dev/null +++ b/plc4py/plc4py/utils/generated/__init__.py @@ -0,0 +1,16 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. diff --git a/plc4py/plc4py/driver_testsuite.py b/plc4py/plc4py/utils/generated/driver_testsuite.py similarity index 93% rename from plc4py/plc4py/driver_testsuite.py rename to plc4py/plc4py/utils/generated/driver_testsuite.py index ccfe24398e..7ab4992180 100644 --- a/plc4py/plc4py/driver_testsuite.py +++ b/plc4py/plc4py/utils/generated/driver_testsuite.py @@ -1,3 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + from dataclasses import dataclass, field from enum import Enum from typing import List, Optional diff --git a/plc4py/setup.py b/plc4py/setup.py index 82bf257669..b6422e592c 100644 --- a/plc4py/setup.py +++ b/plc4py/setup.py @@ -56,6 +56,7 @@ setup( "mypy>=0.942", "flake8>=4.0.1", "pytest-asyncio", + "xsdata" ] }, entry_points={ diff --git a/plc4py/tests/unit/plc4py/utils/TestSuiteTest.py b/plc4py/tests/unit/plc4py/utils/TestSuiteTest.py index 5b52cdc3ab..7bc6c945e6 100644 --- a/plc4py/tests/unit/plc4py/utils/TestSuiteTest.py +++ b/plc4py/tests/unit/plc4py/utils/TestSuiteTest.py @@ -18,31 +18,25 @@ import os import unittest import pytest +from annotated_types import test_cases from typing_extensions import Iterator from utils.ParserSerializerTestSuiteRunner import ParserSerializerTestsuiteRunner from utils.XmlTestSuiteLoader import XmlTestSuiteLoader, ParserSerializerTestSuite, TestCase -class MockXmlTestSuiteLoader(XmlTestSuiteLoader): +def pytest_generate_tests(metafunc): + xml_loader = ParserSerializerTestsuiteRunner( + os.path.join(os.path.dirname(__file__), 'resources', "DriverTestSuite.xml")) - def run(self, test_suite: ParserSerializerTestSuite, test_case: TestCase) -> Iterator[unittest.TestResult]: - return self.test_suite_document_xml is not None + test_suites = xml_loader.test_suite_tests - [email protected] -async def test_parse_xml_file() -> None: - xml_loader = MockXmlTestSuiteLoader(os.path.join(os.path.dirname(__file__), 'resources', "DriverTestSuite.xml")) - for _ in xml_loader.test_suite_document_xml: - pass - - assert xml_loader.run(ParserSerializerTestSuite(), TestCase()) + metafunc.parametrize("test_case", test_suites, ids=[test_case.name for test_case in test_suites]) @pytest.mark.asyncio -async def test_parse_serializer_parse_xml_test() -> None: - xml_loader = ParserSerializerTestsuiteRunner(os.path.join(os.path.dirname(__file__), 'resources', "DriverTestSuite.xml")) - for _ in xml_loader.test_suite_tests: - pass - - assert xml_loader.run(ParserSerializerTestSuite(), TestCase()) +async def test_parse_serializer_parse_xml_test(test_case) -> None: + try: + test_case.runTest() + except Exception as e: + raise e
