Setup a python test framework

This commit is contained in:
skullY 2019-08-21 23:40:24 -07:00 committed by skullydazed
parent 4d339b7b5d
commit 5b7a5b2a76
15 changed files with 130 additions and 11 deletions

View file

@ -94,4 +94,10 @@ else:
exit(1) exit(1)
if __name__ == '__main__': if __name__ == '__main__':
milc.cli() return_code = milc.cli()
if return_code is False:
exit(1)
elif return_code is not True and isinstance(return_code, int) and return_code < 256:
exit(return_code)
else:
exit(0)

View file

@ -0,0 +1,23 @@
/* Copyright 2019
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "config_common.h"
#define MATRIX_COL_PINS { A3 }
#define MATRIX_ROW_PINS { A2 }
#define UNUSED_PINS

View file

@ -0,0 +1,3 @@
# PyTest onekey
This is used by the python test framework. It's probably not useful otherwise.

View file

@ -0,0 +1,2 @@
# MCU name
MCU = STM32F303

View file

@ -0,0 +1 @@
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {__KEYMAP_GOES_HERE__};

View file

@ -534,8 +534,7 @@ class MILC(object):
if not self._inside_context_manager: if not self._inside_context_manager:
# If they didn't use the context manager use it ourselves # If they didn't use the context manager use it ourselves
with self: with self:
self.__call__() return self.__call__()
return
if not self._entrypoint: if not self._entrypoint:
raise RuntimeError('No entrypoint provided!') raise RuntimeError('No entrypoint provided!')

View file

@ -2,9 +2,11 @@
Check up for QMK environment. Check up for QMK environment.
""" """
import shutil
import platform
import os import os
import platform
import shutil
import subprocess
from glob import glob
from milc import cli from milc import cli
@ -16,20 +18,26 @@ def main(cli):
This is currently very simple, it just checks that all the expected binaries are on your system. This is currently very simple, it just checks that all the expected binaries are on your system.
TODO(unclaimed): TODO(unclaimed):
* [ ] Run the binaries to make sure they work
* [ ] Compile a trivial program with each compiler * [ ] Compile a trivial program with each compiler
* [ ] Check for udev entries on linux * [ ] Check for udev entries on linux
""" """
binaries = ['dfu-programmer', 'avrdude', 'dfu-util', 'avr-gcc', 'arm-none-eabi-gcc'] binaries = ['dfu-programmer', 'avrdude', 'dfu-util', 'avr-gcc', 'arm-none-eabi-gcc']
binaries += glob('bin/qmk-*')
cli.log.info('QMK Doctor is Checking your environment') cli.log.info('QMK Doctor is checking your environment')
ok = True ok = True
for binary in binaries: for binary in binaries:
res = shutil.which(binary) res = shutil.which(binary)
if res is None: if res is None:
cli.log.error('{fg_red}QMK can\'t find ' + binary + ' in your path') cli.log.error("{fg_red}QMK can't find %s in your path", binary)
ok = False
else:
try:
subprocess.run([binary, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=5, check=True)
except subprocess.CalledProcessError:
cli.log.error("{fg_red}Can't run `%s --version`", binary)
ok = False ok = False
OS = platform.system() OS = platform.system()
@ -37,11 +45,17 @@ def main(cli):
cli.log.info("Detected {fg_cyan}macOS") cli.log.info("Detected {fg_cyan}macOS")
elif OS == "Linux": elif OS == "Linux":
cli.log.info("Detected {fg_cyan}linux") cli.log.info("Detected {fg_cyan}linux")
if shutil.which('systemctl'):
test = 'systemctl list-unit-files | grep enabled | grep -i ModemManager' test = 'systemctl list-unit-files | grep enabled | grep -i ModemManager'
if os.system(test) == 0: if os.system(test) == 0:
cli.log.warn("{bg_yellow}Detected modem manager. Please disable it if you are using Pro Micros") cli.log.warn("{bg_yellow}Detected modem manager. Please disable it if you are using Pro Micros")
else:
cli.log.warn("Can't find systemctl to check for ModemManager.")
else: else:
cli.log.info("Assuming {fg_cyan}Windows") cli.log.info("Assuming {fg_cyan}Windows")
if ok: if ok:
cli.log.info('{fg_green}QMK is ready to go') cli.log.info('{fg_green}QMK is ready to go')
else:
cli.log.info('{fg_yellow}Problems detected, please fix these problems before proceeding.')
# FIXME(skullydazed): Link to a document about troubleshooting, or discord or something

View file

@ -0,0 +1,18 @@
"""QMK Python Unit Tests
QMK script to run unit and integration tests against our python code.
"""
from milc import cli
@cli.entrypoint('QMK Python Unit Tests')
def main(cli):
"""Use nose2 to run unittests
"""
try:
import nose2
except ImportError:
cli.log.error('Could not import nose2! Please install it with {fg_cyan}pip3 install nose2')
return False
nose2.discover()

View file

View file

@ -0,0 +1,8 @@
class AttrDict(dict):
"""A dictionary that can be accessed by attributes.
This should only be used to mock objects for unit testing. Please do not use this outside of qmk.tests.
"""
def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self

View file

@ -0,0 +1,6 @@
{
"keyboard":"handwired/onekey/pytest",
"keymap":"pytest_unittest",
"layout":"LAYOUT",
"layers":[["KC_A"]]
}

View file

@ -0,0 +1,7 @@
from qmk.errors import NoSuchKeyboardError
def test_NoSuchKeyboardError():
try:
raise(NoSuchKeyboardError("test message"))
except NoSuchKeyboardError as e:
assert e.message == 'test message'

View file

@ -0,0 +1,18 @@
import qmk.keymap
def test_template_onekey_proton_c():
templ = qmk.keymap.template('handwired/onekey/proton_c')
assert templ == qmk.keymap.DEFAULT_KEYMAP_C
def test_template_onekey_pytest():
templ = qmk.keymap.template('handwired/onekey/pytest')
assert templ == 'const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {__KEYMAP_GOES_HERE__};\n'
def test_generate_onekey_pytest():
templ = qmk.keymap.generate('handwired/onekey/pytest', 'LAYOUT', [['KC_A']])
assert templ == 'const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [0] = LAYOUT(KC_A)};\n'
# FIXME(skullydazed): Add a test for qmk.keymap.write that mocks up an FD.

View file

@ -0,0 +1,12 @@
import os
import qmk.path
def test_keymap_onekey_pytest():
path = qmk.path.keymap('handwired/onekey/pytest')
assert path == 'keyboards/handwired/onekey/keymaps'
def test_normpath():
path = qmk.path.normpath('lib/python')
assert path == os.environ['ORIG_CWD'] + '/lib/python'

2
nose2.cfg Normal file
View file

@ -0,0 +1,2 @@
[unittest]
start-dir = lib/python/qmk/tests