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:`.StepCounterApp`
* :py:class:`.StopwatchApp`
* :py:class:`.TestApp`
* :py:class:`.TemplateApp``
* :py:class:`.TemplateApp`
Watch faces
-----------

View file

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

View file

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

View file

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

View file

@ -1,18 +1,21 @@
# SPDX-License-Identifier: LGPL-3.0-or-later
# 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 machine
import ppg
class HeartApp():
"""Heart Rate Sensing application.
.. figure:: res/HeartApp.png
:width: 179
Screenshot of the heart rate application
"""
"""Heart rate monitor application."""
NAME = 'Heart'
def foreground(self):

View file

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

View file

@ -1,20 +1,30 @@
# SPDX-License-Identifier: LGPL-3.0-or-later
# 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 fonts
import icons
class SettingsApp():
"""Ultra-simple settings application.
Currently the settings application contains only one setting: brightness
.. figure:: res/SettingsApp.png
:width: 179
Screenshot of the settings application
"""
"""Settings application."""
NAME = 'Settings'
ICON = icons.settings

View file

@ -1,9 +1,8 @@
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2020 Johannes Wache
"""
Snake Game
~~~~~~~~~~
"""Snake Game
~~~~~~~~~~~~~
This is a classic arcade game called snake.
@ -174,4 +173,3 @@ class Snake():
draw = wasp.watch.drawable
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)

View file

@ -1,6 +1,18 @@
# SPDX-License-Identifier: LGPL-3.0-or-later
# 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 icons

View file

@ -1,6 +1,17 @@
# SPDX-License-Identifier: LGPL-3.0-or-later
# 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 fonts
@ -30,13 +41,7 @@ feet = (
)
class StepCounterApp():
"""Step counter application.
.. figure:: res/StepsApp.png
:width: 179
Screenshot of the step counter application
"""
"""Step counter application."""
NAME = 'Steps'
ICON = icons.app

View file

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

View file

@ -3,6 +3,12 @@
"""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
@ -15,13 +21,7 @@ import machine
from apps.pager import PagerApp
class TestApp():
"""Simple test application.
.. figure:: res/SelfTestApp.png
:width: 179
Screenshot of the self test application
"""
"""Self test application."""
NAME = 'Self Test'
ICON = icons.app

View file

@ -1,25 +1,25 @@
import pytest
import wasp
import importlib
import os
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):
if constructor.NAME in EXCLUDE:
return
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:
readme = f.read()
assert fname in readme
def test_apps_documented(constructor):
def test_app_library(constructor):
if constructor.NAME in EXCLUDE:
return
@ -28,8 +28,32 @@ def test_apps_documented(constructor):
with open('docs/wasp.rst') as f:
waspdoc = f.read()
# Every application must be listed in either the
# Application Library or the Reference manual
needle = f'.. automodule:: {constructor.__module__}'
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:
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('~~~~'))