Skip to content

refactor: improve error handling and add comprehensive test coverage#462

Merged
gibiw merged 18 commits intomainfrom
refactor/error-handling-core-reporter
Mar 6, 2026
Merged

refactor: improve error handling and add comprehensive test coverage#462
gibiw merged 18 commits intomainfrom
refactor/error-handling-core-reporter

Conversation

@gibiw
Copy link
Contributor

@gibiw gibiw commented Mar 6, 2026

Summary

  • Replace bare except clauses with specific exception types across all reporter packages (pytest, robotframework, commons)
  • Classify initialization errors as auth, network, or unknown in core reporter with debug logging
  • Add null guards and str cast in tavern plugin pytest hooks for xdist compatibility
  • Fix pytest_plugins location for pytest 7.2+ compatibility
  • Fix Robot Framework deprecated Return.args warning
  • Add comprehensive error-scenario unit tests for all packages (339 total tests passing)

Changes by package

qase-python-commons (5.0.3 → 5.0.4)

  • Classify init errors as auth/network/unknown in core reporter
  • Replace bare except with specific types in DB profiler
  • Add debug logging for error scenarios
  • Remove dead code (commented-out selective execution, empty stubs)
  • 219 unit tests passing

qase-pytest (8.0.0 → 8.0.1)

  • Replace bare except clauses with specific exception types
  • Remove empty _set_relations stub
  • Fix pytest_plugins location for pytest 7.2+ compat
  • 20 unit tests passing

qase-robotframework (5.0.1 → 5.0.2)

  • Fix deprecated Return.args warning
  • 32 unit tests passing

qase-tavern (3.0.0 → 3.0.1)

  • Add None guards for runtime.result in pytest_runtest_makereport and pytest_runtest_logfinish
  • Fix TypeError in stacktrace join when exception args contain non-string types
  • Fixes pytest-xdist parallel execution compatibility
  • 25 unit tests passing

Test plan

  • All 339 tests pass sequentially across 5 packages
  • All 339 tests pass with pytest -n auto (pytest-xdist parallel mode)

gibiw added 18 commits March 5, 2026 20:32
…orter;

- Delete commented-out call `# self._selective_execution_setup()` on line 39
- Delete entire commented-out `_selective_execution_setup` method definition (lines 241-251)
- Live code (_load_testops_plan, get_execution_plan, _fallback_setup) remains intact
- Delete no-op _set_relations method definition (was just `pass`)
- Delete _set_relations(item) call from start_pytest_item method
- All other setup methods in start_pytest_item remain intact
…mented;

- Add docstring to ExecutionPlan class explaining file-based loading is not yet implemented
- Execution plans are currently loaded from Qase TestOps API via testops.plan.id
- No changes to __init__ or set_path methods
…n pytest plugin

- Replace 6 bare `except:` with `except (AttributeError, TypeError):` in marker-reading methods
- Use `except (AttributeError, TypeError, ValueError):` for _set_testops_ids (int conversion)
- Prevents catching SystemExit/KeyboardInterrupt during marker absence handling
…eporter

- Add _is_auth_error() helper with lazy import of API client exceptions
  and string fallback for wrapped exceptions
- Add _is_network_error() helper checking ConnectionError, OSError,
  and urllib3 MaxRetryError/NewConnectionError
- Split except Exception into except ReporterException (with error
  classification) followed by catch-all except Exception
- Auth errors now log "Authentication failed" with API host
- Network errors now log "Network error" with host and error details
- Unknown ReporterException errors log original exception message
- Unexpected errors log exception type name and message
- Fallback reporter assignment preserved in all 4 except branches
- Applied same pattern to both testops and testops_multi modes
- Replace bare `except:` in SQLAlchemy params formatting with `except (TypeError, ValueError):`
- Replace 19 silent `except Exception: pass` blocks with debug-level logging
- Use `logging.getLogger(__name__).debug()` for all wrapper-level logging errors
- Keep `import logging` inside except blocks (lazy-import pattern)
- Secondary info-gathering blocks and ImportError blocks unchanged
- mode=off produces reporter=None
- mode=report produces QaseReport instance
- mode=testops produces QaseTestOps instance with ApiV2Client
- mode=testops_multi produces QaseTestOpsMulti instance with ApiV2Client
…rter

