TestLink Migration: What the XML Export Actually Carries
Before you promise anyone a cutover date, know what TestLink's XML export carries, what it drops, and the ordered plan that keeps the migration honest.

A QA lead at a mid sized company opens a ticket titled "move off TestLink" and closes their laptop for the day without answering it. The reason is not that TestLink is bad. It has held their suite together for six years and survived two reorganizations. Nobody on the current team even set it up.
The reason is that a TestLink migration is not a task, it is a promise, and promises need a date attached to them. Before that date gets said out loud in a planning meeting, the QA lead needs one thing. They need an honest inventory of what actually comes out of the export button.
This post is that inventory. It is followed by the order of operations that turns it into a real plan instead of a guess.
TestLink itself deserves a fair word here. Checked on 25 August 2026, it is GPL-2.0, written in PHP, with about 1.6k stars on GitHub. Version 1.9.20 is the final release of the 1.9.x family.
A 2.x line is in active development, and the maintainer posted a progress update as recently as 6 December 2025. That is not the profile of an abandoned project. It is the profile of a mature one, aging the way infrastructure ages when a small team keeps it running without much fanfare.
Nothing below is a criticism of that project. It is a description of what its export format was built to carry, and what it was never asked to carry.
The single fact that decides everything
TestLink's XML export carries case structure reasonably well. It keeps almost no run history. If you remember nothing else from this post, remember that sentence, because it is the fact your whole plan hinges on.
A migration where nobody needs last year's pass and fail results is a different, much smaller project than one where an auditor or a customer might ask a hard question. Did the team test this before the last release shipped. That single question changes how much work the migration actually is.
What the XML export actually carries
Run an export on a real suite and open the file in a text editor. You will find three things that come across well:
- Case titles, carried across cleanly and almost always readable exactly as written
- Step text and expected results, generally intact, including most formatting
- Suite and folder structure, preserved as a nested hierarchy
That is the good news, and it is genuinely good. The bad news sits in two other layers of the same file.
Custom fields and attachments come across partially. A custom field defined with a simple text or dropdown type usually survives the trip. One built with a more elaborate configuration, or one referencing another table in the TestLink database, often does not travel cleanly. You will not know which is which until you look at the actual output.
Execution history and most requirement links do not come across at all. The XML export was built as a case export, not a full database dump. The run log lives in a different part of the underlying schema, one the export was never designed to touch.
Why that inventory decides the plan
Once you know that, the branch point in your plan becomes obvious. If nobody needs the history, you export, map the fields, and go. That is a project measured in days, not months.
If the history matters, whether for a compliance requirement, a customer contract, or simply because someone will ask whether the team ever saw a bug before, you need a second export path. That usually means the API, if the installed version has one enabled, or a direct query against the underlying MySQL tables.
That second path is a meaningfully larger amount of work. It belongs in the plan from day one rather than surfacing as a surprise in week three, after a cutover date has already been promised to a director. Teams that skip this check tend to discover the gap during the dry run instead, which is late but still recoverable.
The ordered plan
Skipping steps here is the single most common way these projects run over budget and over time. Work through them in order, and resist the urge to jump straight to the full export:
- Export a sample suite first, not the whole install
- Inspect the exported file by hand, opening it in a text editor rather than trusting a summary count
- Decide, as a team, what history is actually worth carrying forward
- Map every field, including the custom ones, before writing any import script
- Run a full dry run into a scratch instance before agreeing a cutover date with anyone
A worked example with numbers
Take a support software team of twelve engineers running a TestLink instance that had been in place for five years. They exported 1,400 cases ahead of a planned move, expecting the worst.
The worst did not happen for the case content itself. Step text and expected results came across cleanly for essentially all 1,400 cases, and the suite folder structure mapped over without any manual rework. That part of the migration was almost boring, in the best way a migration can be.
The history was a different story. None of the eleven months of run history in that same instance came with the XML export, because it was never designed to carry it. The team lost visibility into roughly 3,000 recorded pass and fail results from those eleven months, all of it tied to two prior release cycles.
That gap was not a surprise by the time cutover happened on a Friday afternoon. The team had already run a sample export three weeks earlier, on a suite of 90 cases, and seen the same gap for themselves. Nobody was blindsided in the final week, because the sample had already told them what to expect, and the project manager had already budgeted an extra day for the archive step.
The decision most teams end up making
Stated without judgement, because it is a reasonable choice and not a failure. Most teams carry the cases forward into the new system.
They archive the old TestLink instance in a read only state to preserve the history. They write down exactly where that archive lives and who has access to it.
That is a smaller, calmer decision than trying to force eleven months of execution records into a format that was never built to hold them. It also tends to be the honest answer once a team has actually looked at what the export contains, rather than what they assumed it contained going in.
A team weighing TestLink against a different open source option, such as Kiwi TCMS, will find the export gap looks similar from that side too, since neither tool was built primarily as a data interchange format. That is worth knowing before assuming a different tool solves the history problem automatically.
What to keep after cutover, and for how long
Someone will eventually ask about a result from before the move. Plan for that question now rather than when it arrives, months after everyone has stopped thinking about the old system.
Keep the old TestLink install accessible, even if only in a read only mode. Match the retention period to your longest audit or support cycle, often a year or more depending on the industry.
Write down the URL, the login process, and who owns it, somewhere the team that inherits the question can actually find it later. A read only archive that nobody can locate is functionally the same as no archive at all, and it defeats the entire point of keeping it around in the first place.
Common mistakes worth naming
A few patterns show up again and again in these projects, and naming them ahead of time is cheaper than learning them the hard way:
- Promising a cutover date before running any export at all
- Treating a successful case count as proof the migration is complete
- Assuming every custom field behaves the same way as the simplest one tested
- Deleting the old instance immediately after cutover instead of archiving it read only
- Forgetting to write down who owns the archived instance once the original owner moves teams
Each of those mistakes traces back to skipping the inventory step this post opened with. The fix is the same every time: look at the actual export before promising anything about it, and write down what you find so the next person does not have to relearn it.
Questions people ask
Does TestLink's export include execution history at all?
Almost none. The XML export was built for case structure, not for the run log, so pass and fail history from past executions is largely left behind.
Is TestLink actually still maintained?
Yes. As of 25 August 2026, version 1.9.20 is the last of the 1.9.x line, a 2.x line is in development, and the maintainer posted progress in December 2025.
What should we do if we need the old execution history for an audit?
Keep the original TestLink instance running in a read only mode rather than trying to migrate the history itself, and document where it lives.
How big should our export sample be before a full migration?
Pick the suite that stresses the format the most, meaning the one with the most custom fields, attachments, or requirement links, not just the largest one.
How long should we keep the old instance around after cutover?
Long enough to cover your typical audit or support window, often a year or more, and written down somewhere the whole team can find.
Try Tesbo, or get the next useful idea
Start building your testing workflow now, or get one practical email a month.
Start freeOne email a month
What we shipped, what we learned, and the occasional infographic worth pinning. Unsubscribe in one click.


