aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorskullY <skullydazed@gmail.com>2019-08-21 23:40:24 -0700
committerskullydazed <skullydazed@users.noreply.github.com>2019-09-07 07:58:41 -0700
commit5b7a5b2a7629fbb667d23a55836dce3c6c46a203 (patch)
treeb153a030844887422464c6c4f4833242b34a9314
parent4d339b7b5d1ecc2320080798d7e07e2d43675578 (diff)
downloadqmk_firmware-5b7a5b2a7629fbb667d23a55836dce3c6c46a203.tar.gz
qmk_firmware-5b7a5b2a7629fbb667d23a55836dce3c6c46a203.zip
Setup a python test framework
-rwxr-xr-xbin/qmk8
-rw-r--r--keyboards/handwired/onekey/pytest/config.h23
-rw-r--r--keyboards/handwired/onekey/pytest/readme.md3
-rw-r--r--keyboards/handwired/onekey/pytest/rules.mk2
-rw-r--r--keyboards/handwired/onekey/pytest/templates/keymap.c1
-rw-r--r--lib/python/milc.py3
-rwxr-xr-xlib/python/qmk/cli/doctor.py30
-rw-r--r--lib/python/qmk/cli/nose2.py18
-rw-r--r--lib/python/qmk/tests/__init__.py0
-rw-r--r--lib/python/qmk/tests/attrdict.py8
-rw-r--r--lib/python/qmk/tests/onekey_export.json6
-rw-r--r--lib/python/qmk/tests/test_qmk_errors.py7
-rw-r--r--lib/python/qmk/tests/test_qmk_keymap.py18
-rw-r--r--lib/python/qmk/tests/test_qmk_path.py12
-rw-r--r--nose2.cfg2
15 files changed, 130 insertions, 11 deletions
diff --git a/bin/qmk b/bin/qmk
index 3c00a675e..1aa16e17d 100755
--- a/bin/qmk
+++ b/bin/qmk
@@ -94,4 +94,10 @@ else:
94 exit(1) 94 exit(1)
95 95
96if __name__ == '__main__': 96if __name__ == '__main__':
97 milc.cli() 97 return_code = milc.cli()
98 if return_code is False:
99 exit(1)
100 elif return_code is not True and isinstance(return_code, int) and return_code < 256:
101 exit(return_code)
102 else:
103 exit(0)
diff --git a/keyboards/handwired/onekey/pytest/config.h b/keyboards/handwired/onekey/pytest/config.h
new file mode 100644
index 000000000..f6bedcfe6
--- /dev/null
+++ b/keyboards/handwired/onekey/pytest/config.h
@@ -0,0 +1,23 @@
1/* Copyright 2019
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#include "config_common.h"
20
21#define MATRIX_COL_PINS { A3 }
22#define MATRIX_ROW_PINS { A2 }
23#define UNUSED_PINS
diff --git a/keyboards/handwired/onekey/pytest/readme.md b/keyboards/handwired/onekey/pytest/readme.md
new file mode 100644
index 000000000..dbbd991f1
--- /dev/null
+++ b/keyboards/handwired/onekey/pytest/readme.md
@@ -0,0 +1,3 @@
1# PyTest onekey
2
3This is used by the python test framework. It's probably not useful otherwise.
diff --git a/keyboards/handwired/onekey/pytest/rules.mk b/keyboards/handwired/onekey/pytest/rules.mk
new file mode 100644
index 000000000..b17a3d031
--- /dev/null
+++ b/keyboards/handwired/onekey/pytest/rules.mk
@@ -0,0 +1,2 @@
1# MCU name
2MCU = STM32F303
diff --git a/keyboards/handwired/onekey/pytest/templates/keymap.c b/keyboards/handwired/onekey/pytest/templates/keymap.c
new file mode 100644
index 000000000..d355210c4
--- /dev/null
+++ b/keyboards/handwired/onekey/pytest/templates/keymap.c
@@ -0,0 +1 @@
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {__KEYMAP_GOES_HERE__};
diff --git a/lib/python/milc.py b/lib/python/milc.py
index 6e82edf8b..c62c1b166 100644
--- a/lib/python/milc.py
+++ b/lib/python/milc.py
@@ -534,8 +534,7 @@ class MILC(object):
534 if not self._inside_context_manager: 534 if not self._inside_context_manager:
535 # If they didn't use the context manager use it ourselves 535 # If they didn't use the context manager use it ourselves
536 with self: 536 with self:
537 self.__call__() 537 return self.__call__()
538 return
539 538
540 if not self._entrypoint: 539 if not self._entrypoint:
541 raise RuntimeError('No entrypoint provided!') 540 raise RuntimeError('No entrypoint provided!')
diff --git a/lib/python/qmk/cli/doctor.py b/lib/python/qmk/cli/doctor.py
index 9ce765a4b..c5a144363 100755
--- a/lib/python/qmk/cli/doctor.py
+++ b/lib/python/qmk/cli/doctor.py
@@ -2,9 +2,11 @@
2 2
3Check up for QMK environment. 3Check up for QMK environment.
4""" 4"""
5import shutil
6import platform
7import os 5import os
6import platform
7import shutil
8import subprocess
9from glob import glob
8 10
9from milc import cli 11from milc import cli
10 12
@@ -16,32 +18,44 @@ def main(cli):
16 This is currently very simple, it just checks that all the expected binaries are on your system. 18 This is currently very simple, it just checks that all the expected binaries are on your system.
17 19
18 TODO(unclaimed): 20 TODO(unclaimed):
19 * [ ] Run the binaries to make sure they work
20 * [ ] Compile a trivial program with each compiler 21 * [ ] Compile a trivial program with each compiler
21 * [ ] Check for udev entries on linux 22 * [ ] Check for udev entries on linux
22 """ 23 """
23 24
24 binaries = ['dfu-programmer', 'avrdude', 'dfu-util', 'avr-gcc', 'arm-none-eabi-gcc'] 25 binaries = ['dfu-programmer', 'avrdude', 'dfu-util', 'avr-gcc', 'arm-none-eabi-gcc']
26 binaries += glob('bin/qmk-*')
25 27
26 cli.log.info('QMK Doctor is Checking your environment') 28 cli.log.info('QMK Doctor is checking your environment')
27 29
28 ok = True 30 ok = True
29 for binary in binaries: 31 for binary in binaries:
30 res = shutil.which(binary) 32 res = shutil.which(binary)
31 if res is None: 33 if res is None:
32 cli.log.error('{fg_red}QMK can\'t find ' + binary + ' in your path') 34 cli.log.error("{fg_red}QMK can't find %s in your path", binary)
33 ok = False 35 ok = False
36 else:
37 try:
38 subprocess.run([binary, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=5, check=True)
39 except subprocess.CalledProcessError:
40 cli.log.error("{fg_red}Can't run `%s --version`", binary)
41 ok = False
34 42
35 OS = platform.system() 43 OS = platform.system()
36 if OS == "Darwin": 44 if OS == "Darwin":
37 cli.log.info("Detected {fg_cyan}macOS") 45 cli.log.info("Detected {fg_cyan}macOS")
38 elif OS == "Linux": 46 elif OS == "Linux":
39 cli.log.info("Detected {fg_cyan}linux") 47 cli.log.info("Detected {fg_cyan}linux")
40 test = 'systemctl list-unit-files | grep enabled | grep -i ModemManager' 48 if shutil.which('systemctl'):
41 if os.system(test) == 0: 49 test = 'systemctl list-unit-files | grep enabled | grep -i ModemManager'
42 cli.log.warn("{bg_yellow}Detected modem manager. Please disable it if you are using Pro Micros") 50 if os.system(test) == 0:
51 cli.log.warn("{bg_yellow}Detected modem manager. Please disable it if you are using Pro Micros")
52 else:
53 cli.log.warn("Can't find systemctl to check for ModemManager.")
43 else: 54 else:
44 cli.log.info("Assuming {fg_cyan}Windows") 55 cli.log.info("Assuming {fg_cyan}Windows")
45 56
46 if ok: 57 if ok:
47 cli.log.info('{fg_green}QMK is ready to go') 58 cli.log.info('{fg_green}QMK is ready to go')
59 else:
60 cli.log.info('{fg_yellow}Problems detected, please fix these problems before proceeding.')
61 # FIXME(skullydazed): Link to a document about troubleshooting, or discord or something
diff --git a/lib/python/qmk/cli/nose2.py b/lib/python/qmk/cli/nose2.py
new file mode 100644
index 000000000..c6c9c67b3
--- /dev/null
+++ b/lib/python/qmk/cli/nose2.py
@@ -0,0 +1,18 @@
1"""QMK Python Unit Tests
2
3QMK script to run unit and integration tests against our python code.
4"""
5from milc import cli
6
7
8@cli.entrypoint('QMK Python Unit Tests')
9def main(cli):
10 """Use nose2 to run unittests
11 """
12 try:
13 import nose2
14 except ImportError:
15 cli.log.error('Could not import nose2! Please install it with {fg_cyan}pip3 install nose2')
16 return False
17
18 nose2.discover()
diff --git a/lib/python/qmk/tests/__init__.py b/lib/python/qmk/tests/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/lib/python/qmk/tests/__init__.py
diff --git a/lib/python/qmk/tests/attrdict.py b/lib/python/qmk/tests/attrdict.py
new file mode 100644
index 000000000..a2584b923
--- /dev/null
+++ b/lib/python/qmk/tests/attrdict.py
@@ -0,0 +1,8 @@
1class AttrDict(dict):
2 """A dictionary that can be accessed by attributes.
3
4 This should only be used to mock objects for unit testing. Please do not use this outside of qmk.tests.
5 """
6 def __init__(self, *args, **kwargs):
7 super(AttrDict, self).__init__(*args, **kwargs)
8 self.__dict__ = self
diff --git a/lib/python/qmk/tests/onekey_export.json b/lib/python/qmk/tests/onekey_export.json
new file mode 100644
index 000000000..95f0a980f
--- /dev/null
+++ b/lib/python/qmk/tests/onekey_export.json
@@ -0,0 +1,6 @@
1{
2 "keyboard":"handwired/onekey/pytest",
3 "keymap":"pytest_unittest",
4 "layout":"LAYOUT",
5 "layers":[["KC_A"]]
6}
diff --git a/lib/python/qmk/tests/test_qmk_errors.py b/lib/python/qmk/tests/test_qmk_errors.py
new file mode 100644
index 000000000..3f6b56713
--- /dev/null
+++ b/lib/python/qmk/tests/test_qmk_errors.py
@@ -0,0 +1,7 @@
1from qmk.errors import NoSuchKeyboardError
2
3def test_NoSuchKeyboardError():
4 try:
5 raise(NoSuchKeyboardError("test message"))
6 except NoSuchKeyboardError as e:
7 assert e.message == 'test message'
diff --git a/lib/python/qmk/tests/test_qmk_keymap.py b/lib/python/qmk/tests/test_qmk_keymap.py
new file mode 100644
index 000000000..6a565ee90
--- /dev/null
+++ b/lib/python/qmk/tests/test_qmk_keymap.py
@@ -0,0 +1,18 @@
1import qmk.keymap
2
3def test_template_onekey_proton_c():
4 templ = qmk.keymap.template('handwired/onekey/proton_c')
5 assert templ == qmk.keymap.DEFAULT_KEYMAP_C
6
7
8def test_template_onekey_pytest():
9 templ = qmk.keymap.template('handwired/onekey/pytest')
10 assert templ == 'const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {__KEYMAP_GOES_HERE__};\n'
11
12
13def test_generate_onekey_pytest():
14 templ = qmk.keymap.generate('handwired/onekey/pytest', 'LAYOUT', [['KC_A']])
15 assert templ == 'const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [0] = LAYOUT(KC_A)};\n'
16
17
18# FIXME(skullydazed): Add a test for qmk.keymap.write that mocks up an FD.
diff --git a/lib/python/qmk/tests/test_qmk_path.py b/lib/python/qmk/tests/test_qmk_path.py
new file mode 100644
index 000000000..23816be7e
--- /dev/null
+++ b/lib/python/qmk/tests/test_qmk_path.py
@@ -0,0 +1,12 @@
1import os
2
3import qmk.path
4
5def test_keymap_onekey_pytest():
6 path = qmk.path.keymap('handwired/onekey/pytest')
7 assert path == 'keyboards/handwired/onekey/keymaps'
8
9
10def test_normpath():
11 path = qmk.path.normpath('lib/python')
12 assert path == os.environ['ORIG_CWD'] + '/lib/python'
diff --git a/nose2.cfg b/nose2.cfg
new file mode 100644
index 000000000..136354553
--- /dev/null
+++ b/nose2.cfg
@@ -0,0 +1,2 @@
1[unittest]
2start-dir = lib/python/qmk/tests