Skip to content

fix: LibreOffice - serialize output_file_type and increase unit tests coverage - #3793

Merged
julian-risch merged 6 commits into
mainfrom
test/libreoffice-unit-coverage
Aug 25, 2026
Merged

fix: LibreOffice - serialize output_file_type and increase unit tests coverage#3793
julian-risch merged 6 commits into
mainfrom
test/libreoffice-unit-coverage

Conversation

@julian-risch

@julian-risch julian-risch commented Aug 16, 2026

Copy link
Copy Markdown
Member

Related Issues

I also found two small problems to fix so this PR does not just increase unit test coverage.

Proposed Changes:

Fixes:

  • to_dict() dropped output_file_type, so it did not survive a from_dict() round trip. Pass it through.
  • run_async discarded the soffice exit code, while run passes check=True. Since every ByteStream in one call is written to the same input temp file, a failed async conversion could return the previous source's converted bytes rather than raising. Now, we check the exit code and raise the same CalledProcessError the sync path already raises

Tests:

  • Add unit tests to increase coverage, mostly by patching the soffice call instead of requiring a LibreOffice installation: run_async (was 0%), the run ByteStream branch, _get_conversion_args, every _validate_args reject branch, and the output_file_type resolution
  • Split the suite into focused classes (as suggested in test: Unstructured - increase unit tests coverage #3794) TestInit, TestSerde, TestGetConversionArgs, TestValidateArgs, TestConvert, TestResolveMimeType, TestRunIntegration. TestConvert is parametrized over run and run_async
  • Move fixtures to tests/conftest.py
  • Rewrite four pre-existing integration tests into one parametrized case

How did you test it?

Notes for the reviewer

Checklist

  • I have read the contributors guidelines and the code of conduct
  • I have updated the related issue with new insights and changes — n/a
  • I added unit tests and updated the docstrings
  • I've used one of the conventional commit types for my PR title: fix:, feat:, build:, chore:, ci:, docs:, style:, refactor:, perf:, test:.

… coverage

to_dict() called default_to_dict(self) without any init parameters, so a
converter built with output_file_type="pdf" serialized to empty
init_parameters and came back from from_dict() with output_file_type=None.
Pass the parameter through so the round trip is lossless, and update the
two serialization tests that pinned the old behaviour.

On top of that, cover the paths that were only reachable through the
integration-marked tests, which the unit coverage badge excludes:

- run_async: the whole method was at 0%, both the path and ByteStream
  branches, by patching create_subprocess_exec
- run: the ByteStream branch, the output_file_type resolution and its
  ValueError, and input-type inference from the filename
- _get_conversion_args: the exact soffice argv, the derived output path,
  and the missing-source and unwritable-outdir errors
- _validate_args: every accept and reject branch

The soffice stand-in derives the output path from the argv the converter
built, so the tests fail if that contract changes.

Fixtures move to tests/conftest.py, where test_files_path is anchored to
__file__ instead of the current working directory.

Unit coverage: 58% -> 100%.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added integration:libreoffice type:documentation Improvements or additions to documentation labels Aug 16, 2026
@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Coverage report (libreoffice)

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  integrations/libreoffice/src/haystack_integrations/components/converters/libreoffice
  converter.py
Project Total  

This report was generated by python-coverage-comment-action

julian-risch and others added 5 commits August 20, 2026 17:48
Drop the separate test_converter_unit.py and merge everything into
test_converter.py, split into focused classes rather than one big class:
TestInit, TestSerde, TestGetConversionArgs, TestValidateArgs, TestRun,
TestRunAsync, TestResolveMimeType and TestRunIntegration. This follows the
review on #3794, down to the class naming, and hoists the integration and
asyncio markers onto the classes instead of repeating them per method.

Cover the behaviour the to_dict() fix protects, which was only asserted at
the attribute level before:

- run and run_async pick up output_file_type from __init__ when the argument
  is omitted, and the argument wins when both are set
- a converter that has been through to_dict() -> from_dict() still converts
  without an output_file_type argument, so reverting the fix fails the test
- from_dict() still accepts dictionaries serialized before output_file_type
  was included
- both ValueError paths when output_file_type is set nowhere, and the
  _validate_args branch for a type outside OUTPUT_FILE_TYPE entirely

Rename the `converter` fixture to `real_converter`, since next to
`mock_converter` the bare name did not convey that it needs an actual
LibreOffice installation, and give the remaining fixtures docstrings.

Unit coverage: 93% -> 100%.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
run passes check=True to subprocess.run, so a failed conversion raises
CalledProcessError. run_async discarded the exit code instead, and because
every ByteStream in one call is written to the same `input` temp file, a
failed conversion could return the previous source's converted bytes rather
than raising. For file path sources it surfaced as a FileNotFoundError on
the missing output instead.

Check the exit code and raise the same CalledProcessError the sync path
already raises, and document it on both methods, since run had this
behaviour all along without saying so.

The async soffice stand-in gains a settable returncode so the new test can
make it report a failure, parametrized over a path and a ByteStream source
to cover both call sites.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
run and run_async share their logic, so the tests duplicated every case.
Collapse them into a TestConvert class parametrized over ["run",
"run_async"], driven by a small _convert helper, and merge the two soffice
stand-ins into one fake_soffice fixture that patches both call sites,
records each argv and honours a settable returncode. This also covers run's
own check=True failure path, which nothing exercised before.

Parametrize the leftovers the same way: the three validation rejects and the
three mime type cases each become one table, and the four integration tests
become one case parametrized over sync/async and path/ByteStream sources,
which still collects as four tests.

Test code drops from 403 to 313 lines, 51 fewer added lines, with the same
29 unit tests and statement and branch coverage still at 100%. Async
coverage now rides the shared test bodies instead of a duplicated class, so
it no longer costs anything to keep.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ested

`fake_soffice._run` raised `CalledProcessError` on a non-zero `returncode`
regardless of its arguments, so `test_raises_when_soffice_exits_non_zero[*-run]`
asserted the fixture's behaviour rather than the converter's: removing
`check=True` from both `subprocess.run` calls left all four parametrizations
green.

Honour `check` the way `subprocess.run` does. The sync cases now cover the
same contract the new `run_async` exit-code handling does — that a failed
conversion raises instead of returning the previous source's bytes — and fail
if `check=True` is ever dropped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@julian-risch
julian-risch marked this pull request as ready for review August 21, 2026 15:48
@julian-risch
julian-risch requested a review from a team as a code owner August 21, 2026 15:48
@julian-risch
julian-risch requested review from anakin87 and sjrl and removed request for a team and anakin87 August 21, 2026 15:48

@sjrl sjrl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@julian-risch
julian-risch merged commit 3c4805f into main Aug 25, 2026
22 of 23 checks passed
@julian-risch
julian-risch deleted the test/libreoffice-unit-coverage branch August 25, 2026 06:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

integration:libreoffice type:documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants