Environment
pytestomatio 2.13.0b0
Python 3.14, pytest
Windows 11, ~300 synced tests in the project
Summary
Every time pytest --testomatio sync runs (/api/load endpoint), for every test the plugin matches to a @pytest.mark.testomatio("@t...") marker in code:
self_tags is reset to [] (except tags covered by TESTOMATIO_TAG_MARKERS, if configured for that marker).
The test's title is silently overwritten with an auto-generated title derived from the Python test function name, with a ${browser_name} placeholder appended (pytest-playwright browser fixture parametrization).
Tags and titles set independently via the Testomat.io API or UI are treated as disposable by the sync, even though they were never part of the sync payload's intent.
Steps to Reproduce
In Testomat.io, set a custom, human-written title and add one or more custom tags on a test that has a corresponding @pytest.mark.testomatio("@t") marker in the pytest suite, e.g.:
PATCH /api/v2/{project}/tests/{id}
{ "title": "Verify X happens when Y", "link": [{"action":"add","type":"tag","value":"my-custom-tag"}] }
Confirm via GET /api/v2/{project}/tests/{id} — title and self_tags reflect the custom values.
Run pytest tests/ --testomatio sync --no-empty (with TESTOMATIO_TAG_MARKERS set to markers that do not include my-custom-tag, e.g. TESTOMATIO_TAG_MARKERS=e2e,no_parallel).
Fetch the same test again via GET /api/v2/{project}/tests/{id}.
Actual Behavior
Before sync:
{
"title": "Verify X happens when Y @my-custom-tag @another-tag",
"self_tags": ["my-custom-tag", "another-tag"],
"code": null
}
After pytest tests/ --testomatio sync --no-empty:
{
"title": "X happens when y ${browser_name}",
"self_tags": [],
"code": " @pytest.mark.testomatio(\"@T<id>\")\n def test_x_happens_when_y(...):\n ...\n"
}
(code becoming populated confirms the plugin matched/processed this test in this run.) This is not limited to newly-touched tests — a single sync run resets self_tags for every matched test in the project, not just ones whose code changed.
Expected Behavior
/api/load should only sync code-derived structural fields (file path, class/function name via the marker). It should not overwrite title or self_tags set independently through the API/UI when they're absent from the sync payload.
Secondary issue: propagation delay
Immediately after the sync command finished, a GET on the affected test still returned the pre-sync values (old title, old tags, code: null). A GET issued again shortly after returned the fully updated values. Suggests an async/indexing lag between the sync write and it becoming consistently readable — worth noting for anyone scripting a read-immediately-after-sync check.
Current Workaround
We maintain a script that re-applies specific tags after every sync by scanning test files for a known pytest marker and re-PATCHing those tags via the API. This only covers tags backed by an actual pytest marker (via TESTOMATIO_TAG_MARKERS). Any tag or title set purely through the API/UI — with no corresponding pytest marker — has no recovery path and is lost on every sync. At ~300 synced tests this makes sync a lossy operation for most tagging/title metadata.
Suggested Fix
(a) Omit tags/title from the /api/load payload unless the plugin is explicitly configured to manage them, so the backend leaves existing values untouched, or
(b) Merge/preserve existing self_tags/title server-side rather than overwriting when the incoming payload doesn't explicitly specify them.
Environment
pytestomatio 2.13.0b0
Python 3.14, pytest
Windows 11, ~300 synced tests in the project
Summary
Every time pytest --testomatio sync runs (/api/load endpoint), for every test the plugin matches to a @pytest.mark.testomatio("@t...") marker in code:
self_tags is reset to [] (except tags covered by TESTOMATIO_TAG_MARKERS, if configured for that marker).
The test's title is silently overwritten with an auto-generated title derived from the Python test function name, with a ${browser_name} placeholder appended (pytest-playwright browser fixture parametrization).
Tags and titles set independently via the Testomat.io API or UI are treated as disposable by the sync, even though they were never part of the sync payload's intent.
Steps to Reproduce
In Testomat.io, set a custom, human-written title and add one or more custom tags on a test that has a corresponding @pytest.mark.testomatio("@t") marker in the pytest suite, e.g.:
Actual Behavior
Before sync:
After pytest tests/ --testomatio sync --no-empty:
(code becoming populated confirms the plugin matched/processed this test in this run.) This is not limited to newly-touched tests — a single sync run resets self_tags for every matched test in the project, not just ones whose code changed.
Expected Behavior
/api/load should only sync code-derived structural fields (file path, class/function name via the marker). It should not overwrite title or self_tags set independently through the API/UI when they're absent from the sync payload.
Secondary issue: propagation delay
Immediately after the sync command finished, a GET on the affected test still returned the pre-sync values (old title, old tags, code: null). A GET issued again shortly after returned the fully updated values. Suggests an async/indexing lag between the sync write and it becoming consistently readable — worth noting for anyone scripting a read-immediately-after-sync check.
Current Workaround
We maintain a script that re-applies specific tags after every sync by scanning test files for a known pytest marker and re-PATCHing those tags via the API. This only covers tags backed by an actual pytest marker (via TESTOMATIO_TAG_MARKERS). Any tag or title set purely through the API/UI — with no corresponding pytest marker — has no recovery path and is lost on every sync. At ~300 synced tests this makes sync a lossy operation for most tagging/title metadata.
Suggested Fix
(a) Omit tags/title from the /api/load payload unless the plugin is explicitly configured to manage them, so the backend leaves existing values untouched, or
(b) Merge/preserve existing self_tags/title server-side rather than overwriting when the incoming payload doesn't explicitly specify them.