Skip to content

Development and Testing

U3knOwn edited this page Oct 3, 2026 · 11 revisions

Development and Testing

How to work on TinyPPI: get the code onto a box, run the tests, regenerate generated files, and prepare a release. For the code structure see Architecture.


Getting the code

git clone https://github.com/CE-Repo/script.tinyppi.git
cd script.tinyppi

Requirements on the development machine: Python 3.10 or later (the code uses X | Y type unions) and pytest for the unit tests.


Trying a change on a CoreELEC box

  1. Copy the add-on folder to the box, replacing the installed copy:

    rsync -av --delete --exclude .git --exclude tests --exclude tools \
          ./ root@coreelec:/storage/.kodi/addons/script.tinyppi/
  2. Restart Kodi (systemctl restart kodi) — the service and its cached modules only reload with a new interpreter. Script-only changes take effect on the next launch, but anything running in the service (overlay, splash, dashboard) needs the restart.

  3. Watch the log:

    tail -f /storage/.kodi/temp/kodi.log | grep TinyPPI

Useful switches while developing:

Switch Where Effect
FORCE_DEBUG = True resources/lib/core/log.py Writes TinyPPI's debug lines at INFO level, without enabling Kodi's debug log.
_ALLOW_NON_COREELEC = True resources/lib/ui/overlay.py Lets the overlay open on a non-CoreELEC Kodi (desktop testing). Never commit it.

Unit tests

The add-on's code runs outside Kodi: tests/stubs stands in for xbmc, xbmcgui, xbmcaddon and xbmcvfs.

python3 -m pip install pytest
python3 -m pytest tests
File Covers
unit/test_library.py The dashboard's library cache: one query for concurrent readers, no stale list after a drop, a scan's burst of notifications as one drop, the drops after playback stops, episodes, the continue row, marking
unit/test_vs10_switcher.py VS10 switches from the dashboard: the last tap wins, a failed switch does not stop the next, the modes offered per source
unit/test_server.py The HTTP server: fixed routes, security headers, the token for writing and for untrusted host names, the guessing lockout, connection caps, tokens and ports
unit/test_access.py Which host names count as the home network; the lockout table
unit/test_delta.py Delta frames of the event stream, applied as js/core.js applies them
unit/test_artwork.py Artwork sources (Kodi's texture cache first) and types (from the bytes)
unit/test_settings_definition.py resources/settings.xml against the five languages, the code and the skin: texts, defaults, dependencies, action buttons, color defaults and their translated names, opacity sliders, every setting read, every color property used
unit/test_settings_logic.py Settings that only act with Dolby Vision or on Amlogic hardware, checked on their code paths; every color setting reaching its skin property; the color picker (HEX tile first, then the palette; color names numbered per family; every family light to dark, its neighbours alike in saturation; every tile distinct; older stored colors keep their color)
unit/test_modules.py Every module imports; the small state holders behave

The conftest.py fixture resets the stubs' settings, properties, InfoLabels, conditions, log and JSON-RPC handler before every test.


The Kodi 22 suite

tests/kodi runs TinyPPI in a real Kodi 22 under Xvfb and checks it from outside — over JSON-RPC, over the dashboard's HTTP API, through a small helper add-on inside Kodi (settings, Home-window properties), and on screenshots.

Run Covers
run_scan.py A library scan with an open films tab ends in about one re-read (with BASELINE_REF, compared with the same run on older code)
run_functional.py Service, dashboard API and headers, access control, playback from the dashboard, the overlay (launch, toggle, handover), the VS10 dialog, codec logos, the remote (pause, seek, tracks, subtitles, chapters, volume), VS10 switching, watched / unwatched / resume, connection caps, the guessing lockout, the settings dialogs, the page in Chromium, a clean shutdown
run_settings.py Every setting with an effect on a desktop Kodi, set live and measured: all colors and opacities, overlay, VS10 dialog, channel graphic, codec logos in all three modes, dashboard
run_settings_dialog.py Every category of the settings dialog opens without errors

What it needs

  • Kodi 22 for X11. Ubuntu 24.04 has no package; build_kodi.sh builds it from source into /opt/kodi (as root, about an hour).
  • Xvfb, ImageMagick, ffmpeg with libx264 and libx265 (installed by build_kodi.sh).
  • Python 3 with Pillow.
  • Optional: Node.js with the playwright package for the browser check (skipped without it).
  • An /etc/coreelec folder: the overlay and the VS10 dialog open on CoreELEC only, and this makes a desktop Kodi pass. Use a throwaway machine or container.

Running it

sudo tests/kodi/build_kodi.sh        # once
sudo mkdir -p /etc/coreelec          # once, on a test machine only
tests/kodi/run_all.sh

run_all.sh makes the test media and a Kodi profile template (once), then runs every suite on fresh profiles and exits non-zero on a failure. Runs can also be started on their own, e.g. python3 tests/kodi/run_settings.py splash.

Variable Default Purpose
KODI_TEST_ROOT /opt/kodi-test Media, profiles, screenshots, results (results/*.json)
KODI_BIN /opt/kodi/bin/kodi The Kodi to test
KODI_TEST_DISPLAY :99 The Xvfb display
BASELINE_REF (none) A git ref to compare the scan run against, e.g. main
PYTHON python3 The Python run_all.sh uses (needs Pillow)

Kodi's web server is switched on in the test profiles (port 8080, user kodi, password kodi) and the dashboard runs on 8099; keep both ports free.

What only a CoreELEC box can test

  • the Amlogic driver (the VS10 sysfs writes fail on a desktop and are reported apart as expected),
  • Dolby Vision side data (stock Kodi does not publish it, and script.module.sidedata parses on aarch64 only),
  • the output format the codec logos show.

Generated files

The Bar and Single button VS10 dialog layouts are generated from the shared description in resources/lib/ui/dialog_layout.py; the Dialog layout is maintained by hand.

python3 tools/gen_dialog_skins.py   # writes script-tinyppi-dialog-bar.xml and -single.xml
python3 tools/gen_dialog_media.py   # draws media/dialog/arrow-left.png and arrow-right.png

Run them from the repository root after changing dialog_layout.py, and commit the results.


Conventions

  • Every source file starts with an SPDX header:
    # SPDX-License-Identifier: AGPL-3.0-or-later
    # Copyright (c) 2026 U3knOwn
  • Module and function docstrings explain why, not just what; comments are plain English sentences.
  • Never let an exception escape into Kodi from the service: log it with the module's channel() logger and carry on.
  • No thread may outlive the service script, and no wait may be unbounded (Kodi waits for every thread at shutdown).
  • Write window properties only when the value changed (set_changed_properties), and read InfoLabels inside a read_pass.
  • New user-visible text goes into all five strings.po files, with the next free ID in the block of its area (see Translations); test_settings_definition.py enforces it for settings.
  • New settings need a label, a help text, a default and, for colors, an opacity slider; the definition test checks this.

Releasing

  1. Bump version in addon.xml.
  2. Replace the <news> entry in addon.xml — it holds the latest version only.
  3. Run the unit tests (and ideally the Kodi 22 suite).
  4. Commit as "Bump version to x.y.z", tag, and publish the ZIP to the repository.

Contributing

Issues and pull requests are welcome at https://github.com/CE-Repo/script.tinyppi. Please include tests for logic changes, keep pull requests focused, and describe how you verified the change (unit tests, Kodi 22 suite, or on which CoreELEC box).

Clone this wiki locally