Skip to content

Commit

Permalink
feat(tests): Add tests for MicroPython test suite.
Browse files Browse the repository at this point in the history
  • Loading branch information
Carglglz committed Jul 28, 2024
1 parent 6fae7e7 commit e06953e
Show file tree
Hide file tree
Showing 25 changed files with 1,119 additions and 2 deletions.
2 changes: 1 addition & 1 deletion lvgl
Submodule lvgl updated 1 files
+0 −7 src/lv_init.c
3 changes: 2 additions & 1 deletion micropython.mk
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# LVGL unix optional libraries
# Update CFLAGS_EXTMOD and LDFLAGS_EXTMOD for LVGL extenral library,
# but do that only on the unix port, for unix specific dependencies

ifeq ($(notdir $(CURDIR)),unix)
ifneq ($(UNAME_S),Darwin)
CFLAGS_EXTMOD += -DMICROPY_FB=1
endif
Expand Down Expand Up @@ -36,6 +36,7 @@ ifneq ($(FFMPEG_LDFLAGS_EXTMOD),)
CFLAGS_EXTMOD += $(FFMPEG_CFLAGS_EXTMOD) -DMICROPY_FFMPEG=1
LDFLAGS_EXTMOD += $(FFMPEG_LDFLAGS_EXTMOD)
endif
endif

################################################################################

Expand Down
1 change: 1 addition & 0 deletions ports/stm32/manifest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module("lv_utils.py", base_path="../../lib")
46 changes: 46 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

### Tests:

- `api/`: These tests are to test MicroPython-LVGL bindings. They can be
automated/included in CI.
To run from `micropython/tests`:
```
./run-tests.py ../../user_modules/lv_binding_micropython/tests/api/basic*.py -r .
```

- `display/`: These are to test the `api` + display driver. Intended for HIL
(Hardware in the loop) testing. Display only, no touch interface, touch is
automated and simulated in software.
To run from `micropython/tests`:
```
./run-tests.py ../../user_modules/lv_binding_micropython/tests/display/basic*.py -r .
```
e.g. in unix port a display will appear to provide visual feedback.


- `indev/`: These are to test the `display` + indev (touch) driver. Intended for
interactive HIL testing, e.g. they expect user input to complete the test.

To run from `micropython/tests`:
```
./run-tests.py ../../user_modules/lv_binding_micropython/tests/indev/basic*.py -r .
```
e.g. in unix port a display will appear to allow user input.

All tests are intended/expected to be run both in desktop (unix port) and in devices with the same result.

For devices `testrunner.py`, `testdisplay.py` and `display_mode.py` need to be
uploaded. Also for display/indev testing a `hwdisplay.py` with a display driver
called `display` is expected. This `display` driver is expected to have at least a
```py

def blit(self, x1, y1, w, h, buff):
```
method or handle the lv display setup by itself (e.g setting buffers, `flush_cb`, etc)

For interactive indev tests, it is required to have a
```py

def read_cb(self, indev, data):
```
method too, or handle indev creation by itself.
60 changes: 60 additions & 0 deletions tests/api/basic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import lvgl as lv
import sys
import asyncio
import os

sys.path.append("..")
sys.path.append(os.getcwd())
import testrunner

# This is a basic test to test buttons, labels,
# RGB colors, layout aligment and events.


async def demo(scr, display=None):
def get_button(scr, text, align, color):
_btn = lv.button(scr)
_btn.set_size(lv.pct(25), lv.pct(10))
_lab = lv.label(_btn)
_lab.set_text(text)
_lab.center()
_btn.set_style_align(align, 0)
_btn.set_style_bg_color(lv.color_make(*color), 0)
return _btn, text

buttons = [
("RED", lv.ALIGN.TOP_MID, (255, 0, 0)),
("GREEN", lv.ALIGN.BOTTOM_MID, (0, 255, 0)),
("BLUE", lv.ALIGN.CENTER, (0, 0, 255)),
]

def button_cb(event, name):
print(f"{name} PRESSED")

_all_btns = [get_button(scr, *btn) for btn in buttons]

for btn, name in _all_btns:
btn.add_event_cb(
lambda event, button_name=name: button_cb(event, button_name),
lv.EVENT.CLICKED,
None,
)

