1
0
Fork 0

simulator: test_qa: Add some basic docstring tests

This one picked up a lot of inconsistancy so the changes here are pretty
big.

Signed-off-by: Daniel Thompson <daniel@redfelineninja.org.uk>
This commit is contained in:
Daniel Thompson 2021-01-13 21:51:17 +00:00
parent f7ef165433
commit 39d8783055
14 changed files with 126 additions and 74 deletions

View file

@ -21,8 +21,7 @@ treated as examples they are described in detail as part of the
* :py:class:`.SoftwareApp` * :py:class:`.SoftwareApp`
* :py:class:`.StepCounterApp` * :py:class:`.StepCounterApp`
* :py:class:`.StopwatchApp` * :py:class:`.StopwatchApp`
* :py:class:`.TestApp` * :py:class:`.TemplateApp`
* :py:class:`.TemplateApp``
Watch faces Watch faces
----------- -----------

View file

@ -1,9 +1,13 @@
# SPDX-License-Identifier: LGPL-3.0-or-later # SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2020 Johannes Wache # Copyright (C) 2020 Johannes Wache
"""Calculator application """Calculator
~~~~~~~~~~~~~
This is a simple calculator app that uses the build-in eval() function to This is a simple calculator app that uses the build-in eval() function to
compute the solution. compute the solution.
.. figure:: res/CalcApp.png
:width: 179
""" """
import wasp, fonts import wasp, fonts

View file

@ -5,6 +5,9 @@
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
Shows a time (as HH:MM) together with a battery meter and the date. Shows a time (as HH:MM) together with a battery meter and the date.
.. figure:: res/ClockApp.png
:width: 179
""" """
import wasp import wasp
@ -21,13 +24,7 @@ DIGITS = (
MONTH = 'JanFebMarAprMayJunJulAugSepOctNovDec' MONTH = 'JanFebMarAprMayJunJulAugSepOctNovDec'
class ClockApp(): class ClockApp():
"""Simple digital clock application. """Simple digital clock application."""
.. figure:: res/ClockApp.png
:width: 179
Screenshot of the clock application
"""
NAME = 'Clock' NAME = 'Clock'
ICON = icons.clock ICON = icons.clock

View file

@ -5,6 +5,9 @@
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
Shows a pure white screen with the backlight set to maximum. Shows a pure white screen with the backlight set to maximum.
.. figure:: res/TorchApp.png
:width: 179
""" """
import wasp import wasp
@ -12,13 +15,7 @@ import wasp
import icons import icons
class TorchApp(object): class TorchApp(object):
"""Trivial flashlight application. """Trivial flashlight application."""
.. figure:: res/TorchApp.png
:width: 179
Screenshot of the flashlight application
"""
NAME = 'Torch' NAME = 'Torch'
ICON = icons.torch ICON = icons.torch

View file

@ -6,6 +6,9 @@
These three lines poems are fun to write and fit nicely on a tiny screen. These three lines poems are fun to write and fit nicely on a tiny screen.
.. figure:: res/HaikuApp.png
:width: 179
If there is a file called haiku.txt in the flash filesystem then this app If there is a file called haiku.txt in the flash filesystem then this app
allows it to be displayed three lines at a time using the pager. allows it to be displayed three lines at a time using the pager.

View file

@ -1,18 +1,21 @@
# SPDX-License-Identifier: LGPL-3.0-or-later # SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2020 Daniel Thompson # Copyright (C) 2020 Daniel Thompson
"""Heart rate monitor
~~~~~~~~~~~~~~~~~~~~~
A graphing heart rate monitor using a PPG sensor.
.. figure:: res/HeartApp.png
:width: 179
"""
import wasp import wasp
import machine import machine
import ppg import ppg
class HeartApp(): class HeartApp():
"""Heart Rate Sensing application. """Heart rate monitor application."""
.. figure:: res/HeartApp.png
:width: 179
Screenshot of the heart rate application
"""
NAME = 'Heart' NAME = 'Heart'
def foreground(self): def foreground(self):

View file

@ -3,19 +3,16 @@
"""Application launcher """Application launcher
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
.. figure:: res/LauncherApp.png
:width: 179
""" """
import wasp import wasp
import icons import icons
class LauncherApp(): class LauncherApp():
"""An application launcher application. """An application launcher application."""
.. figure:: res/LauncherApp.png
:width: 179
Screenshot of the application launcher
"""
NAME = 'Launcher' NAME = 'Launcher'
ICON = icons.app ICON = icons.app

View file

@ -1,20 +1,30 @@
# SPDX-License-Identifier: LGPL-3.0-or-later # SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2020-21 Daniel Thompson # Copyright (C) 2020-21 Daniel Thompson
"""Settings application
~~~~~~~~~~~~~~~~~~~~~~~
Allows a very small set of user preferences (including the date and
time) to be set on the device itself.
.. figure:: res/SettingsApp.png
:width: 179
.. note::
The settings tool is not expected to comprehensively present every
user configurable preference. Some are better presented via a
companion app and some particular exotic ones are perhaps best
managed with a user-provided ``main.py``.
"""
import wasp import wasp
import fonts import fonts
import icons import icons
class SettingsApp(): class SettingsApp():
"""Ultra-simple settings application. """Settings application."""
Currently the settings application contains only one setting: brightness
.. figure:: res/SettingsApp.png
:width: 179
Screenshot of the settings application
"""
NAME = 'Settings' NAME = 'Settings'
ICON = icons.settings ICON = icons.settings

View file

@ -1,9 +1,8 @@
# SPDX-License-Identifier: LGPL-3.0-or-later # SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2020 Johannes Wache # Copyright (C) 2020 Johannes Wache
""" """Snake Game
Snake Game ~~~~~~~~~~~~~
~~~~~~~~~~
This is a classic arcade game called snake. This is a classic arcade game called snake.
@ -174,4 +173,3 @@ class Snake():
draw = wasp.watch.drawable draw = wasp.watch.drawable
draw.fill(x=self.oldtail[0],y=self.oldtail[1],w=15,h=15,bg=0x0000) draw.fill(x=self.oldtail[0],y=self.oldtail[1],w=15,h=15,bg=0x0000)
draw.fill(x=self.body[-1][0]+1,y=self.body[-1][1]+1,w=13,h=13,bg=0xffff) draw.fill(x=self.body[-1][0]+1,y=self.body[-1][1]+1,w=13,h=13,bg=0xffff)

View file

@ -1,6 +1,18 @@
# SPDX-License-Identifier: LGPL-3.0-or-later # SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2020 Daniel Thompson # Copyright (C) 2020 Daniel Thompson
"""Wizard to generate main.py.""" """Software
~~~~~~~~~~~
A tool to enable/disable applications.
.. figure:: res/SoftwareApp.png
:width: 179
Most applications are disabled by default at boot in order to conserve
RAM (which is in short supply and very useful to anyone wanting to
write an application). This tools allows us to boot and conserve RAM
whilst still allowing users to activate so many awesome applications!
"""
import wasp import wasp
import icons import icons

View file

@ -1,6 +1,17 @@
# SPDX-License-Identifier: LGPL-3.0-or-later # SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2020 Daniel Thompson # Copyright (C) 2020 Daniel Thompson
"""Step counter
~~~~~~~~~~~~~~~
Provide a daily step count.
.. figure:: res/StepsApp.png
:width: 179
The step counts automatically reset at midnight.
"""
import wasp import wasp
import fonts import fonts
@ -30,13 +41,7 @@ feet = (
) )
class StepCounterApp(): class StepCounterApp():
"""Step counter application. """Step counter application."""
.. figure:: res/StepsApp.png
:width: 179
Screenshot of the step counter application
"""
NAME = 'Steps' NAME = 'Steps'
ICON = icons.app ICON = icons.app

View file

@ -1,19 +1,22 @@
# SPDX-License-Identifier: LGPL-3.0-or-later # SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2020 Daniel Thompson # Copyright (C) 2020 Daniel Thompson
"""Stopwatch
~~~~~~~~~~~~
Simple stop/start watch with support for split times.
.. figure:: res/StopclockApp.png
:width: 179
"""
import wasp import wasp
import icons import icons
import fonts import fonts
class StopwatchApp(): class StopwatchApp():
"""Stopwatch application. """Stopwatch application."""
.. figure:: res/StopclockApp.png
:width: 179
Screenshot of the stopwatch application
"""
# Stopwatch requires too many pixels to fit into the launcher # Stopwatch requires too many pixels to fit into the launcher
NAME = 'Stopclock' NAME = 'Stopclock'
ICON = icons.app ICON = icons.app

View file

@ -3,6 +3,12 @@
"""Self Tests """Self Tests
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
A collection of tests used to develop features or provide useful metrics such
as performance indicators or memory usage.
.. figure:: res/SelfTestApp.png
:width: 179
""" """
import wasp import wasp
@ -15,13 +21,7 @@ import machine
from apps.pager import PagerApp from apps.pager import PagerApp
class TestApp(): class TestApp():
"""Simple test application. """Self test application."""
.. figure:: res/SelfTestApp.png
:width: 179
Screenshot of the self test application
"""
NAME = 'Self Test' NAME = 'Self Test'
ICON = icons.app ICON = icons.app

View file

@ -1,25 +1,25 @@
import pytest import pytest
import wasp import wasp
import importlib
import os import os
EXCLUDE = ('Notifications', 'Template', 'Demo') EXCLUDE = ('Notifications', 'Template', 'Demo')
def test_screenshot(constructor):
if constructor.NAME in EXCLUDE:
return
fname = f'res/{constructor.NAME}App.png'.replace(' ', '')
assert os.path.exists(fname)
def test_screenshot_README(constructor): def test_screenshot_README(constructor):
if constructor.NAME in EXCLUDE: if constructor.NAME in EXCLUDE:
return return
fname = f'res/{constructor.NAME}App.png'.replace(' ', '') fname = f'res/{constructor.NAME}App.png'.replace(' ', '')
# A screenshot must exist for every application (press 's' in the
# simulator)
assert os.path.exists(fname)
# Every screenshot must be included in the README image gallery
with open('README.rst') as f: with open('README.rst') as f:
readme = f.read() readme = f.read()
assert fname in readme assert fname in readme
def test_apps_documented(constructor): def test_app_library(constructor):
if constructor.NAME in EXCLUDE: if constructor.NAME in EXCLUDE:
return return
@ -28,8 +28,32 @@ def test_apps_documented(constructor):
with open('docs/wasp.rst') as f: with open('docs/wasp.rst') as f:
waspdoc = f.read() waspdoc = f.read()
# Every application must be listed in either the
# Application Library or the Reference manual
needle = f'.. automodule:: {constructor.__module__}' needle = f'.. automodule:: {constructor.__module__}'
assert needle in appdoc or needle in waspdoc assert needle in appdoc or needle in waspdoc
# If an application is listed in the Reference manual
# then we need to make sure there is long to it from the
# Application Library
if needle in waspdoc: if needle in waspdoc:
assert constructor.__name__ in appdoc assert constructor.__name__ in appdoc
def test_docstrings(constructor):
if constructor.NAME in EXCLUDE:
return
fname = f'res/{constructor.NAME}App.png'.replace(' ', '')
class_doc = constructor.__doc__
module_doc = importlib.import_module(constructor.__module__).__doc__
# Screenshots should *not* appear in the constructor.
if constructor.__doc__:
assert fname not in constructor.__doc__
# Screenshots should appear in the full module documentation
assert f'.. figure:: {fname }' in module_doc
# The second line of the module documentation should be an
# underline (e.g. the first line must be a section header)
assert(module_doc.split('\n')[1].startswith('~~~~'))