Self-hosted service
kiwitcms/Kiwi avatar
kiwitcms/Kiwi

Kiwi TCMS: a Django test case manager with an API and containers

open source test management system with over 2 million downloads!

1,281 stars366 forksPythonGPL-2.0

At a glance

What is it?
Kiwi TCMS is an open source test management system built on Django, covering manual and automated testing with bug tracker integration, access control and an API layer. It suits QA teams that want to leave TestLink and Testopia behind without giving up a hosted demo, and it is a full server application rather than a plugin.
Who is it for?
Adopt Kiwi TCMS when a team needs a shared place for test cases, plans, runs and results with an API in front of it, since the project covers manual and automated testing, ships a documented API layer and publishes a multi database Docker Compose setup you can run without touching a source install.
Can I use it commercially?
Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the project covers and what it leaves out

Kiwi TCMS describes itself as the leading open source test management system for both manual and automated testing, and the feature list is specific: bug tracker integration, search pages, powerful access control, test automation framework plugins, visual reports and a rich API layer.

Read that list as a scope statement rather than a marketing line. Test cases, plans, runs, results and product components are the core entities, and the automation plugins attach results from test frameworks into those same structures rather than running a separate system. Access control and search pages point to a multi user tool with real data volumes, not a personal checklist. The API layer is what makes it usable from a pipeline or a bug tracker rather than only from a browser.

The project was created by Red Hat in February 2009 under the name Nitrate, and the history section in the README is unusually detailed about how it changed hands and shape. The source was published on GitHub in November 2014 without previous history, upstream went unresponsive in 2017, and a fork by Mr. Senko produced the first release that removed hard-coded bug tracker specifications and made external integration possible. The project was renamed Kiwi TCMS in September 2017, the same time it moved to Python 3.5 and began migrating to a modern interface using Patternfly.

The Docker Compose deployment is the documented install path

The installation section of the README is short, and it points at one document: running Kiwi TCMS as a Docker container, in the Read the Docs installation guide. The repository contains the artefacts that make that route work, including a Dockerfile, docker-compose.yml, docker-compose.postgres, docker-compose.with-secrets, a helm/ directory and an httpd-foreground script.

The compose file shows the intended shape of a deployment. A database service runs mariadb:latest with utf8mb4 and utf8mb4_unicode_ci character settings and a named volume for the data. The web service runs the published image pub.kiwitcms.eu/kiwitcms/kiwi:latest, publishes ports 80 to 8080 and 443 to 8443, mounts a named uploads volume at /Kiwi/uploads, and receives its database settings through the KIWI_DB_HOST, KIWI_DB_PORT, KIWI_DB_NAME, KIWI_DB_USER and KIWI_DB_PASSWORD environment variables.

Two details are worth copying rather than ignoring. The web service sets cap_drop to ALL, dropping every Linux capability, which is a cheap and effective hardening step for a container with a web server in front of it. And the compose file also defines a third service, an nginx reverse proxy, which the comments mark as used only for testing purposes and not needed for an actual deployment.

One warning applies to that file. The database password in the sample compose file is a placeholder, not a secret, and the same is true of the root password. Anyone deploying from it has to replace both before the stack is exposed to a network.

One image, four database engines, and a check target

The Makefile is where the engineering discipline shows. There is a test target that compiles the translation messages first, then runs the Django test suite under coverage, and a loop that runs the whole matrix when the database variable is set to all:

bash
	./manage.py compilemessages

The switch at the top of the file selects the Django settings module, defaulting to tcms.settings.test and switching to the mariadb or postgresql variants when TEST_DB is MySQL, MariaDB or Postgres. The matrix named in the loop is SQLite, MySQL, Postgres and MariaDB. A test management system that stores runs, results and attachments has to behave identically across those, and the project tests all four on request.

The quality target combines the linter and the tests:

bash
check: flake8 test

which runs flake8 over the tcms package, the top level Python files, the kiwi_lint directory and the tcms_settings_dir, followed by the test target. There is also a separate pylint target that loads the Django plugin checkers, including the migrations checker, and relaxes three specific warnings, missing-docstring, duplicate-code and new-db-field-with-default, while keeping the rest of the rules in force. A dedicated target checks for missing migrations by running makemigrations in check mode.

The linting setup is unusual in another way. A kiwi_lint/ directory at the top level holds the project's own custom lint plugin, so project specific rules travel with the code rather than living in a wiki page. The .pre-commit-config.yaml at the top level ties the same checks into the commit workflow.

The container build compiles a static bundle before packaging

The Dockerfile is a multi-stage build with a CentOS Stream 10 base, and it carries a few decisions that tell you about the runtime. The runtime stage installs python3.12, the MariaDB connector, libpq, nginx-core, sscg, tar and a glibc language pack, then updates and cleans the package cache. The build stage adds the development counterparts, including gcc, rust, cargo, nodejs24-npm and gettext, and symlinks npm-24 and node-24 into place.

The frontend bundle is compiled explicitly rather than being collected as a static file:

code
RUN pushd tcms/ && npm install --include=dev && ./node_modules/.bin/webpack && popd

The package is then installed from a built tarball rather than from the source tree, with a check script run first:

