How Tiden identifies a test case
Every result that Tiden receives belongs to one test case. Tiden decides which one from what the reporter sends. This page explains what that is, what keeps a case's history when a test moves or changes name, and how to correct a wrong match.
What a reporter sends
A reporter sends three things for each test:
- The repository the test lives in.
- The file or package, relative to the repository root.
- The test name, including its
describeblocks or parent tests.
Tiden builds the case key from these parts. The key does not depend on the framework. Two producers that describe the same test send the same parts, so their results land on one test case.
Example. This test is in github.com/acme/shop:
src/auth/login.test.ts
describe('Auth') > describe('Session') > test('logs in')
- The vitest reporter and the jest reporter both send this repository, this
file, and the name path
Auth,Session,logs in. Both reports update one test case. - A Reverse PR import of the same test uses the same parts. Its test case matches the reporter's results. You do not get a second case.
Two tests in different repositories of one product can share a file path and a name. They are two test cases, because the repository is part of the key.
The repository
JavaScript, PHP, and Swift reporters find the repository in this order:
- The
TIDEN_REPOSITORYenvironment variable. - CI variables:
GITHUB_SERVER_URLwithGITHUB_REPOSITORY(GitHub Actions),CI_SERVER_URLwithCI_PROJECT_PATH(GitLab),BITBUCKET_GIT_HTTP_ORIGIN(Bitbucket Pipelines),BUILD_REPOSITORY_URI(Azure Pipelines). - The
originremote in.git/config.
The Go reporter and tiden run report read the git remote. Any git host works.
Set TIDEN_REPOSITORY when a build runs outside a git checkout, for example in
a container that has no .git directory:
export TIDEN_REPOSITORY=github.com/acme/shop
Without a repository, the reporter warns once and sends results the way earlier
reporter versions did. Those results still match their existing test cases.
Two repositories that use the same file path and test name can then collide on
one test case. Tiden keeps these results on a separate "conflict" case. The
Quality Gate shows identity conflict on the spec's linked test cases. To
clear it, set TIDEN_REPOSITORY (or run the reporter in a checkout with an
origin remote) and report again.
What keeps history across a rename or move
A test case keeps its history when Tiden can show that a changed test is still the same test. Tiden uses three kinds of evidence, in this order.
Explicit ids
An explicit id ties a test to a case number. The id survives any rename or move. Add it where you expect a test to change.
| Producer | How to set the id |
|---|---|
| jest | Add (Tiden ID: 42) to the test title, or wrap the title: test(tiden(42, 'logs in'), …) |
| vitest | Add (Tiden ID: 42) to the test title, or wrap the title: test(addTidenId('logs in', [42]), …) |
| Playwright | Add (Tiden ID: 42) to the test title, or call tiden.id(42) inside the test |
| Go | Add the doc comment // tiden:id 42 above the test function |
| PHPUnit | Add the attribute #[TidenId(42)] |
| JUnit XML | Add <property name="tiden_id" value="42"/> to the test case |
| Swift | Not available yet |
Example in Go:
// tiden:id 42
func TestLogin(t *testing.T) {
// ...
}
Results for this test go to test case 42. If the test already had its own case, for example case 57, Tiden merges case 57 into case 42. This needs proof that both cases are in the same repository.
Detected moves and renames
Tiden reads merged pull requests. It detects two changes without an explicit id:
- A file move. A merged pull request moves
login.test.tstosession.test.ts. The test cases in the old file follow the file. The next run lands on them. This works for every JavaScript framework. - A rename with an unchanged body. A Go or vitest test gets a new name and its body stays the same. Tiden keeps the case. A body that is too short, or that matches another test, is not enough evidence.
Manual merge
For any other change, merge the cases yourself. Use the survivor you want to keep. Tiden keeps the older case by default, because it holds the history.
tiden test merge 61 --into 57 --reason "renamed in #1204"
The MCP server has the same action as merge_test_cases. The merge moves the
results and links of case 61 to case 57. Old links and references to case 61
still resolve to case 57.
Duplicate cases already in a product
A product can already hold two cases for one test. For example, a Reverse PR import created one and a reporter created the other. Tiden merges such a pair into the older case when both cases share a key and Tiden can prove they are in the same repository. New results land on the older case from that point.
Every merge has an id and can be undone:
tiden test merges
tiden test unmerge <merge-id>
tiden test mergeslists merges and their ids.tiden test unmergerestores the merged-away case with its own results. The MCP tool isunmerge_test_cases.- Tiden does not merge that pair again.
- If a later merge involves one of the cases, the command refuses and names the merge to undo first.
Playwright projects
A Playwright project, for example chromium or webkit, is a way to run a
test. It is not a different test. Tiden records the project name as a
parameter on the result. One test case shows all its project runs.
Known limits
- One producer per suite. If you send jest results through the native
reporter and also as
jest-junitXML, you get two test cases. The XML exporters for jest, vitest, and Playwright format names in different ways, so Tiden cannot match them exactly. PHPUnit and Go XML do match their native reporters. - JUnit XML without a
fileattribute. For XML other than PHPUnit and Go, Tiden reads the language from thefileattribute of each test case. If the attribute is missing, Tiden matches the case by its name only. The default pytest format omits it: run pytest with-o junit_family=xunit1. - Renames without an explicit id. Tiden detects an unchanged-body rename
for Go and vitest. In jest, Playwright, PHPUnit, Swift, and JUnit-imported
tests, a renamed test becomes a new case unless it has an explicit id. Use
tiden test merge. File moves are detected for all JavaScript frameworks. - Swift. There is no explicit id yet. A Swift test that changes name and
body becomes a new case. Merge the two cases with
tiden test merge. - A new test that reuses an old name. You rename
TestAtoTestB. Weeks later, you write a new, unrelatedTestA. Its results join theTestBcase. Give the new test an explicit id to keep it apart. - Deleted tests. A case whose test no longer exists keeps its last status.
See also Tests and the CLI reference.