Skip to main content

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 describe blocks 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:

  1. The TIDEN_REPOSITORY environment variable.
  2. CI variables: GITHUB_SERVER_URL with GITHUB_REPOSITORY (GitHub Actions), CI_SERVER_URL with CI_PROJECT_PATH (GitLab), BITBUCKET_GIT_HTTP_ORIGIN (Bitbucket Pipelines), BUILD_REPOSITORY_URI (Azure Pipelines).
  3. The origin remote 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.

ProducerHow to set the id
jestAdd (Tiden ID: 42) to the test title, or wrap the title: test(tiden(42, 'logs in'), …)
vitestAdd (Tiden ID: 42) to the test title, or wrap the title: test(addTidenId('logs in', [42]), …)
PlaywrightAdd (Tiden ID: 42) to the test title, or call tiden.id(42) inside the test
GoAdd the doc comment // tiden:id 42 above the test function
PHPUnitAdd the attribute #[TidenId(42)]
JUnit XMLAdd <property name="tiden_id" value="42"/> to the test case
SwiftNot 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.ts to session.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 merges lists merges and their ids.
  • tiden test unmerge restores the merged-away case with its own results. The MCP tool is unmerge_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-junit XML, 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 file attribute. For XML other than PHPUnit and Go, Tiden reads the language from the file attribute 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 TestA to TestB. Weeks later, you write a new, unrelated TestA. Its results join the TestB case. 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.