code
RUN ./tests/check-build && \
    pip3 install --no-cache-dir dist/kiwitcms-*.tar.gz

That is a deliberate pattern. Building the tarball, running a check against it and installing the artefact is what makes the container image match what a package install produces, instead of running from a mutable source directory. A separate scratch stage packages the distribution files on their own.

The final image sets the locale explicitly, exposes 8080 and 8443, copies the httpd-foreground script as the command, and defines a healthcheck that curls the login page over HTTPS with a Referer header:

code
HEALTHCHECK CMD curl --fail -k -H "Referer: healthcheck" https://127.0.0.1:8443/accounts/login/

A container that reports its own health through the login endpoint is the kind of detail that matters in an orchestrated deployment.

Packaging for pip installs, with a custom lint package

The setup.py is a small piece of engineering that reveals how the project is distributed beyond the container. It reads two requirement files, requirements/tarballs.txt and requirements/base.txt, through a helper that skips the -r include lines and separates plain requirements from links, the latter marked with a #egg= fragment. The two lists are concatenated into install_requires and dependency_links, which is how older packages that are not on PyPI get pulled in.

The package itself is named kiwitcms on PyPI, the version comes from tcms.__version__ rather than being written twice, and the long description is read from README.rst so the PyPI page and the repository cannot drift apart. Packages are found with find_namespace_packages, excluding docs, kiwi_lint, tests and the test settings module, and the distribution is marked zip_safe=False with include_package_data=True.

The classifiers include Programming Language :: Python :: 3.9 and the project declares a Tidelift badge, so the maintainers take subscriptions for dependency maintenance. The presence of a Tidelift subscription and an Open Collective sponsor link at the top of the README means the funding model is a mix of sponsors, donations of five euros or more, and commercial support, and the support section says commercial support is available with more information on kiwitcms.org.

On the licence, the repository carries a LICENSE file and the project identifies as GPL-2.0. The distinction that matters in practice is between running the system and distributing a modified version of it, and this article does not give legal advice on that boundary.

Translations, a public tenant, and a project that outgrew its original sponsor

Two features of the project are easy to underestimate. The first is localisation. The README links a Crowdin project as the place where supported languages are managed, a GitHub issue template for requesting a new language, and a translation guide in the contribution documentation. A test management system used by distributed teams has to speak the testers' languages, and Crowdin plus gettext in the build is a real localisation pipeline rather than a promise.

The second is the public instance. The README points at https://public.tenant.kiwitcms.org as a place to check it out, and there is a matching open source hosting offer with a GitHub Marketplace listing that the project reached in May 2019 and, by March 2021, as a Verified Publisher. The OpenAwards entry and the Mozilla Open Source Award both refer to the same project, which is an unusual level of external recognition for a tool that began as a Red Hat internal project.

The project also reports its own distribution scale through Docker Hub pull counts, which the README tracks as a timeline: 100K pulls in May 2020, 1M in July 2021 and 2M in November 2023. The project description also mentions over two million downloads. These are counts of container pulls rather than installed systems, so they indicate reach rather than a user base, but they do explain why the Docker path is the one that is documented in detail.

The changelog lives in CHANGELOG.rst, the releases are frequent, v16.4 on 2026-09-07, v16.5 on 2026-09-17 and v16.6 on 2026-10-07, and the last push to the master branch was on 2026-10-19.

Editorial conclusion

Adopt Kiwi TCMS when a team needs a shared place for test cases, plans, runs and results with an API in front of it, since the project covers manual and automated testing, ships a documented API layer and publishes a multi database Docker Compose setup you can run without touching a source install. Do not adopt it as a plug-in for an existing tracker, because it is a standalone server application, and do not expect a hosted service, since the documentation points you at a Docker deployment. Before you commit, try the public tenant at public.tenant.kiwitcms.org, and read the docker-compose.yml before deploying, because the sample credentials in that file are placeholders you must replace.

Frequently asked questions

How do I install and run Kiwi TCMS?

The README points to the documentation on running Kiwi TCMS as a Docker container, and the repository ships a Dockerfile plus docker-compose.yml with a MariaDB service and a web service on ports 80 and 443. There is also a Helm directory, a compose file for PostgreSQL and one for deployments with secrets.

What databases does Kiwi TCMS support?

The Makefile switches the Django settings module based on a TEST_DB variable and names SQLite, MySQL, Postgres and MariaDB, with the all option running the test suite against each of them in turn. The sample docker-compose.yml uses mariadb:latest with utf8mb4 character settings.

Can I try Kiwi TCMS before installing it?

Yes, the README links a public tenant at https://public.tenant.kiwitcms.org, and the project is also listed on GitHub Marketplace as a Verified Publisher. Documentation is hosted on Read the Docs at kiwitcms.readthedocs.io.

Does Kiwi TCMS integrate with bug trackers and automated test frameworks?

The project lists bug tracker integration and test automation framework plugins among its features, and the history in the README notes that the first fork release removed hard-coded bug tracker specifications so external systems could be integrated. It also exposes a rich API layer.

Official sources

  1. kiwitcms/Kiwi on GitHub
  2. License: GPL-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/kiwitcms-kiwi.svg)](https://hysenlabs.com/projects/kiwitcms-kiwi)

Was this useful?