cleder / fastkml

Fast 🌍️ <KML /> processing for python
https://fastkml.readthedocs.io
229 stars 92 forks source link

361 test geometries with hypothesis #364

Closed cleder closed 1 month ago

cleder commented 1 month ago

User description

workerB


PR Type

Tests, Enhancement


Description


Changes walkthrough πŸ“

Relevant files
Enhancement
2 files
features.py
Add default value for `max_lines` attribute                           

fastkml/features.py - Added a default value for `max_lines` attribute.
+1/-0     
geometry.py
Refactor geometry classes and add equality checks               

fastkml/geometry.py
  • Added equality checks for geometry classes.
  • Refactored coordinate precision handling.
  • Introduced xml_attrs for attribute management.
  • +52/-23 
    Tests
    11 files
    conftest.py
    Configure Hypothesis profiles for testing                               

    tests/conftest.py - Configured Hypothesis profiles for testing.
    +21/-0   
    boundaries_test.py
    Update boundary tests with precision parameter                     

    tests/geometries/boundaries_test.py - Updated tests to include precision parameter.
    +2/-2     
    coordinates_test.py
    Update coordinate tests with precision parameter                 

    tests/geometries/coordinates_test.py - Updated coordinate tests to include precision parameter.
    +1/-1     
    geometry_test.py
    Update geometry tests with precision parameter                     

    tests/geometries/geometry_test.py - Updated geometry tests to include precision parameter.
    +33/-27 
    linearring_test.py
    Update LinearRing tests with precision parameter                 

    tests/geometries/linearring_test.py - Updated LinearRing tests to include precision parameter.
    +2/-1     
    linestring_test.py
    Update LineString tests with precision parameter                 

    tests/geometries/linestring_test.py - Updated LineString tests to include precision parameter.
    +1/-1     
    multigeometry_test.py
    Update MultiGeometry tests with precision parameter           

    tests/geometries/multigeometry_test.py - Updated MultiGeometry tests to include precision parameter.
    +19/-13 
    point_test.py
    Update Point tests with precision parameter                           

    tests/geometries/point_test.py - Updated Point tests to include precision parameter.
    +4/-2     
    polygon_test.py
    Update Polygon tests with precision parameter                       

    tests/geometries/polygon_test.py - Updated Polygon tests to include precision parameter.
    +3/-3     
    geometry_test.py
    Add property-based tests for geometry classes                       

    tests/hypothesis/geometry_test.py - Added property-based tests for geometry classes using Hypothesis.
    +501/-0 
    multi_geometry_test.py
    Add property-based tests for multi-geometry classes           

    tests/hypothesis/multi_geometry_test.py
  • Added property-based tests for multi-geometry classes using
    Hypothesis.
  • +670/-0 
    Configuration changes
    2 files
    run-all-tests.yml
    Update test workflow and coverage threshold                           

    .github/workflows/run-all-tests.yml
  • Increased coverage threshold to 95%.
  • Updated permissions for publishing workflow.
  • +4/-4     
    .pre-commit-config.yaml
    Update pre-commit configuration for Python and dependencies

    .pre-commit-config.yaml
  • Updated Python version for pyupgrade.
  • Added Hypothesis to mypy dependencies.
  • +2/-2     
    Dependencies
    1 files
    pyproject.toml
    Update test dependencies and coverage configuration           

    pyproject.toml
  • Added Hypothesis to test dependencies.
  • Updated coverage report exclusions.
  • +2/-0     

    πŸ’‘ PR-Agent usage: Comment /help "your question" on any pull request to receive relevant information

    Summary by Sourcery

    Enhance geometry handling by adding equality checks and refactoring coordinate precision management. Introduce property-based testing with Hypothesis to improve test coverage and robustness. Update CI and deployment configurations to enforce stricter code coverage and secure publishing processes.

    New Features:

    Enhancements:

    Build:

    CI:

    Deployment:

    Tests:

    Summary by CodeRabbit


    [!IMPORTANT] Add property-based tests using Hypothesis for geometry classes, refactor precision handling, and update testing configurations.

    • Tests:
      • Add property-based tests for geometry and multi-geometry classes using Hypothesis in tests/hypothesis/geometry_test.py and tests/hypothesis/multi_geometry_test.py.
      • Update existing tests in boundaries_test.py, coordinates_test.py, geometry_test.py, linearring_test.py, linestring_test.py, multigeometry_test.py, point_test.py, and polygon_test.py to include precision parameters.
      • Configure Hypothesis profiles in conftest.py for testing.
    • Enhancements:
      • Refactor geometry classes in geometry.py to add equality checks and improve precision handling.
      • Introduce xml_attrs for attribute management in geometry.py.
    • Configuration:
      • Increase coverage threshold to 95% in run-all-tests.yml.
      • Update pre-commit configuration in .pre-commit-config.yaml to support Python 3.8+ and add Hypothesis to mypy dependencies.
    • Misc:
      • Add default value for max_lines attribute in features.py.

    This description was created by Ellipsis for 1142a1e54923d46309c049e016b4b6316d072379. It will automatically update as commits are pushed.

    semanticdiff-com[bot] commented 1 month ago

    Review changes with SemanticDiff.

    Analyzed 14 of 18 files.

    Overall, the semantic diff is 5% smaller than the GitHub diff.

    1 files do not contain logic changes. Filename Status
    :grey_question: .pre-commit-config.yaml Unsupported file format
    :grey_question: pyproject.toml Unsupported file format
    :heavy_check_mark: tests/conftest.py Analyzed
    :heavy_check_mark: tests/hypothesis/__init__.py No logic changes found
    :heavy_check_mark: tests/hypothesis/geometry_test.py Analyzed
    :heavy_check_mark: tests/hypothesis/multi_geometry_test.py Analyzed
    :heavy_check_mark: tests/geometries/boundaries_test.py Analyzed
    :heavy_check_mark: tests/geometries/coordinates_test.py Analyzed
    :heavy_check_mark: tests/geometries/geometry_test.py 71.81% smaller
    :heavy_check_mark: tests/geometries/linearring_test.py 92.52% smaller
    :heavy_check_mark: tests/geometries/linestring_test.py Analyzed
    :heavy_check_mark: tests/geometries/multigeometry_test.py 66.98% smaller
    :heavy_check_mark: tests/geometries/point_test.py 72.51% smaller
    :heavy_check_mark: tests/geometries/polygon_test.py Analyzed
    :heavy_check_mark: fastkml/features.py Analyzed
    :heavy_check_mark: fastkml/geometry.py 3.86% smaller
    :grey_question: docs/usage_guide.rst Unsupported file format
    :grey_question: .github/workflows/run-all-tests.yml Unsupported file format
    sourcery-ai[bot] commented 1 month ago

    Reviewer's Guide by Sourcery

    This pull request implements property-based testing for geometry classes using the Hypothesis library. It also includes improvements to the existing code, such as adding precision handling for coordinate string representations and implementing equality methods for geometry classes.

    No diagrams generated as the changes look simple and do not need a visual representation.

    File-Level Changes

    Change Details Files
    Implemented property-based testing for geometry classes
    • Added new test files for hypothesis-based testing of geometry and multi-geometry classes
    • Created test cases for various geometry types (Point, LineString, Polygon, MultiGeometry)
    • Implemented roundtrip tests for string and repr representations of geometry objects
    tests/hypothesis/multi_geometry_test.py
    tests/hypothesis/geometry_test.py
    Improved coordinate string representation handling
    • Added precision parameter to to_string() method calls
    • Updated existing tests to use precision parameter when comparing coordinate strings
    fastkml/geometry.py
    tests/geometries/geometry_test.py
    tests/geometries/multigeometry_test.py
    tests/geometries/point_test.py
    tests/geometries/polygon_test.py
    tests/geometries/linearring_test.py
    tests/geometries/linestring_test.py
    tests/geometries/coordinates_test.py
    tests/geometries/boundaries_test.py
    Implemented equality methods for geometry classes
    • Added eq methods to Point, LineString, and Polygon classes
    • Created a set of common XML attributes for comparison
    fastkml/geometry.py
    Updated CI/CD pipeline configuration
    • Increased code coverage requirement to 95%
    • Updated PyPI publishing configuration to use trusted publishing
    • Added hypothesis as a dependency for mypy
    .github/workflows/run-all-tests.yml
    .pre-commit-config.yaml
    Minor code improvements and refactoring
    • Simplified coordinate string generation logic
    • Removed redundant repr method from LinearRing class
    • Set default value for 'draw_order' attribute in features.py
    fastkml/geometry.py
    fastkml/features.py

    Possibly linked issues


    Tips and commands #### Interacting with Sourcery - **Trigger a new review:** Comment `@sourcery-ai review` on the pull request. - **Continue discussions:** Reply directly to Sourcery's review comments. - **Generate a GitHub issue from a review comment:** Ask Sourcery to create an issue from a review comment by replying to it. - **Generate a pull request title:** Write `@sourcery-ai` anywhere in the pull request title to generate a title at any time. - **Generate a pull request summary:** Write `@sourcery-ai summary` anywhere in the pull request body to generate a PR summary at any time. You can also use this command to specify where the summary should be inserted. #### Customizing Your Experience Access your [dashboard](https://app.sourcery.ai) to: - Enable or disable review features such as the Sourcery-generated pull request summary, the reviewer's guide, and others. - Change the review language. - Add, remove or edit custom review instructions. - Adjust other review settings. #### Getting Help - [Contact our support team](mailto:support@sourcery.ai) for questions or feedback. - Visit our [documentation](https://docs.sourcery.ai) for detailed guides and information. - Keep in touch with the Sourcery team by following us on [X/Twitter](https://x.com/SourceryAI), [LinkedIn](https://www.linkedin.com/company/sourcery-ai/) or [GitHub](https://github.com/sourcery-ai).
    coderabbitai[bot] commented 1 month ago

    Walkthrough

    The pull request introduces several enhancements across various files, focusing on improving testing capabilities, coverage reporting, and KML feature functionalities. Key changes include updates to GitHub workflows for stricter coverage thresholds, modifications to pre-commit hooks for Python version compatibility, and enhancements to geometry classes to support precision in KML output. New property-based tests utilizing the Hypothesis library are added for comprehensive coverage of geometry classes, ensuring their reliability through extensive automated testing.

    Changes

    File Change Summary
    .github/workflows/run-all-tests.yml Updated coverage threshold for cpython-lxml job to 95, added environment key to publish job, clarified publishing conditions, and included installation of pypa/build.
    .pre-commit-config.yaml Changed pyupgrade hook argument from --py37-plus to --py38-plus and added hypothesis to mypy hook's additional dependencies.
    fastkml/features.py Added default value for max_lines in Snippet, validation in Placemark for geometry types, and new attributes in NetworkLink for visibility and view behavior.
    fastkml/geometry.py Enhanced precision handling in coordinates_subelement, added __eq__ methods for geometry classes, introduced geometry property, and removed redundant __repr__ methods.
    pyproject.toml Added hypothesis to tests under optional dependencies and updated coverage report exclusions.
    tests/conftest.py Registered three Hypothesis profiles: exhaustive, coverage, and CI, each with specific settings for testing.
    tests/geometries/*.py Updated various test methods to include precision=6 in to_string method calls for consistent KML output formatting.
    tests/hypothesis/geometry_test.py Introduced property-based tests for geometry classes using Hypothesis, covering various geometric entities and validating their string representations.
    tests/hypothesis/multi_geometry_test.py Added property-based tests for MultiGeometry class, ensuring integrity through round-trip serialization and deserialization.

    Possibly related PRs

    πŸ‡ In the land of KML, we hop and play,
    With precision and tests, we brighten the day.
    From features to geometry, all in a row,
    Our code now shines, with a beautiful glow!
    So let’s leap with joy, for changes abound,
    In the garden of code, new wonders are found! 🌼


    Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

    ❀️ Share - [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai) - [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai) - [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai) - [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)
    πŸͺ§ Tips ### Chat There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai): - Review comments: Directly reply to a review comment made by CodeRabbit. Example: - `I pushed a fix in commit , please review it.` - `Generate unit testing code for this file.` - `Open a follow-up GitHub issue for this discussion.` - Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples: - `@coderabbitai generate unit testing code for this file.` - `@coderabbitai modularize this function.` - PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples: - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.` - `@coderabbitai read src/utils.ts and generate unit testing code.` - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.` - `@coderabbitai help me debug CodeRabbit configuration file.` Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. ### CodeRabbit Commands (Invoked using PR comments) - `@coderabbitai pause` to pause the reviews on a PR. - `@coderabbitai resume` to resume the paused reviews. - `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository. - `@coderabbitai full review` to do a full review from scratch and review all the files again. - `@coderabbitai summary` to regenerate the summary of the PR. - `@coderabbitai resolve` resolve all the CodeRabbit review comments. - `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository. - `@coderabbitai help` to get help. ### Other keywords and placeholders - Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed. - Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description. - Add `@coderabbitai` anywhere in the PR title to generate the title automatically. ### Documentation and Community - Visit our [Documentation](https://coderabbit.ai/docs) for detailed information on how to use CodeRabbit. - Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback. - Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.
    codiumai-pr-agent-free[bot] commented 1 month ago

    CI Failure Feedback 🧐

    (Checks updated until commit https://github.com/cleder/fastkml/commit/b9eda46ab0f664cb3b6eb83b2979ec1e4508e238)

    **Action:** doctest-lxml (3.12)
    **Failed stage:** [test the pythoncode in the documentation](https://github.com/cleder/fastkml/actions/runs/11314562680/job/31464688276) [❌]
    **Failed test name:** usage_guide.rst
    **Failure summary:** The action failed because there were 2 test failures in the file usage_guide.rst:
  • The first failure occurred at line 48.
  • The second failure occurred at line 148.
    These failures caused the overall test suite to fail,
    resulting in the process exiting with code 1.
  • Relevant error logs: ```yaml 1: ##[group]Operating System 2: Ubuntu ... 255: ok 256: Trying: 257: fastkml.config.set_default_namespaces() 258: Expecting nothing 259: ok 260: 1 items passed all tests: 261: 10 tests in Configuration.rst 262: 10 tests in 1 items. 263: 10 passed and 0 failed. 264: Test passed. 265: 1 items had no tests: 266: HISTORY.rst 267: 0 tests in 1 items. 268: 0 passed and 0 failed. 269: Test passed. 270: 1 items had no tests: 271: contributing.rst 272: 0 tests in 1 items. 273: 0 passed and 0 failed. 274: Test passed. 275: 1 items had no tests: 276: fastkml.rst 277: 0 tests in 1 items. 278: 0 passed and 0 failed. 279: Test passed. 280: 1 items had no tests: 281: index.rst 282: 0 tests in 1 items. 283: 0 passed and 0 failed. 284: Test passed. 285: 1 items had no tests: 286: installing.rst 287: 0 tests in 1 items. 288: 0 passed and 0 failed. 289: Test passed. 290: 1 items had no tests: 291: modules.rst 292: 0 tests in 1 items. 293: 0 passed and 0 failed. ... 298: ok 299: Trying: 300: k = kml.KML() 301: Expecting nothing 302: ok 303: 1 items passed all tests: 304: 2 tests in quickstart.rst 305: 2 tests in 1 items. 306: 2 passed and 0 failed. 307: Test passed. 308: 1 items had no tests: 309: reference_guide.rst 310: 0 tests in 1 items. 311: 0 passed and 0 failed. ... 404: 405: 406: 407: 408: 409: 410: ********************************************************************** 411: File "docs/usage_guide.rst", line 48, in usage_guide.rst 412: Failed example: ... 573: -122.370000,37.817000,0.000000 574: 575: 576: 577: 578: 579: ********************************************************************** 580: File "docs/usage_guide.rst", line 148, in usage_guide.rst 581: Failed example: ... 630: 631: -122.37,37.817,0.0 632: 633: 634: 635: 636: 637: ********************************************************************** 638: 1 items had failures: 639: 2 of 28 in usage_guide.rst 640: 28 tests in 1 items. 641: 26 passed and 2 failed. 642: ***Test Failed*** 2 failures. 643: ##[error]Process completed with exit code 1. ```

    ✨ CI feedback usage guide:
    The CI feedback tool (`/checks)` automatically triggers when a PR has a failed check. The tool analyzes the failed checks and provides several feedbacks: - Failed stage - Failed test name - Failure summary - Relevant error logs In addition to being automatically triggered, the tool can also be invoked manually by commenting on a PR: ``` /checks "https://github.com/{repo_name}/actions/runs/{run_number}/job/{job_number}" ``` where `{repo_name}` is the name of the repository, `{run_number}` is the run number of the failed check, and `{job_number}` is the job number of the failed check. #### Configuration options - `enable_auto_checks_feedback` - if set to true, the tool will automatically provide feedback when a check is failed. Default is true. - `excluded_checks_list` - a list of checks to exclude from the feedback, for example: ["check1", "check2"]. Default is an empty list. - `enable_help_text` - if set to true, the tool will provide a help message with the feedback. Default is true. - `persistent_comment` - if set to true, the tool will overwrite a previous checks comment with the new feedback. Default is true. - `final_update_message` - if `persistent_comment` is true and updating a previous checks message, the tool will also create a new message: "Persistent checks updated to latest commit". Default is true. See more information about the `checks` tool in the [docs](https://pr-agent-docs.codium.ai/tools/ci_feedback/).
    what-the-diff[bot] commented 1 month ago

    PR Summary

    codiumai-pr-agent-free[bot] commented 1 month ago

    PR Reviewer Guide πŸ”

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 4 πŸ”΅πŸ”΅πŸ”΅πŸ”΅βšͺ
    πŸ§ͺ PR contains tests
    πŸ”’ No security concerns identified
    ⚑ Recommended focus areas for review

    Test Coverage
    Ensure that the new property-based tests using Hypothesis cover all edge cases and potential issues for geometry classes. Test Complexity
    Review the complexity of the multi-geometry tests to ensure they are not overly complicated and maintain good performance. Code Refactoring
    Verify that the refactored geometry classes, especially the new equality checks and precision handling, are implemented correctly and efficiently.
    codiumai-pr-agent-free[bot] commented 1 month ago

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Score
    Enhancement
    Add property-based tests to verify specific invariants of the MultiGeometry class ___ **Consider adding property-based tests that verify specific properties or invariants
    of the MultiGeometry class, such as checking if the bounding box of a MultiGeometry
    always contains all its constituent geometries.** [tests/hypothesis/multi_geometry_test.py [57-90]](https://github.com/cleder/fastkml/pull/364/files#diff-62429ef5316bba4d85f3d395ed68e6adaf2bfa4bc618ac4ebadc42ca78d6a568R57-R90) ```diff @given( id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), target_id=st.one_of(st.none(), st.text(ID_TEXT)), extrude=st.one_of(st.none(), st.booleans()), tessellate=st.one_of(st.none(), st.booleans()), altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), geometry=st.one_of( st.none(), multi_points(srs=epsg4326), ), ) -def test_multipoint_repr_roundtrip( +def test_multipoint_properties( id: typing.Optional[str], target_id: typing.Optional[str], extrude: typing.Optional[bool], tessellate: typing.Optional[bool], altitude_mode: typing.Optional[AltitudeMode], geometry: typing.Optional[MultiPoint], ) -> None: multi_geometry = fastkml.geometry.MultiGeometry( id=id, target_id=target_id, extrude=extrude, tessellate=tessellate, altitude_mode=altitude_mode, geometry=geometry, ) - new_mg = eval(repr(multi_geometry), {}, eval_locals) # noqa: S307 + if geometry: + bbox = multi_geometry.bounds + for point in geometry.geoms: + assert bbox[0] <= point.x <= bbox[2] + assert bbox[1] <= point.y <= bbox[3] - assert multi_geometry == new_mg - if geometry: - assert isinstance(new_mg.geometry, MultiPoint) + assert multi_geometry.is_valid ``` - [ ] **Apply this suggestion**
    Suggestion importance[1-10]: 8 Why: Adding property-based tests to verify invariants like bounding box containment can enhance the robustness of the tests by ensuring that fundamental properties of the MultiGeometry class are maintained.
    8
    Add test cases for empty multi-geometries to ensure proper handling of edge cases ___ **Consider adding a test case that specifically checks for the handling of empty
    geometries (i.e., when geometry is an empty MultiPoint, MultiLineString,
    MultiPolygon, or GeometryCollection). This would help ensure that the code correctly
    handles edge cases with empty multi-geometries.** [tests/hypothesis/multi_geometry_test.py [57-75]](https://github.com/cleder/fastkml/pull/364/files#diff-62429ef5316bba4d85f3d395ed68e6adaf2bfa4bc618ac4ebadc42ca78d6a568R57-R75) ```diff @given( id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), target_id=st.one_of(st.none(), st.text(ID_TEXT)), extrude=st.one_of(st.none(), st.booleans()), tessellate=st.one_of(st.none(), st.booleans()), altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), geometry=st.one_of( st.none(), multi_points(srs=epsg4326), + st.just(MultiPoint([])), ), ) def test_multipoint_repr_roundtrip( id: typing.Optional[str], target_id: typing.Optional[str], extrude: typing.Optional[bool], tessellate: typing.Optional[bool], altitude_mode: typing.Optional[AltitudeMode], geometry: typing.Optional[MultiPoint], ) -> None: ``` - [ ] **Apply this suggestion**
    Suggestion importance[1-10]: 7 Why: Adding test cases for empty geometries is a valuable enhancement that ensures edge cases are handled correctly, potentially catching bugs related to empty multi-geometries.
    7
    Add a step to run exhaustive tests periodically in the CI pipeline ___ **Consider adding a step to run tests with the 'exhaustive' Hypothesis profile. This
    will ensure that the extensive test suite is run periodically, potentially catching
    edge cases that might be missed in regular CI runs.** [.github/workflows/run-all-tests.yml [45-46]](https://github.com/cleder/fastkml/pull/364/files#diff-f715a403191ed7bfccfd1db9e835d484432652b18d6bb7da5fadfb0d6202a4bcR45-R46) ```diff - name: Test with pytest run: | pytest tests --cov=fastkml --cov=tests --cov-fail-under=95 --cov-report=xml +- name: Run exhaustive tests + if: github.event_name == 'schedule' + run: | + pytest tests --hypothesis-profile=exhaustive ``` - [ ] **Apply this suggestion**
    Suggestion importance[1-10]: 7 Why: Adding a step to run exhaustive tests periodically can help catch edge cases that might be missed in regular CI runs, improving the robustness of the test suite. This is a valuable enhancement to the CI pipeline.
    7
    βœ… Parameterize tests for different multi-geometry types to reduce code duplication and improve test maintainability ___
    Suggestion Impact:The commit refactored the tests by using a common geometry strategy with the `partial` function, which aligns with the suggestion's goal of reducing code duplication and improving maintainability for different multi-geometry types. code diff: ```diff -@given( +common_geometry = partial( + given, id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), target_id=st.one_of(st.none(), st.text(ID_TEXT)), extrude=st.one_of(st.none(), st.booleans()), tessellate=st.one_of(st.none(), st.booleans()), altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), +) + + +def _test_repr_roundtrip( + geometry: fastkml.geometry.MultiGeometry, + cls: type[MultiPoint | MultiLineString | MultiPolygon | GeometryCollection], +) -> None: + new_g = eval(repr(geometry), {}, eval_locals) # noqa: S307 + + assert geometry == new_g + if geometry: + assert type(new_g.geometry) is cls + + +def _test_geometry_str_roundtrip( + geometry: fastkml.geometry.MultiGeometry, + cls: type[MultiPoint | MultiLineString | MultiPolygon], +) -> None: + new_g = fastkml.geometry.MultiGeometry.class_from_string(geometry.to_string()) + + assert geometry.to_string() == new_g.to_string() + assert geometry == new_g + if geometry: + assert type(new_g.geometry) is cls + + +@common_geometry( geometry=st.one_of( st.none(), multi_points(srs=epsg4326), ), ) def test_multipoint_repr_roundtrip( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[MultiPoint], -) -> None: - multi_geometry = fastkml.geometry.MultiGeometry( - id=id, - target_id=target_id, - extrude=extrude, - tessellate=tessellate, - altitude_mode=altitude_mode, - geometry=geometry, - ) - - new_mg = eval(repr(multi_geometry), {}, eval_locals) # noqa: S307 - - assert multi_geometry == new_mg - if geometry: - assert isinstance(new_mg.geometry, MultiPoint) - - -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: MultiPoint | None, +) -> None: + multi_geometry = fastkml.geometry.MultiGeometry( + id=id, + target_id=target_id, + extrude=extrude, + tessellate=tessellate, + altitude_mode=altitude_mode, + geometry=geometry, + ) + + _test_repr_roundtrip(multi_geometry, MultiPoint) + + +@common_geometry( geometry=st.one_of( st.none(), multi_points(srs=epsg4326), ), ) def test_multipoint_str_roundtrip( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[MultiPoint], -) -> None: - multi_geometry = fastkml.geometry.MultiGeometry( - id=id, - target_id=target_id, - extrude=extrude, - tessellate=tessellate, - altitude_mode=altitude_mode, - geometry=geometry, - ) - - new_mg = fastkml.geometry.MultiGeometry.class_from_string( - multi_geometry.to_string(), - ) - - assert multi_geometry.to_string() == new_mg.to_string() - assert multi_geometry == new_mg - if geometry: - assert isinstance(new_mg.geometry, MultiPoint) - - -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: MultiPoint | None, +) -> None: + multi_geometry = fastkml.geometry.MultiGeometry( + id=id, + target_id=target_id, + extrude=extrude, + tessellate=tessellate, + altitude_mode=altitude_mode, + geometry=geometry, + ) + + _test_geometry_str_roundtrip(multi_geometry, MultiPoint) + + +@common_geometry( geometry=st.one_of( st.none(), multi_points(srs=epsg4326), ), ) def test_multipoint_str_roundtrip_terse( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[MultiPoint], + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: MultiPoint | None, ) -> None: multi_geometry = fastkml.geometry.MultiGeometry( id=id, @@ -166,24 +174,19 @@ assert isinstance(new_mg.geometry, MultiPoint) -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), +@common_geometry( geometry=st.one_of( st.none(), multi_points(srs=epsg4326), ), ) def test_multipoint_str_roundtrip_verbose( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[MultiPoint], + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: MultiPoint | None, ) -> None: multi_geometry = fastkml.geometry.MultiGeometry( id=id, @@ -205,97 +208,71 @@ assert isinstance(new_mg.geometry, MultiPoint) -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), +@common_geometry( geometry=st.one_of( st.none(), multi_line_strings(srs=epsg4326), ), ) def test_multilinestring_repr_roundtrip( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[MultiLineString], -) -> None: - multi_geometry = fastkml.geometry.MultiGeometry( - id=id, - target_id=target_id, - extrude=extrude, - tessellate=tessellate, - altitude_mode=altitude_mode, - geometry=geometry, - ) - - new_mg = eval(repr(multi_geometry), {}, eval_locals) # noqa: S307 - - assert multi_geometry == new_mg - if geometry: - assert isinstance(new_mg.geometry, MultiLineString) - - -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: MultiLineString | None, +) -> None: + multi_geometry = fastkml.geometry.MultiGeometry( + id=id, + target_id=target_id, + extrude=extrude, + tessellate=tessellate, + altitude_mode=altitude_mode, + geometry=geometry, + ) + + _test_repr_roundtrip(multi_geometry, MultiLineString) + + +@common_geometry( geometry=st.one_of( st.none(), multi_line_strings(srs=epsg4326), ), ) def test_multilinestring_str_roundtrip( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[MultiLineString], -) -> None: - multi_geometry = fastkml.geometry.MultiGeometry( - id=id, - target_id=target_id, - extrude=extrude, - tessellate=tessellate, - altitude_mode=altitude_mode, - geometry=geometry, - ) - - new_mg = fastkml.geometry.MultiGeometry.class_from_string( - multi_geometry.to_string(), - ) - - assert multi_geometry.to_string() == new_mg.to_string() - assert multi_geometry == new_mg - if geometry: - assert isinstance(new_mg.geometry, MultiLineString) - - -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: MultiLineString | None, +) -> None: + multi_geometry = fastkml.geometry.MultiGeometry( + id=id, + target_id=target_id, + extrude=extrude, + tessellate=tessellate, + altitude_mode=altitude_mode, + geometry=geometry, + ) + + _test_geometry_str_roundtrip(multi_geometry, MultiLineString) + + +@common_geometry( geometry=st.one_of( st.none(), multi_line_strings(srs=epsg4326), ), ) def test_multilinestring_str_roundtrip_terse( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[MultiLineString], + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: MultiLineString | None, ) -> None: multi_geometry = fastkml.geometry.MultiGeometry( id=id, @@ -317,24 +294,19 @@ assert isinstance(new_mg.geometry, MultiLineString) -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), +@common_geometry( geometry=st.one_of( st.none(), multi_line_strings(srs=epsg4326), ), ) def test_multilinestring_str_roundtrip_verbose( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[MultiLineString], + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: MultiLineString | None, ) -> None: multi_geometry = fastkml.geometry.MultiGeometry( id=id, @@ -356,97 +328,71 @@ assert isinstance(new_mg.geometry, MultiLineString) -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), +@common_geometry( geometry=st.one_of( st.none(), multi_polygons(srs=epsg4326), ), ) def test_multipolygon_repr_roundtrip( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[MultiPolygon], -) -> None: - multi_geometry = fastkml.geometry.MultiGeometry( - id=id, - target_id=target_id, - extrude=extrude, - tessellate=tessellate, - altitude_mode=altitude_mode, - geometry=geometry, - ) - - new_mg = eval(repr(multi_geometry), {}, eval_locals) # noqa: S307 - - assert multi_geometry == new_mg - if geometry: - assert isinstance(new_mg.geometry, MultiPolygon) - - -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: MultiPolygon | None, +) -> None: + multi_geometry = fastkml.geometry.MultiGeometry( + id=id, + target_id=target_id, + extrude=extrude, + tessellate=tessellate, + altitude_mode=altitude_mode, + geometry=geometry, + ) + + _test_repr_roundtrip(multi_geometry, MultiPolygon) + + +@common_geometry( geometry=st.one_of( st.none(), multi_polygons(srs=epsg4326), ), ) def test_multipolygon_str_roundtrip( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[MultiPolygon], -) -> None: - multi_geometry = fastkml.geometry.MultiGeometry( - id=id, - target_id=target_id, - extrude=extrude, - tessellate=tessellate, - altitude_mode=altitude_mode, - geometry=geometry, - ) - - new_mg = fastkml.geometry.MultiGeometry.class_from_string( - multi_geometry.to_string(), - ) - - assert multi_geometry.to_string() == new_mg.to_string() - assert multi_geometry == new_mg - if geometry: - assert isinstance(new_mg.geometry, MultiPolygon) - - -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: MultiPolygon | None, +) -> None: + multi_geometry = fastkml.geometry.MultiGeometry( + id=id, + target_id=target_id, + extrude=extrude, + tessellate=tessellate, + altitude_mode=altitude_mode, + geometry=geometry, + ) + + _test_geometry_str_roundtrip(multi_geometry, MultiPolygon) + + +@common_geometry( geometry=st.one_of( st.none(), multi_polygons(srs=epsg4326), ), ) def test_multipolygon_str_roundtrip_terse( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[MultiPolygon], + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: MultiPolygon | None, ) -> None: multi_geometry = fastkml.geometry.MultiGeometry( id=id, @@ -468,24 +414,19 @@ assert isinstance(new_mg.geometry, MultiPolygon) -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), +@common_geometry( geometry=st.one_of( st.none(), multi_polygons(srs=epsg4326), ), ) def test_multipolygon_str_roundtrip_verbose( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[MultiPolygon], + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: MultiPolygon | None, ) -> None: multi_geometry = fastkml.geometry.MultiGeometry( id=id, @@ -507,24 +448,19 @@ assert isinstance(new_mg.geometry, MultiPolygon) -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), +@common_geometry( geometry=st.one_of( st.none(), geometry_collections(srs=epsg4326), ), ) def test_geometrycollection_repr_roundtrip( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[GeometryCollection], + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: GeometryCollection | None, ) -> None: multi_geometry = fastkml.geometry.MultiGeometry( id=id, @@ -547,24 +483,19 @@ assert not new_mg -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), +@common_geometry( geometry=st.one_of( st.none(), geometry_collections(srs=epsg4326), ), ) def test_geometrycollection_str_roundtrip( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[GeometryCollection], + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: GeometryCollection | None, ) -> None: multi_geometry = fastkml.geometry.MultiGeometry( id=id, @@ -588,24 +519,19 @@ assert not new_mg -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), +@common_geometry( geometry=st.one_of( st.none(), geometry_collections(srs=epsg4326), ), ) def test_geometrycollection_str_roundtrip_terse( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[GeometryCollection], + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: GeometryCollection | None, ) -> None: multi_geometry = fastkml.geometry.MultiGeometry( id=id, @@ -629,24 +555,19 @@ assert not new_mg -@given( - id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), - target_id=st.one_of(st.none(), st.text(ID_TEXT)), - extrude=st.one_of(st.none(), st.booleans()), - tessellate=st.one_of(st.none(), st.booleans()), - altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), +@common_geometry( geometry=st.one_of( st.none(), geometry_collections(srs=epsg4326), ), ) def test_geometrycollection_str_roundtrip_verbose( - id: typing.Optional[str], - target_id: typing.Optional[str], - extrude: typing.Optional[bool], - tessellate: typing.Optional[bool], - altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[GeometryCollection], + id: str | None, + target_id: str | None, + extrude: bool | None, + tessellate: bool | None, + altitude_mode: AltitudeMode | None, + geometry: GeometryCollection | None, ) -> None: multi_geometry = fastkml.geometry.MultiGeometry( id=id, ```
    ___ **Consider parameterizing the tests for different multi-geometry types (MultiPoint,
    MultiLineString, MultiPolygon, GeometryCollection) to reduce code duplication and
    improve maintainability.** [tests/hypothesis/multi_geometry_test.py [57-75]](https://github.com/cleder/fastkml/pull/364/files#diff-62429ef5316bba4d85f3d395ed68e6adaf2bfa4bc618ac4ebadc42ca78d6a568R57-R75) ```diff +@pytest.mark.parametrize("geometry_type, geometry_strategy", [ + (MultiPoint, multi_points(srs=epsg4326)), + (MultiLineString, multi_line_strings(srs=epsg4326)), + (MultiPolygon, multi_polygons(srs=epsg4326)), + (GeometryCollection, geometry_collections(srs=epsg4326)), +]) @given( id=st.one_of(st.none(), st.text(alphabet=ID_TEXT)), target_id=st.one_of(st.none(), st.text(ID_TEXT)), extrude=st.one_of(st.none(), st.booleans()), tessellate=st.one_of(st.none(), st.booleans()), altitude_mode=st.one_of(st.none(), st.sampled_from(AltitudeMode)), - geometry=st.one_of( - st.none(), - multi_points(srs=epsg4326), - ), ) -def test_multipoint_repr_roundtrip( +def test_multi_geometry_repr_roundtrip( + geometry_type, + geometry_strategy, id: typing.Optional[str], target_id: typing.Optional[str], extrude: typing.Optional[bool], tessellate: typing.Optional[bool], altitude_mode: typing.Optional[AltitudeMode], - geometry: typing.Optional[MultiPoint], ) -> None: + geometry = st.one_of(st.none(), geometry_strategy).example() ``` - [ ] **Apply this suggestion**
    Suggestion importance[1-10]: 6 Why: Parameterizing tests can significantly reduce code duplication and improve maintainability, making it easier to manage and extend tests for different geometry types.
    6
    Enhance test coverage by using a more sophisticated strategy for generating geometry objects ___ **Consider using a custom composite strategy that combines different geometry types
    instead of using st.one_of() with st.none() for the geometry parameter. This would
    allow for more focused testing of non-null geometries and potentially uncover edge
    cases.** [tests/hypothesis/multi_geometry_test.py [64-66]](https://github.com/cleder/fastkml/pull/364/files#diff-62429ef5316bba4d85f3d395ed68e6adaf2bfa4bc618ac4ebadc42ca78d6a568R64-R66) ```diff geometry=st.one_of( st.none(), - multi_points(srs=epsg4326), + st.builds( + fastkml.geometry.MultiGeometry, + geometry=multi_points(srs=epsg4326) + ), ), ``` - [ ] **Apply this suggestion**
    Suggestion importance[1-10]: 5 Why: The suggestion proposes using a custom composite strategy for generating geometry objects, which could enhance test coverage by focusing on non-null geometries. However, the improvement is moderate as the existing strategy already covers a range of cases.
    5

    πŸ’‘ Need additional feedback ? start a PR chat

    github-actions[bot] commented 1 month ago

    Preparing review...

    github-actions[bot] commented 1 month ago

    Preparing review...

    github-actions[bot] commented 1 month ago

    Failed to generate code suggestions for PR

    codecov[bot] commented 1 month ago

    Codecov Report

    Attention: Patch coverage is 97.91045% with 7 lines in your changes missing coverage. Please review.

    Project coverage is 98.12%. Comparing base (b9812da) to head (1142a1e). Report is 17 commits behind head on develop.

    Files with missing lines Patch % Lines
    fastkml/geometry.py 58.82% 3 Missing and 4 partials :warning:
    Additional details and impacted files ```diff @@ Coverage Diff @@ ## develop #364 +/- ## =========================================== + Coverage 98.00% 98.12% +0.11% =========================================== Files 47 50 +3 Lines 4567 4848 +281 Branches 215 148 -67 =========================================== + Hits 4476 4757 +281 - Misses 58 63 +5 + Partials 33 28 -5 ```

    :umbrella: View full report in Codecov by Sentry.
    :loudspeaker: Have feedback on the report? Share it here.

    github-actions[bot] commented 1 month ago

    Preparing review...

    github-actions[bot] commented 1 month ago

    Preparing review...