await asyncio.sleep_ms(500) # await so the frame can be rendered
print("EVENT TEST:")
for _btn, name in _all_btns:
_btn.send_event(lv.EVENT.CLICKED, None)
await asyncio.sleep_ms(200)

return _all_btns


__file__ = globals().get("__file__", "test")

try:
from display_mode import MODE as _mode
except Exception:
_mode = None

testrunner.run(demo, __file__, mode=_mode)
testrunner.devicereset()
34 changes: 34 additions & 0 deletions tests/api/basic.py.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

FRAME: 0 (0, 0, 240, 32, 23040)
d5c5d09cff879bb12cb926dc44bf10161cded58d2057806e7cbde536540b1421

FRAME: 1 (0, 32, 240, 32, 23040)
f281e1fce42dc013342ad8a4573d74874238d995e6dff46dc29a1d68b780f920

FRAME: 2 (0, 64, 240, 32, 23040)
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694

FRAME: 3 (0, 96, 240, 32, 23040)
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694

FRAME: 4 (0, 128, 240, 32, 23040)
424125778438a53da017c2dca09964ec2cec5ad4e2689038dd0e830125112fd8

FRAME: 5 (0, 160, 240, 32, 23040)
9abb7f9219bb7ccc8784119c784b1bf41c451f9957989fd2a9fc12a15606b1d0

FRAME: 6 (0, 192, 240, 32, 23040)
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694

FRAME: 7 (0, 224, 240, 32, 23040)
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694

FRAME: 8 (0, 256, 240, 32, 23040)
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694

FRAME: 9 (0, 288, 240, 32, 23040)
f546d8ae7340f5fb71e30358ef0d6f33a4f2d72946d9b312444b07fa9d659396
EVENT TEST:
RED PRESSED
GREEN PRESSED
BLUE PRESSED
77 changes: 77 additions & 0 deletions tests/api/basic_indev.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import lvgl as lv
import sys
import asyncio
import os

sys.path.append("..")
sys.path.append(os.getcwd())
import testrunner

# This is a basic test to test buttons, labels,
# RGB colors, layout aligment and events.


async def demo(scr, display=None):
def get_button(scr, text, align, color):
_btn = lv.button(scr)
_btn.set_size(lv.pct(25), lv.pct(10))
_lab = lv.label(_btn)
_lab.set_text(text)
_lab.center()
_btn.set_style_align(align, 0)
_btn.set_style_bg_color(lv.color_make(*color), 0)
return _btn, text

buttons = [
("RED", lv.ALIGN.TOP_MID, (255, 0, 0)),
("GREEN", lv.ALIGN.BOTTOM_MID, (0, 255, 0)),
("BLUE", lv.ALIGN.CENTER, (0, 0, 255)),
]

def button_cb(event, name):
print(f"{name} PRESSED")

_all_btns = [get_button(scr, *btn) for btn in buttons]

for btn, name in _all_btns:
btn.add_event_cb(
lambda event, button_name=name: button_cb(event, button_name),
lv.EVENT.CLICKED,
None,
)

await asyncio.sleep_ms(500) # await so the frame can be rendered
print("EVENT TEST:")
for _btn, name in _all_btns:
_btn.send_event(lv.EVENT.CLICKED, None)
await asyncio.sleep_ms(200)

# simulate touch events
if display:
print("INDEV TEST:")
await display.touch(100, 100)

await asyncio.sleep_ms(500)

print("INDEV + BUTTONS TEST:")
# display.debug_indev(press=False, release=False)
display.debug_display(False)
for _btn, name in _all_btns:
pos = _btn.get_x(), _btn.get_y()
await display.touch(*pos)
await asyncio.sleep_ms(1000)

await asyncio.sleep_ms(500)

return _all_btns


__file__ = globals().get("__file__", "test")

try:
from display_mode import MODE as _mode
except Exception:
_mode = None

testrunner.run(demo, __file__, mode=_mode)
testrunner.devicereset()
47 changes: 47 additions & 0 deletions tests/api/basic_indev.py.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@

FRAME: 0 (0, 0, 240, 32, 23040)
d5c5d09cff879bb12cb926dc44bf10161cded58d2057806e7cbde536540b1421

