Skip to content

Commit ad783bd

Browse files
committed
feat(tests): Add tests for MicroPython test suite.
1 parent 65d882d commit ad783bd

24 files changed

+1126
-1
lines changed

micropython.mk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# LVGL unix optional libraries
44
# Update CFLAGS_EXTMOD and LDFLAGS_EXTMOD for LVGL extenral library,
55
# but do that only on the unix port, for unix specific dependencies
6-
6+
ifeq ($(notdir $(CURDIR)),unix)
77
ifneq ($(UNAME_S),Darwin)
88
CFLAGS_EXTMOD += -DMICROPY_FB=1
99
endif
@@ -36,6 +36,7 @@ ifneq ($(FFMPEG_LDFLAGS_EXTMOD),)
3636
CFLAGS_EXTMOD += $(FFMPEG_CFLAGS_EXTMOD) -DMICROPY_FFMPEG=1
3737
LDFLAGS_EXTMOD += $(FFMPEG_LDFLAGS_EXTMOD)
3838
endif
39+
endif
3940

4041
################################################################################
4142

ports/stm32/manifest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module("lv_utils.py", base_path="../../lib")

tests/README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
### Tests:
3+
4+
- `api/`: These tests are to test MicroPython-LVGL bindings. They can be
5+
automated/included in CI.
6+
To run from `micropython/tests`:
7+
```
8+
./run-tests.py ../../user_modules/lv_binding_micropython/tests/api/basic*.py -r .
9+
```
10+
11+
- `display/`: These are to test the `api` + display driver. Intended for HIL
12+
(Hardware in the loop) testing. Display only, no touch interface, touch is
13+
automated and simulated in software.
14+
To run from `micropython/tests`:
15+
```
16+
./run-tests.py ../../user_modules/lv_binding_micropython/tests/display/basic*.py -r .
17+
```
18+
e.g. in unix port a display will appear to provide visual feedback.
19+
20+
21+
- `indev/`: These are to test the `display` + indev (touch) driver. Intended for
22+
interactive HIL testing, e.g. they expect user input to complete the test.
23+
24+
To run from `micropython/tests`:
25+
```
26+
./run-tests.py ../../user_modules/lv_binding_micropython/tests/indev/basic*.py -r .
27+
```
28+
e.g. in unix port a display will appear to allow user input.
29+
30+
All tests are intended/expected to be run both in desktop (unix port) and in devices with the same result.
31+
32+
For devices `testrunner.py`, `testdisplay.py` and `display_mode.py` need to be
33+
uploaded. Also for display/indev testing a `hwdisplay.py` with a display driver
34+
called `display` is expected. This `display` driver is expected to have at least a
35+
```py
36+
37+
def blit(self, x1, y1, w, h, buff):
38+
```
39+
method or handle the lv display setup by itself (e.g setting buffers, `flush_cb`, etc)
40+
41+
For interactive indev tests, it is required to have a
42+
```py
43+
44+
def read_cb(self, indev, data):
45+
```
46+
method too, or handle indev creation by itself.

tests/api/basic.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import lvgl as lv
2+
import sys
3+
import asyncio
4+
import os
5+
6+
sys.path.append("..")
7+
sys.path.append(os.getcwd())
8+
import testrunner
9+
10+
# This is a basic test to test buttons, labels,
11+
# RGB colors, layout aligment and events.
12+
13+
14+
async def demo(scr, display=None):
15+
def get_button(scr, text, align, color):
16+
_btn = lv.button(scr)
17+
_btn.set_size(lv.pct(25), lv.pct(10))
18+
_lab = lv.label(_btn)
19+
_lab.set_text(text)
20+
_lab.center()
21+
_btn.set_style_align(align, 0)
22+
_btn.set_style_bg_color(lv.color_make(*color), 0)
23+
return _btn, text
24+
25+
buttons = [
26+
("RED", lv.ALIGN.TOP_MID, (255, 0, 0)),
27+
("GREEN", lv.ALIGN.BOTTOM_MID, (0, 255, 0)),
28+
("BLUE", lv.ALIGN.CENTER, (0, 0, 255)),
29+
]
30+
31+
def button_cb(event, name):
32+
print(f"{name} PRESSED")
33+
34+
_all_btns = [get_button(scr, *btn) for btn in buttons]
35+
36+
for btn, name in _all_btns:
37+
btn.add_event_cb(
38+
lambda event, button_name=name: button_cb(event, button_name),
39+
lv.EVENT.CLICKED,
40+
None,
41+
)
42+
43+
await asyncio.sleep_ms(500) # await so the frame can be rendered
44+
print("EVENT TEST:")
45+
for _btn, name in _all_btns:
46+
_btn.send_event(lv.EVENT.CLICKED, None)
47+
await asyncio.sleep_ms(200)
48+
49+
return _all_btns
50+
51+
52+
__file__ = globals().get("__file__", "test")
53+
54+
try:
55+
from display_mode import MODE as _mode
56+
except Exception:
57+
_mode = None
58+
59+
testrunner.run(demo, __file__, mode=_mode)
60+
testrunner.devicereset()

