LVV - LVGL Test Automation Tool

Please let me present this project which aims to create an advanced test automation tool for LVGL. I consider the main use case for it is in production environments, but other users may find it useful.

Key Features

  • App streaming and control inside the Web UI
  • Widget tree inspection and property access
  • Flexible interactions (by object name or screen coordinates: click, type, swipe, etc.)
  • Screenshot capture with visual regression testing
  • Built-in wait and synchronization utilities
  • Assertion system for UI validation
  • Test runner with JUnit XML reporting
  • Python scripting support (PocketPy + system Python option)
  • Object mapping via JSON for easier targeting
  • Advanced selectors using multiple properties
  • Gesture helpers (long press, drag, etc.)
  • Retry-aware element search to reduce flaky tests
  • Extended assertion helpers (ranges, regex, boolean checks)
  • Web-based test recorder that generates Python scripts
  • Headless CI execution (Docker-friendly)
  • Log capture and debugging utilities
  • Performance metrics tracking
  • Visual regression ignore regions for dynamic UI areas
  • HTML test reports
  • Fail-fast execution option
  • Per-test setup scripting
  • Diagnostic tool (lvv doctor) for environment checks

Everything served from a single small executable (<10MB) which is the server that launches a WebUI (is user wants streaming and direct app control), and a spy C code that the target application needs to compile with it.

Please note that the project still under heavy test itself and may evolve, other that Desktop testing, I tested it with a real project flashed on ESP32 with communication going through serial. Any remarks about it and feature requests are welcome.

4 Likes

@boulabiar, it looks amazing, at least for now the community is excited about this project. I will take a look and give a feedback

It’s an amazing work with a lot of very useful features. Have you tested it with embedded hardware too?

It really seems like you put a lot of work into it so I wonder what is the motivation behind the project.

Thanks for your message about lvv (the v is for verify).

I have a esp32-p4 7" board, so I tested flashing a project there and using serial to connect and launch tests to evaluate a real world case.
To make it work there, I had to modify some code which is in commit 59d584d6b34119f1b67a4719f77a7a65f9c38743 , there is also some specific configuration for esp32 but can’t put these in lvv because they are specific for esp32.

I made this because I want to make LVGL ecosystem match other competing projects and let companies have more freedom choosing without costly membership fees.

In Embedded World in Nurnberg I met many companies and one of their problems is professional testing (lvv answers many but still not all yet, I’ve already talked with Jonathan about this project in front of Riverdi booth). There are also other tools requests and I will be adressing these too.
I also want to get some revenues from these projects to pay my bills ! And in the same time allow hobbyists and small projects builders to use these tools without restrictions.

Sounds great! I hope you will find customers for the project. :rocket:

1 Like

You asked me whether I’ve tested it with a device.

This is a short example of it:

https://youtube.com/shorts/HatbZrMh3vY

Sorry about the quality…

Of course I still have some problems with the webui view, the live stream from the device is very slow and must be interrupted when running a test, I started questioning whether it’s needed in this specific case. The tests are also better written by hand instead of relying on live recording from interface.

The tests starts with this part:

import lvv
import json

for i in range(5):
    home = lvv.find_by("type=label,text=Home")
    if home is not None:
        break
    lvv.click_at(68, 63)
    lvv.wait(500)

home = lvv.find_by("type=label,text=Home")
assert home is not None, "Home title not found — not on home screen"

settings_row = lvv.find_by("type=label,text=Settings")
assert settings_row is not None, "Settings button not found"
...