allure-framework / allure-framework/allure-python
KeyError in allure_pytest when running pytest.main() from inside a test (nested pytest run)
- Dominant language
- Python
- Stars
- 814
- Forks
- 260
- PR merge metrics
- No merged PRs in 30d
Description
Running a nested pytest session (subsession) from within a test using `pytest.main()` causes `allure` to fail during teardown in subsession with a `KeyError` in `allure_commons/reporter.py`.
The inner test passes, but `allure` raises an exception, causing the overall main test to fail.
The issue reproduces **only** when both main and sub sessions use allure (for example, via configuration (`pytest.ini` or `pyproject.toml`) and the subsession runs teardown fixtures.
The report shows the subtest as broken and duplicates teardown fixtures for it - one fixture has `passed` state, and the duplicate has `unknown` state.
| simple_fixture::0 | Unknown |
|-|-|
| simple_fixture::0 | 0s|
Overriding `alluredir` doesn't help - allure report for main session always contains both tests, allure report for subsession - only its test.
Steps to reproduce:
1. Set pytest ini options (I'm using `pyproject.toml`)
```toml
[tool.pytest.ini_options]
addopts = [
"-v",
"--alluredir", "allure-results",
]
```
2. Create test file
```python
from pathlib import Path
import pytest
def test_parent():
args: list[str] = [
f"{Path(__file__)}::test_child",
]
result = pytest.main(args)
assert not result
@pytest.fixture()
def simple_fixture():
yield 2
def test_child(simple_fixture):
assert simple_fixture == 2
```
3. Run the command
```bash
pytest test/test_parent.py::test_parent
```
Actual result:
```log
❯ poetry run pytest test/test_parent.py::test_parent
======================================== test session starts =========================================
platform darwin -- Python 3.13.5, pytest-8.4.0, pluggy-1.6.0 -- /example_dir/Library/Caches/pypoetry/virtualenvs/tests_repo-CJ2ygyH8-py3.13/bin/python
cachedir: .pytest_cache
rootdir: /example_dir/tests_repo
configfile: pyproject.toml
plugins: allure-pytest-2.14.2, xdist-3.7.0, instafail-0.5.0, anyio-4.9.0, timeout-2.4.0, check-2.5.3, mock-3.14.1, cov-6.1.1
collected 1 item
test/test_parent.py::test_parent FAILED [100%]
============================================== FAILURES ==============================================
____________________________________________ test_parent _____________________________________________
def test_parent():
args: list[str] = [
"-s",
f"{Path(__file__)}::test_child",
]
result = pytest.main(args)
> assert not result
E assert not
test/test_parent.py:12: AssertionError
---------------------------------------- Captured stdout call ----------------------------------------
============================= test session starts ==============================
platform darwin -- Python 3.13.5, pytest-8.4.0, pluggy-1.6.0 -- /example_dir/Library/Caches/pypoetry/virtualenvs/tests_repo-CJ2ygyH8-py3.13/bin/python
cachedir: .pytest_cache
rootdir: /example_dir/tests_repo
configfile: pyproject.toml
plugins: allure-pytest-2.14.2, xdist-3.7.0, instafail-0.5.0, anyio-4.9.0, timeout-2.4.0, check-2.5.3, mock-3.14.1, cov-6.1.1
collecting ... collected 1 item
test/test_parent.py::test_child PASSED
test/test_parent.py::test_child ERROR
==================================== ERRORS ====================================
_______________________ ERROR at teardown of test_child ________________________
self = , args = ()
kwargs = {}
def __call__(self, *args, **kwargs):
self.parameters = func_parameters(self._fixture_function, *args, **kwargs)
> with self:
^^^^
../../Library/Caches/pypoetry/virtualenvs/tests_repo-CJ2ygyH8-py3.13/lib/python3.13/site-packages/allure_commons/_allure.py:230:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../Library/Caches/pypoetry/virtualenvs/tests_repo-CJ2ygyH8-py3.13/lib/python3.13/site-packages/allure_commons/_allure.py:240: in __exit__
plugin_manager.hook.stop_fixture(parent_uuid=self._parent_uuid,
../../Library/Caches/pypoetry/virtualenvs/tests_repo-CJ2ygyH8-py3.13/lib/python3.13/site-packages/allure_pytest/listener.py:66: in stop_fixture
self.allure_logger.stop_after_fixture(uuid,
../../Library/Caches/pypoetry/virtualenvs/tests_repo-CJ2ygyH8-py3.13/lib/python3.13/site-packages/allure_commons/reporter.py:109: in stop_after_fixture
self._update_item(uuid, **kwargs)
../../Library/Caches/pypoetry/virtualenvs/tests_repo-CJ2ygyH8-py3.13/lib/python3.13/site-packages/allure_commons/reporter.py:62: in _update_item
item = self._items[uuid] if uuid else self._items[next(reversed(self._items))]
^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self =
item = '5073499a-d95d-40a6-a635-36507b26b451'
def __getitem__(self, item):
> return self.thread_context.__getitem__(item)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E KeyError: '5073499a-d95d-40a6-a635-36507b26b451'
../../Library/Caches/pypoetry/virtualenvs/tests_repo-CJ2ygyH8-py3.13/lib/python3.13/site-packages/allure_commons/reporter.py:33: KeyError
=========================== short test summary info ============================
ERROR test/test_parent.py::test_child - KeyError: '5073499a-d95d-40a6-a635-36...
========================== 1 passed, 1 error in 0.05s ==========================
====================================== short test summary info =======================================
FAILED test/test_parent.py::test_parent - assert not
========================================= 1 failed in 0.14s ==========================================
```
Contributor guide
Assessment
This issue has not been assessed yet.