tests/api/basic.py.exp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
FRAME: 0 (0, 0, 240, 32, 23040)
3+
d5c5d09cff879bb12cb926dc44bf10161cded58d2057806e7cbde536540b1421
4+
5+
FRAME: 1 (0, 32, 240, 32, 23040)
6+
f281e1fce42dc013342ad8a4573d74874238d995e6dff46dc29a1d68b780f920
7+
8+
FRAME: 2 (0, 64, 240, 32, 23040)
9+
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694
10+
11+
FRAME: 3 (0, 96, 240, 32, 23040)
12+
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694
13+
14+
FRAME: 4 (0, 128, 240, 32, 23040)
15+
424125778438a53da017c2dca09964ec2cec5ad4e2689038dd0e830125112fd8
16+
17+
FRAME: 5 (0, 160, 240, 32, 23040)
18+
9abb7f9219bb7ccc8784119c784b1bf41c451f9957989fd2a9fc12a15606b1d0
19+
20+
FRAME: 6 (0, 192, 240, 32, 23040)
21+
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694
22+
23+
FRAME: 7 (0, 224, 240, 32, 23040)
24+
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694
25+
26+
FRAME: 8 (0, 256, 240, 32, 23040)
27+
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694
28+
29+
FRAME: 9 (0, 288, 240, 32, 23040)
30+
f546d8ae7340f5fb71e30358ef0d6f33a4f2d72946d9b312444b07fa9d659396
31+
EVENT TEST:
32+
RED PRESSED
33+
GREEN PRESSED
34+
BLUE PRESSED

tests/api/basic_indev.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import lvgl as lv
2+
import sys
3+
import asyncio
4+
import os
5+
6+
sys.path.append("..")
7+
sys.path.append(os.getcwd())
8+
import testrunner
9+
10+
# This is a basic test to test buttons, labels,
11+
# RGB colors, layout aligment and events.
12+
13+
14+
async def demo(scr, display=None):
15+
def get_button(scr, text, align, color):
16+
_btn = lv.button(scr)
17+
_btn.set_size(lv.pct(25), lv.pct(10))
18+
_lab = lv.label(_btn)
19+
_lab.set_text(text)
20+
_lab.center()
21+
_btn.set_style_align(align, 0)
22+
_btn.set_style_bg_color(lv.color_make(*color), 0)
23+
return _btn, text
24+
25+
buttons = [
26+
("RED", lv.ALIGN.TOP_MID, (255, 0, 0)),
27+
("GREEN", lv.ALIGN.BOTTOM_MID, (0, 255, 0)),
28+
("BLUE", lv.ALIGN.CENTER, (0, 0, 255)),
29+
]
30+
31+
def button_cb(event, name):
32+
print(f"{name} PRESSED")
33+
34+
_all_btns = [get_button(scr, *btn) for btn in buttons]
35+
36+
for btn, name in _all_btns:
37+
btn.add_event_cb(
38+
lambda event, button_name=name: button_cb(event, button_name),
39+
lv.EVENT.CLICKED,
40+
None,
41+
)
42+
43+
await asyncio.sleep_ms(500) # await so the frame can be rendered
44+
print("EVENT TEST:")
45+
for _btn, name in _all_btns:
46+
_btn.send_event(lv.EVENT.CLICKED, None)
47+
await asyncio.sleep_ms(200)
48+
49+
# simulate touch events
50+
if display:
51+
print("INDEV TEST:")
52+
await display.touch(100, 100)
53+
54+
await asyncio.sleep_ms(500)
55+
56+
print("INDEV + BUTTONS TEST:")
57+
# display.debug_indev(press=False, release=False)
58+
display.debug_display(False)
59+
for _btn, name in _all_btns:
60+
pos = _btn.get_x(), _btn.get_y()
61+
await display.touch(*pos)
62+
await asyncio.sleep_ms(1000)
63+
64+
await asyncio.sleep_ms(500)
65+
66+
return _all_btns
67+
68+
69+
__file__ = globals().get("__file__", "test")
70+
71+
try:
72+
from display_mode import MODE as _mode
73+
except Exception:
74+
_mode = None
75+
76+
testrunner.run(demo, __file__, mode=_mode)
77+
testrunner.devicereset()