- ReporterException and generic Exception both trigger fallback to QaseReport
- No fallback configured results in reporter=None after failure
- Fallback works for testops_multi mode as well
- _is_auth_error correctly identifies 401/403/unauthorized strings
- _is_network_error correctly identifies ConnectionError/OSError
- Auth errors log "Authentication failed" with host context
- Network errors log "Network error" with host context
…and error scenarios

- Test enable() registers sqlite3 hook and replaces sqlite3.connect
- Test disable() restores original functions and clears state
- Test enable/disable idempotent behavior (double-enable safe)
- Test singleton init/get_instance/double-init lifecycle
- Test graceful handling of unavailable optional libraries
- Test runtime step recording on actual sqlite3 query execution
- Test enable() patches requests.Session.send when requests in sys.modules
- Test enable() patches urllib3.PoolManager.request
- Test enable() skips patching when module not in sys.modules
- Test disable() is safe to call without prior enable()
- Test singleton init/get_instance/double-init/reset lifecycle
- Add 19 unit tests for QasePytestPlugin covering _get_qase_ids,
  _get_title, _set_fields, _set_testops_ids, _set_author, _set_muted
- Test graceful handling of missing/malformed markers
- Test singleton lifecycle (init, get_instance, PluginNotInitializedException)
- All tests use MagicMock to avoid framework auto-registration
- 25 TagParser tests covering empty input, valid/malformed Q-ids, qase.ignore,
  qase.fields (valid/invalid JSON), qase.params, multi-project tags, mixed tags
- 7 Listener static helper tests for _create_gherkin_step_with_type,
  _create_gherkin_step_from_name, _set_step_status_based_on_children
- Replaces placeholder test_listener.py (assert True) with real tests
- Add 15 unit tests covering malformed tag parsing, multi-project tags,
  step status mapping edge cases, and scenario field handling
- Test ValueError/IndexError on malformed qase.id tags
- Test graceful JSON fallback in qase.fields parsing
- Test qase.ignore, qase.suite with || separator, and filter_scenarios
- 5 extract_qase_ids error path tests (non-string inputs, empty string,
  no pattern match)
- 3 multi-project ID extraction tests (multiple projects, precedence over
  QaseID, multiple IDs per project)
- 2 _get_title tests (with spec, without spec)
- 3 _set_relations tests (with fspath, without fspath, fspath without basename)
- 2 _set_steps tests (without spec, with spec and stages via mock)
- Moved pytest_plugins = ["pytester"] from nested conftest to tests/conftest.py
- Fixes "Defining 'pytest_plugins' in a non-top-level conftest is no longer supported" error
- All 5 package test suites pass: commons(219), pytest(20), behave(43), robotframework(32), tavern(25)
Tavern plugin registers globally as a pytest plugin, so its hooks fire
for all packages. Added None checks for runtime.result in makereport
and logfinish hooks, and cast exception args to str before joining to
prevent TypeError with non-string args. Fixes pytest-xdist compatibility.
qase-python-commons 5.0.3 → 5.0.4
qase-pytest 8.0.0 → 8.0.1
qase-robotframework 5.0.1 → 5.0.2
qase-tavern 3.0.0 → 3.0.1
Remove non-existent 'all' extra from tox configs for pytest, behave,
and tavern packages. Add robotframework>=5.0 to robotframework testing
deps so tests can import the robot module. Fix test_listener.py patch
target to use robot.libraries.BuiltIn.BuiltIn.
@gibiw gibiw merged commit 21d1f21 into main Mar 6, 2026
36 checks passed
@gibiw gibiw deleted the refactor/error-handling-core-reporter branch March 6, 2026 11:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant