Metadata-Version: 2.4
Name: juwunit
Version: 0.1.3
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: Implementation :: CPython
License-File: LICENSE-APACHE
License-File: LICENSE-MIT
Summary: Small JUnit XML serialization/deserialization for Python
Author-email: "Astral Software Inc." <hey@astral.sh>
License-Expression: MIT OR Apache-2.0
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Releases, https://github.com/astral-sh/juwunit/releases
Project-URL: Repository, https://github.com/astral-sh/juwunit

# juwunit

_juwunit_ is a small JUnit XML serializer and deserializer for Python.

It's a small Python layer on top of the excellent [quick-junit].

[quick-junit]: https://crates.io/crates/quick-junit

## Usage

Install it:

```console
uv add juwunit
```

Loading a report:

```python
import juwunit

report = juwunit.Report.from_xml("...")
for suite in report.test_suites:
    for case in suite.test_cases:
        print(f"{case.name}: {case.status}")
```

Building a report:

```python
import juwunit

case = juwunit.TestCase("my-test", status=juwunit.Success())
suite = juwunit.TestSuite("my-suite")
suite.add_test_case(case)
report = juwunit.Report("my-report")
report.add_test_suite(suite)

print(report.to_xml())
```

The Python API follows `quick-junit` closely while using Python-native types where that is more
natural:

- `uuid.UUID` for report UUIDs
- timezone-aware `datetime.datetime` for timestamps
- `datetime.timedelta` for durations
- `Success`, `Failure`, `Error`, and `Skipped` status objects
- `dict[str, str]`-style `extra` attributes and ordered `Property` objects

## Development

Install the editable extension:

```shell
uv run --dev maturin develop
```

Run the unit tests:

```shell
# rust side
cargo test

# python side
uv run --dev pytest
```

Linting/formatting/typechecking:

```shell
uv run --dev ruff format
uv run --dev ruff check --fix
uv run --dev ty check
```