tests/api/basic_indev.py.exp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
2+
FRAME: 0 (0, 0, 240, 32, 23040)
3+
d5c5d09cff879bb12cb926dc44bf10161cded58d2057806e7cbde536540b1421
4+
5+
FRAME: 1 (0, 32, 240, 32, 23040)
6+
f281e1fce42dc013342ad8a4573d74874238d995e6dff46dc29a1d68b780f920
7+
8+
FRAME: 2 (0, 64, 240, 32, 23040)
9+
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694
10+
11+
FRAME: 3 (0, 96, 240, 32, 23040)
12+
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694
13+
14+
FRAME: 4 (0, 128, 240, 32, 23040)
15+
424125778438a53da017c2dca09964ec2cec5ad4e2689038dd0e830125112fd8
16+
17+
FRAME: 5 (0, 160, 240, 32, 23040)
18+
9abb7f9219bb7ccc8784119c784b1bf41c451f9957989fd2a9fc12a15606b1d0
19+
20+
FRAME: 6 (0, 192, 240, 32, 23040)
21+
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694
22+
23+
FRAME: 7 (0, 224, 240, 32, 23040)
24+
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694
25+
26+
FRAME: 8 (0, 256, 240, 32, 23040)
27+
46e2096b907947368d310929303a04005b39c4a278e3a7de2225c355b4522694
28+
29+
FRAME: 9 (0, 288, 240, 32, 23040)
30+
f546d8ae7340f5fb71e30358ef0d6f33a4f2d72946d9b312444b07fa9d659396
31+
EVENT TEST:
32+
RED PRESSED
33+
GREEN PRESSED
34+
BLUE PRESSED
35+
INDEV TEST:
36+
[PRESSED]: (100,100)
37+
[RELEASED]: (100,100)
38+
INDEV + BUTTONS TEST:
39+
[PRESSED]: (90,0)
40+
RED PRESSED
41+
[RELEASED]: (90,0)
42+
[PRESSED]: (90,288)
43+
GREEN PRESSED
44+
[RELEASED]: (90,288)
45+
[PRESSED]: (90,144)
46+
BLUE PRESSED
47+
[RELEASED]: (90,144)

tests/api/basic_slider.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import lvgl as lv
2+
import sys
3+
import asyncio
4+
import os
5+
6+
sys.path.append("..")
7+
sys.path.append(os.getcwd())
8+
import testrunner # noqa
9+
10+
# This is a basic test to test buttons, labels,
11+
# RGB colors, layout aligment and events.
12+
13+
14+
async def demo(scr, display=None):
15+
def get_button(scr, text, align, color):
16+
scr.set_style_pad_all(10, 0)
17+
_btn = lv.slider(scr)
18+
_btn.set_width(lv.pct(75))
19+
_btn.set_height(lv.pct(10))
20+
_lab = lv.label(_btn)
21+
_lab.set_text(text)
22+
_lab.set_style_text_color(lv.color_white(), 0)
23+
_lab.center()
24+
_btn.set_style_align(align, 0)
25+
_btn.set_style_bg_color(lv.color_make(*color), lv.PART.INDICATOR)
26+
_btn.set_style_bg_color(lv.color_make(*color), lv.PART.MAIN)
27+
_btn.set_style_bg_color(lv.color_make(*color), lv.PART.KNOB)
28+
return _btn, text
29+
30+
buttons = [
31+
("RED", lv.ALIGN.TOP_MID, (255, 0, 0)),
32+
("GREEN", lv.ALIGN.BOTTOM_MID, (0, 255, 0)),
33+
("BLUE", lv.ALIGN.CENTER, (0, 0, 255)),
34+
]
35+
36+
def button_cb(event, name, slider):
37+
if slider.get_value() == 100:
38+
print(f"{name} VALUE: {slider.get_value()}")
39+
40+
_all_btns = [get_button(scr, *btn) for btn in buttons]
41+
42+
for btn, name in _all_btns:
43+
btn.add_event_cb(
44+
lambda event, button_name=name, slider=btn: button_cb(
45+
event, button_name, slider
46+
),
47+
lv.EVENT.VALUE_CHANGED,
48+
None,
49+
)
50+
51+
await asyncio.sleep_ms(500) # await so the frame can be rendered
52+
# simulate touch events
53+
if display:
54+
print("INDEV + SLIDER TEST:")
55+
display.debug_indev(press=False)
56+
display.debug_display(False)
57+
for _btn, name in _all_btns:
58+
pos = _btn.get_x(), _btn.get_y()
59+
pos2 = _btn.get_x2(), _btn.get_y2()
60+
x1, y1 = pos
61+
x2, y2 = pos2
62+
y_mid = y2 - ((y2 - y1) // 2)
63+
await display.swipe(x1 + 5, y_mid, x2 + (y2 - y1), y_mid, ms=500)
64+
await asyncio.sleep_ms(100)
65+
66+
return _all_btns
67+
68+
69+
__file__ = globals().get("__file__", "test")
70+
71+
try:
72+
from display_mode import MODE as _mode
73+
except Exception:
74+
_mode = None
75+
76+
testrunner.run(demo, __file__, mode=_mode)
77+
testrunner.devicereset()

0 commit comments

Comments
 (0)