FRAME: 1 (0, 32, 240, 32, 23040)
f281e1fce42dc013342ad8a4573d74874238d995e6dff46dc29a1d68b780f920

FRAME: 2 (0, 64, 240, 32, 23040)
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694

FRAME: 3 (0, 96, 240, 32, 23040)
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694

FRAME: 4 (0, 128, 240, 32, 23040)
424125778438a53da017c2dca09964ec2cec5ad4e2689038dd0e830125112fd8

FRAME: 5 (0, 160, 240, 32, 23040)
9abb7f9219bb7ccc8784119c784b1bf41c451f9957989fd2a9fc12a15606b1d0

FRAME: 6 (0, 192, 240, 32, 23040)
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694

FRAME: 7 (0, 224, 240, 32, 23040)
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694

FRAME: 8 (0, 256, 240, 32, 23040)
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694

FRAME: 9 (0, 288, 240, 32, 23040)
f546d8ae7340f5fb71e30358ef0d6f33a4f2d72946d9b312444b07fa9d659396
EVENT TEST:
RED PRESSED
GREEN PRESSED
BLUE PRESSED
INDEV TEST:
[PRESSED]: (100,100)
[RELEASED]: (100,100)
INDEV + BUTTONS TEST:
[PRESSED]: (90,0)
RED PRESSED
[RELEASED]: (90,0)
[PRESSED]: (90,288)
GREEN PRESSED
[RELEASED]: (90,288)
[PRESSED]: (90,144)
BLUE PRESSED
[RELEASED]: (90,144)
77 changes: 77 additions & 0 deletions tests/api/basic_slider.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import lvgl as lv
import sys
import asyncio
import os

sys.path.append("..")
sys.path.append(os.getcwd())
import testrunner # noqa

# This is a basic test to test buttons, labels,
# RGB colors, layout aligment and events.


async def demo(scr, display=None):
def get_button(scr, text, align, color):
scr.set_style_pad_all(10, 0)
_btn = lv.slider(scr)
_btn.set_width(lv.pct(75))
_btn.set_height(lv.pct(10))
_lab = lv.label(_btn)
_lab.set_text(text)
_lab.set_style_text_color(lv.color_white(), 0)
_lab.center()
_btn.set_style_align(align, 0)
_btn.set_style_bg_color(lv.color_make(*color), lv.PART.INDICATOR)
_btn.set_style_bg_color(lv.color_make(*color), lv.PART.MAIN)
_btn.set_style_bg_color(lv.color_make(*color), lv.PART.KNOB)
return _btn, text

buttons = [
("RED", lv.ALIGN.TOP_MID, (255, 0, 0)),
("GREEN", lv.ALIGN.BOTTOM_MID, (0, 255, 0)),
("BLUE", lv.ALIGN.CENTER, (0, 0, 255)),
]

def button_cb(event, name, slider):
if slider.get_value() == 100:
print(f"{name} VALUE: {slider.get_value()}")

_all_btns = [get_button(scr, *btn) for btn in buttons]

for btn, name in _all_btns:
btn.add_event_cb(
lambda event, button_name=name, slider=btn: button_cb(
event, button_name, slider
),
lv.EVENT.VALUE_CHANGED,
None,
)

await asyncio.sleep_ms(500) # await so the frame can be rendered
# simulate touch events
if display:
print("INDEV + SLIDER TEST:")
display.debug_indev(press=False)
display.debug_display(False)
for _btn, name in _all_btns:
pos = _btn.get_x(), _btn.get_y()
pos2 = _btn.get_x2(), _btn.get_y2()
x1, y1 = pos
x2, y2 = pos2
y_mid = y2 - ((y2 - y1) // 2)
await display.swipe(x1 + 5, y_mid, x2 + (y2 - y1), y_mid, ms=500)
await asyncio.sleep_ms(100)

return _all_btns


__file__ = globals().get("__file__", "test")

try:
from display_mode import MODE as _mode
except Exception:
_mode = None

testrunner.run(demo, __file__, mode=_mode)
testrunner.devicereset()
Loading

0 comments on commit e06953e

Please sign in to comment.