From 9b786ba8c7c0d41347e6d8cf1d8ee4ca24f72db8 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 2 Nov 2016 18:24:52 +0200 Subject: [PATCH] Remote Unit Testing --- docs/plus/unit-testing.rst | 74 +++++++++++----- docs/projectconf.rst | 24 +++++- docs/userguide/cmd_test.rst | 27 +++++- docs/userguide/remote/cmd_test.rst | 134 +++++++++++++++++++++++++++++ docs/userguide/remote/index.rst | 1 + examples | 2 +- platformio/builder/tools/piolib.py | 9 +- platformio/commands/remote.py | 35 ++++++-- platformio/commands/run.py | 2 +- platformio/commands/test.py | 7 +- 10 files changed, 271 insertions(+), 44 deletions(-) create mode 100644 docs/userguide/remote/cmd_test.rst diff --git a/docs/plus/unit-testing.rst b/docs/plus/unit-testing.rst index 4236e8dc..6e56a1d8 100644 --- a/docs/plus/unit-testing.rst +++ b/docs/plus/unit-testing.rst @@ -9,6 +9,9 @@ See the License for the specific language governing permissions and limitations under the License. +.. |PIOUTE| replace:: **PlatformIO Unit Testing Engine** +.. |PIOUTF| replace:: *PlatformIO Unit Testing Framework* + .. _unit_testing: Unit Testing @@ -22,30 +25,53 @@ of one or more MCU program modules together with associated control data, usage procedures, and operating procedures, are tested to determine whether they are fit for use. Unit testing finds problems early in the development cycle. -PlatformIO Testing Engine supports 2 different test types: +|PIOUTE| supports 2 different test types: -1. **Local Test** - *[host, native]*, process test on the host machine - using :ref:`platform_native`. -2. **Embedded Test** - *[remote, hardware]*, prepare special firmware for the - target device and upload it. Run test on the embedded device and collect - results. Process test results on the host machine. +1. **Desktop Test**. PlatformIO wraps test and main program (from + :ref:`projectconf_pio_src_dir`) with own |PIOUTF|, builds final program + using :ref:`platform_native` and run test on a local host machine (desktop). - You will be able to run the same test on the different target devices - (:ref:`embedded_boards`). + .. note:: + PlatformIO does not install any toolchains automatically for + :ref:`platform_native` and requires ``GCC`` toolchain to be installed + on your local machine. + Please open Terminal and check that ``gcc`` command is installed. -PlatformIO Testing Engine consists of: +2. **Embedded Test**. PlatformIO wraps test and main firmware (from + :ref:`projectconf_pio_src_dir`) with own |PIOUTF|, builds special firmware + for a target device and upload it. After uploading, PlatformIO connects + to embedded device (board) using :ref:`projectconf_test_port` , starts + test, collects results and shows test results on the local host machine. -* Project builder -* Test builder -* Firmware uploader (is used only for embedded test) -* Test processor + Currently, |PIOUTE| supports these frameworks: -There is special command :ref:`cmd_test` to run tests from PlatformIO Project. -It allows to process specific environments or to ignore some tests using -"Glob patterns". + * :ref:`framework_arduino` + * :ref:`framework_energia` + * :ref:`framework_mbed`. -Also, is possible to ignore some tests for specific environment using -:ref:`projectconf_test_ignore` option from :ref:`projectconf`. + .. note:: + Please note that |PIOUTF| uses Serial/UART as communication interface + between PlatformIO Unit Test Engine and target device. If you use + ``Serial`` in your project, please wrap/hide Serial-based blocks with + ``#ifndef UNIT_TEST`` macro. + + +There are 2 options how to run tests: + +1. **Local**. Allows to run tests on local host machine or on the target devices + (boards) that are directly connected to this machine. In this case, need to + use :ref:`cmd_test` command. + +2. **Remote**. Allows to run tests on remote machine or remote target device + (board) without any dependencies to OS software, extra software, SSH, VPN + or opening network ports. Remote Unit Testing works in pair with + :ref:`pio_remote`. In this case, need to use special command + :ref:`cmd_remote_test`. + +Both commands allow to process specific environments or to ignore some tests +using "Glob patterns". Also, you will be able to ignore some tests for +specific environment using :ref:`projectconf_test_ignore` option +from :ref:`projectconf`. .. contents:: @@ -62,13 +88,13 @@ Demo of `Local & Embedded: Calculator platformio test <../userguide/cmd_test> + platformio remote test <../userguide/remote/cmd_test> -------------- diff --git a/docs/projectconf.rst b/docs/projectconf.rst index ffd04555..2ccb5ebe 100644 --- a/docs/projectconf.rst +++ b/docs/projectconf.rst @@ -648,7 +648,7 @@ This option is used by "uploader" tool when sending firmware to board via If ``upload_port`` isn't specified, then *PlatformIO* will try to detect it automatically. -To print all available serial ports use :ref:`cmd_device` command. +To print all available serial ports use :ref:`cmd_device_list` command. This option can be set by global environment variable :envvar:`PLATFORMIO_UPLOAD_PORT`. @@ -841,9 +841,9 @@ Test options .. seealso:: Please make sure to read :ref:`unit_testing` guide first. -Ignore tests where the name matches specified patterns. Multiple names are -allowed. Please separate them using comma+space ", ". Also, you can -ignore some tests using :option:`platformio test --ignore` command. +Ignore :ref:`unit_testing` tests where the name matches specified patterns. +Multiple names are allowed. Please separate them using comma+space ", ". Also, +you can ignore some tests using :option:`platformio test --ignore` command. .. list-table:: :header-rows: 1 @@ -870,6 +870,22 @@ ignore some tests using :option:`platformio test --ignore` command. [env:myenv] test_ignore = footest, bartest_*, test[13] +.. _projectconf_test_port: + +``test_port`` +^^^^^^^^^^^^^ + +This option is used as communication interface (Serial/UART) between PlatformIO +:ref:`unit_testing` Engine and target device. For example, + +* ``/dev/ttyUSB0`` - Unix-based OS +* ``COM3`` - Windows OS + +If ``test_port`` isn't specified, then *PlatformIO* will try to detect it +automatically. + +To print all available serial ports use :ref:`cmd_device_list` command. + Advanced options ~~~~~~~~~~~~~~~~ diff --git a/docs/userguide/cmd_test.rst b/docs/userguide/cmd_test.rst index e34ea0c0..9d7f3394 100644 --- a/docs/userguide/cmd_test.rst +++ b/docs/userguide/cmd_test.rst @@ -14,7 +14,7 @@ platformio test =============== -.. versionadded:: 3.0 +Helper command for local :ref:`unit_testing`. .. contents:: @@ -28,7 +28,7 @@ Usage Description ----------- -Run tests from PlatformIO based project. More details about PlatformIO +Run locally tests from PlatformIO based project. More details about PlatformIO :ref:`unit_testing`. This command allows you to apply the tests for the environments specified @@ -75,17 +75,36 @@ For example, ``platformio test --ignore "mytest*" -i "test[13]"`` .. option:: --upload-port -Upload port of embedded board. To print all available ports use -:ref:`cmd_device` command. +A port that is intended for firmware uploading. To list available ports +please use :ref:`cmd_device_list` command. If upload port is not specified, PlatformIO will try to detect it automatically. +.. option:: + --test-port + +A Serial/UART port that PlatformIO uses as communication interface between +PlatformIO Unit Test Engine and target device. To list available ports +please use :ref:`cmd_device_list` command. + +If test port is not specified, PlatformIO will try to detect it automatically. + .. option:: -d, --project-dir Specify the path to project directory. By default, ``--project-dir`` is equal to current working directory (``CWD``). +.. option:: + --without-building + +Skip building stage. + +.. option:: + --without-uploading + +Skip uploading stage + .. option:: -v, --verbose diff --git a/docs/userguide/remote/cmd_test.rst b/docs/userguide/remote/cmd_test.rst new file mode 100644 index 00000000..ea631c82 --- /dev/null +++ b/docs/userguide/remote/cmd_test.rst @@ -0,0 +1,134 @@ +.. Copyright 2014-present PlatformIO + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +.. _cmd_remote_test: + +platformio remote test +====================== + +Helper command for remote :ref:`unit_testing`. + +.. contents:: + +Usage +----- + +.. code-block:: bash + + platformio remote test [OPTIONS] + + # run tests on specified PIO Remote Agent + platformio remote --agent NAME test [OPTIONS] + +Description +----------- + +Run remotely tests from PlatformIO based project. More details about PlatformIO +:ref:`unit_testing`. + +This command allows you to apply the tests for the environments specified +in :ref:`projectconf`. + +Options +------- + +.. program:: platformio remote test + +.. option:: + -e, --environment + +Process specified environments. More details :option:`platformio run --environment` + +.. option:: + -i, --ignore + +Ignore tests where the name matches specified patterns. More than one +pattern is allowed. If you need to ignore some tests for the specific +environment, please take a look at :ref:`projectconf_test_ignore` option from +:ref:`projectconf`. + +.. list-table:: + :header-rows: 1 + + * - Pattern + - Meaning + + * - ``*`` + - matches everything + + * - ``?`` + - matches any single character + + * - ``[seq]`` + - matches any character in seq + + * - ``[!seq]`` + - matches any character not in seq + +For example, ``platformio remote test --ignore "mytest*" -i "test[13]"`` + +.. option:: + --upload-port + +A port that is intended for firmware uploading. To list available ports +please use :ref:`cmd_device_list` command. + +If upload port is not specified, PlatformIO will try to detect it automatically. + +.. option:: + --test-port + +A Serial/UART port that PlatformIO uses as communication interface between +PlatformIO Unit Test Engine and target device. To list available ports +please use :ref:`cmd_device_list` command. + +If test port is not specified, PlatformIO will try to detect it automatically. + +.. option:: + -d, --project-dir + +Specify the path to project directory. By default, ``--project-dir`` is equal +to current working directory (``CWD``). + +.. option:: + -r, --build-remotely + +By default, :ref:`pio_remote` builds project on the local machine and deploy +final testing firmware Over-The-Air (OTA) to remote device. + +If you need to build project on remote machine, please use +:option:`platformio remote test --build-remotely` option. In this case, +:ref:`pio_remote` will automatically deploy your project to remote machine, +install required toolchains, frameworks, SDKs, etc and process tests. + + +.. option:: + --without-building + +Skip building stage. + +.. option:: + --without-uploading + +Skip uploading stage + +.. option:: + -v, --verbose + +Shows detailed information when processing environments. + +This option can be set globally using :ref:`setting_force_verbose` setting +or by environment variable :envvar:`PLATFORMIO_SETTING_FORCE_VERBOSE`. + +Examples +-------- + +For the examples please follow to :ref:`unit_testing` page. diff --git a/docs/userguide/remote/index.rst b/docs/userguide/remote/index.rst index eb3e2ecc..b42708a2 100644 --- a/docs/userguide/remote/index.rst +++ b/docs/userguide/remote/index.rst @@ -45,3 +45,4 @@ To print all available commands and options use: cmd_agent cmd_device cmd_run + cmd_test diff --git a/examples b/examples index 15e215e3..5ca4b103 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 15e215e33ea98a55a873af99de26275d9dca163d +Subproject commit 5ca4b103ab57eb0025b9dda85b5f25ce6e776e4a diff --git a/platformio/builder/tools/piolib.py b/platformio/builder/tools/piolib.py index 6b3100e7..711bc394 100644 --- a/platformio/builder/tools/piolib.py +++ b/platformio/builder/tools/piolib.py @@ -214,8 +214,11 @@ class LibBuilderBase(object): for item in self.dependencies: skip = False for key in ("platforms", "frameworks"): - if (key in item and not self.items_in_list( - self.env["PIO" + key.upper()[:-1]], item[key])): + env_key = "PIO" + key.upper()[:-1] + if env_key not in self.env: + continue + if (key in item and + not self.items_in_list(self.env[env_key], item[key])): if verbose: sys.stderr.write("Skip %s incompatible dependency %s\n" % (key[:-1], item)) @@ -507,7 +510,7 @@ class PlatformIOLibBuilder(LibBuilderBase): isdir(join(self.path, "utility"))): inc_dirs.append(join(self.path, "utility")) - for path in self.env['CPPPATH']: + for path in self.env.get("CPPPATH", []): if path not in self.envorigin['CPPPATH']: inc_dirs.append(self.env.subst(path)) return inc_dirs diff --git a/platformio/commands/remote.py b/platformio/commands/remote.py index 94560ac0..94fadc6a 100644 --- a/platformio/commands/remote.py +++ b/platformio/commands/remote.py @@ -51,7 +51,7 @@ def remote_agent_list(): pioplus_call(sys.argv[1:]) -@cli.command("run", short_help="Process project environments") +@cli.command("run", short_help="Process project environments remotely") @click.option("-e", "--environment", multiple=True) @click.option("-t", "--target", multiple=True) @click.option("--upload-port") @@ -65,26 +65,49 @@ def remote_agent_list(): dir_okay=True, writable=True, resolve_path=True)) +@click.option("--disable-auto-clean", is_flag=True) +@click.option("-r", "--build-remotely", is_flag=True) @click.option("-s", "--silent", is_flag=True) @click.option("-v", "--verbose", is_flag=True) -@click.option("-r", "--build-remotely", is_flag=True) -@click.option("--disable-auto-clean", is_flag=True) def remote_run(**kwargs): pioplus_call(sys.argv[1:]) -@cli.group("device", short_help="Monitor device or list existing") +@cli.command("test", short_help="Remote Unit Testing") +@click.option("--environment", "-e", multiple=True, metavar="") +@click.option("--ignore", "-i", multiple=True, metavar="") +@click.option("--upload-port") +@click.option("--test-port") +@click.option( + "-d", + "--project-dir", + default=getcwd, + type=click.Path( + exists=True, + file_okay=False, + dir_okay=True, + writable=True, + resolve_path=True)) +@click.option("-r", "--build-remotely", is_flag=True) +@click.option("--without-building", is_flag=True) +@click.option("--without-uploading", is_flag=True) +@click.option("--verbose", "-v", is_flag=True) +def remote_test(**kwargs): + pioplus_call(sys.argv[1:]) + + +@cli.group("device", short_help="Monitor remote device or list existing") def remote_device(): pass -@remote_device.command("list", short_help="List devices") +@remote_device.command("list", short_help="List remote devices") @click.option("--json-output", is_flag=True) def device_list(json_output): pioplus_call(sys.argv[1:]) -@remote_device.command("monitor", short_help="Monitor device (Serial)") +@remote_device.command("monitor", short_help="Monitor remote device") @click.option("--port", "-p", help="Port, a number or a device name") @click.option( "--baud", "-b", type=int, default=9600, help="Set baud rate, default=9600") diff --git a/platformio/commands/run.py b/platformio/commands/run.py index 27fcc269..ead610a9 100644 --- a/platformio/commands/run.py +++ b/platformio/commands/run.py @@ -126,7 +126,7 @@ class EnvironmentProcessor(object): "upload_port", "upload_protocol", "upload_speed", "upload_flags", "upload_resetmethod", "lib_install", "lib_deps", "lib_force", "lib_ignore", "lib_extra_dirs", "lib_ldf_mode", "lib_compat_mode", - "test_ignore", "piotest") + "test_ignore", "test_port", "piotest") REMAPED_OPTIONS = {"framework": "pioframework", "platform": "pioplatform"} diff --git a/platformio/commands/test.py b/platformio/commands/test.py index 420c7082..714113ce 100644 --- a/platformio/commands/test.py +++ b/platformio/commands/test.py @@ -20,10 +20,11 @@ import click from platformio.pioplus import pioplus_call -@click.command("test", short_help="Unit Testing") +@click.command("test", short_help="Local Unit Testing") @click.option("--environment", "-e", multiple=True, metavar="") @click.option("--ignore", "-i", multiple=True, metavar="") -@click.option("--upload-port", metavar="") +@click.option("--upload-port") +@click.option("--test-port") @click.option( "-d", "--project-dir", @@ -34,6 +35,8 @@ from platformio.pioplus import pioplus_call dir_okay=True, writable=True, resolve_path=True)) +@click.option("--without-building", is_flag=True) +@click.option("--without-uploading", is_flag=True) @click.option("--verbose", "-v", is_flag=True) def cli(*args, **kwargs): # pylint: disable=unused-argument pioplus_call(sys.argv[1:])