mirror of
https://github.com/platformio/platformio-core.git
synced 2025-07-30 10:07:14 +02:00
Allow to ignore tests using glob patterns // Issue #408
This commit is contained in:
@ -44,7 +44,7 @@ Design
|
|||||||
PlatformIO Test System design is based on a few isolated components:
|
PlatformIO Test System design is based on a few isolated components:
|
||||||
|
|
||||||
1. **Main program**. Contains the independent modules, procedures,
|
1. **Main program**. Contains the independent modules, procedures,
|
||||||
functions or methods that will be the target candidates (TC) for testing
|
functions or methods that will be the target candidates (TC) for testing.
|
||||||
2. **Unit test**. This a small independent program that is intended to
|
2. **Unit test**. This a small independent program that is intended to
|
||||||
re-use TC from the main program and apply tests for them.
|
re-use TC from the main program and apply tests for them.
|
||||||
3. **Test processor**. The set of approaches and tools that will be used
|
3. **Test processor**. The set of approaches and tools that will be used
|
||||||
@ -53,8 +53,8 @@ PlatformIO Test System design is based on a few isolated components:
|
|||||||
Workflow
|
Workflow
|
||||||
--------
|
--------
|
||||||
|
|
||||||
1. Create PlatformIO project using :ref:`cmd_init` command
|
1. Create PlatformIO project using :ref:`cmd_init` command.
|
||||||
2. Place source code of main program to ``src`` directory
|
2. Place source code of main program to ``src`` directory.
|
||||||
3. Wrap ``main()`` or ``setup()/loop()`` methods of main program in ``UNIT_TEST``
|
3. Wrap ``main()`` or ``setup()/loop()`` methods of main program in ``UNIT_TEST``
|
||||||
guard:
|
guard:
|
||||||
|
|
||||||
@ -86,10 +86,10 @@ Workflow
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
4. Create ``test`` directory in the root of project. See :ref:`projectconf_pio_test_dir`
|
4. Create ``test`` directory in the root of project. See :ref:`projectconf_pio_test_dir`.
|
||||||
5. Write test using :ref:`unit_testing_api`. The each test is a small
|
5. Write test using :ref:`unit_testing_api`. The each test is a small
|
||||||
independent program with own ``main()`` or ``setup()/loop()`` methods. Also,
|
independent program with own ``main()`` or ``setup()/loop()`` methods. Also,
|
||||||
test should start from ``UNITY_BEGIN()`` and finish with ``UNITY_END()``
|
test should start from ``UNITY_BEGIN()`` and finish with ``UNITY_END()``.
|
||||||
6. Place test to ``test`` directory. If you have more than one test, split them
|
6. Place test to ``test`` directory. If you have more than one test, split them
|
||||||
into sub-folders. For example, ``test/test_1/*.[c,cpp,h]``,
|
into sub-folders. For example, ``test/test_1/*.[c,cpp,h]``,
|
||||||
``test_N/*.[c,cpp,h]``, etc. If no such directory in ``test`` folder, then
|
``test_N/*.[c,cpp,h]``, etc. If no such directory in ``test`` folder, then
|
||||||
@ -185,11 +185,11 @@ Example
|
|||||||
-------
|
-------
|
||||||
|
|
||||||
1. Please follow to :ref:`quickstart` and create "Blink Project". According
|
1. Please follow to :ref:`quickstart` and create "Blink Project". According
|
||||||
to the Unit Testing :ref:`unit_testing_design` it is the **Main program**
|
to the Unit Testing :ref:`unit_testing_design` it is the **Main program**.
|
||||||
2. Create ``test`` directory in that project (on the same level as ``src``)
|
2. Create ``test`` directory in that project (on the same level as ``src``)
|
||||||
and place ``test_main.cpp`` file to it (the source code is located below)
|
and place ``test_main.cpp`` file to it (the source code is located below).
|
||||||
3. Wrap ``setup()`` and ``loop()`` methods of main program in ``UNIT_TEST``
|
3. Wrap ``setup()`` and ``loop()`` methods of main program in ``UNIT_TEST``
|
||||||
guard
|
guard.
|
||||||
4. Run tests using :ref:`cmd_test` command.
|
4. Run tests using :ref:`cmd_test` command.
|
||||||
|
|
||||||
Project structure
|
Project structure
|
||||||
@ -313,11 +313,11 @@ Source files
|
|||||||
delay(500);
|
delay(500);
|
||||||
RUN_TEST(test_led_state_low);
|
RUN_TEST(test_led_state_low);
|
||||||
delay(500);
|
delay(500);
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
else if (i == max_blinks) {
|
else if (i == max_blinks) {
|
||||||
UNITY_END(); // IMPORTANT LINE!
|
UNITY_END(); // stop unit testing
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -42,6 +42,32 @@ Options
|
|||||||
|
|
||||||
Process specified environments. More details :option:`platformio run --environment`
|
Process specified environments. More details :option:`platformio run --environment`
|
||||||
|
|
||||||
|
.. option::
|
||||||
|
-i, --ignore
|
||||||
|
|
||||||
|
Ignore tests where the name matches with specified pattern. More than one
|
||||||
|
option/pattern is allowed.
|
||||||
|
|
||||||
|
.. 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 test --ignore "mytest*" -i "test[13]"``
|
||||||
|
|
||||||
.. option::
|
.. option::
|
||||||
--upload-port
|
--upload-port
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from fnmatch import fnmatch
|
||||||
from os import getcwd, listdir
|
from os import getcwd, listdir
|
||||||
from os.path import isdir, join
|
from os.path import isdir, join
|
||||||
from time import sleep, time
|
from time import sleep, time
|
||||||
@ -27,22 +28,21 @@ from platformio.managers.platform import PlatformFactory
|
|||||||
|
|
||||||
@click.command("test", short_help="Unit Testing")
|
@click.command("test", short_help="Unit Testing")
|
||||||
@click.option("--environment", "-e", multiple=True, metavar="<environment>")
|
@click.option("--environment", "-e", multiple=True, metavar="<environment>")
|
||||||
|
@click.option("--ignore", "-i", multiple=True, metavar="<pattern>")
|
||||||
@click.option("--upload-port", metavar="<upload port>")
|
@click.option("--upload-port", metavar="<upload port>")
|
||||||
@click.option("--project-dir", "-d", default=getcwd,
|
@click.option("--project-dir", "-d", default=getcwd,
|
||||||
type=click.Path(exists=True, file_okay=False, dir_okay=True,
|
type=click.Path(exists=True, file_okay=False, dir_okay=True,
|
||||||
writable=True, resolve_path=True))
|
writable=True, resolve_path=True))
|
||||||
@click.option("--verbose", "-v", count=True, default=3)
|
@click.option("--verbose", "-v", count=True, default=3)
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def cli(ctx, environment, upload_port, # pylint: disable=R0913,R0914
|
def cli(ctx, environment, ignore, upload_port, # pylint: disable=R0913,R0914
|
||||||
project_dir, verbose):
|
project_dir, verbose):
|
||||||
assert check_project_envs(project_dir, environment)
|
assert check_project_envs(project_dir, environment)
|
||||||
with util.cd(project_dir):
|
with util.cd(project_dir):
|
||||||
test_dir = util.get_projecttest_dir()
|
test_dir = util.get_projecttest_dir()
|
||||||
if not isdir(test_dir):
|
if not isdir(test_dir):
|
||||||
raise exception.TestDirEmpty(test_dir)
|
raise exception.TestDirEmpty(test_dir)
|
||||||
config = util.get_project_config()
|
projectconf = util.get_project_config()
|
||||||
env_names = set(
|
|
||||||
[s[4:] for s in config.sections() if s.startswith("env:")])
|
|
||||||
|
|
||||||
test_names = []
|
test_names = []
|
||||||
for item in sorted(listdir(test_dir)):
|
for item in sorted(listdir(test_dir)):
|
||||||
@ -56,11 +56,20 @@ def cli(ctx, environment, upload_port, # pylint: disable=R0913,R0914
|
|||||||
start_time = time()
|
start_time = time()
|
||||||
results = []
|
results = []
|
||||||
for testname in test_names:
|
for testname in test_names:
|
||||||
for envname in env_names:
|
for envname in projectconf.sections():
|
||||||
|
if not envname.startswith("env:"):
|
||||||
|
continue
|
||||||
|
envname = envname[4:]
|
||||||
if environment and envname not in environment:
|
if environment and envname not in environment:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# check ignore patterns
|
||||||
|
if testname != "*" and any([fnmatch(testname, i) for i in ignore]):
|
||||||
|
results.append((None, testname, envname))
|
||||||
|
continue
|
||||||
|
|
||||||
tp = TestProcessor(ctx, testname, envname, {
|
tp = TestProcessor(ctx, testname, envname, {
|
||||||
"project_config": config,
|
"project_config": projectconf,
|
||||||
"project_dir": project_dir,
|
"project_dir": project_dir,
|
||||||
"upload_port": upload_port,
|
"upload_port": upload_port,
|
||||||
"verbose": verbose
|
"verbose": verbose
|
||||||
@ -72,13 +81,18 @@ def cli(ctx, environment, upload_port, # pylint: disable=R0913,R0914
|
|||||||
|
|
||||||
passed = True
|
passed = True
|
||||||
for result in results:
|
for result in results:
|
||||||
if not result[0]:
|
status, testname, envname = result
|
||||||
|
status_str = click.style("PASSED", fg="green")
|
||||||
|
if status is False:
|
||||||
passed = False
|
passed = False
|
||||||
|
status_str = click.style("FAILED", fg="red")
|
||||||
|
elif status is None:
|
||||||
|
status_str = click.style("IGNORED", fg="yellow")
|
||||||
|
|
||||||
click.echo("test:%s/env:%s\t%s" % (
|
click.echo("test:%s/env:%s\t%s" % (
|
||||||
click.style(result[1], fg="yellow"),
|
click.style(testname, fg="yellow"),
|
||||||
click.style(result[2], fg="cyan"),
|
click.style(envname, fg="cyan"),
|
||||||
click.style("PASSED" if passed else "FAILED", fg="green"
|
status_str), err=status is False)
|
||||||
if passed else "red")), err=not passed)
|
|
||||||
|
|
||||||
print_header("[%s] Took %.2f seconds" % (
|
print_header("[%s] Took %.2f seconds" % (
|
||||||
(click.style("PASSED", fg="green", bold=True) if passed
|
(click.style("PASSED", fg="green", bold=True) if passed
|
||||||
@ -144,7 +158,8 @@ class TestProcessor(object):
|
|||||||
line[:-5], click.style("PASSED", fg="green")))
|
line[:-5], click.style("PASSED", fg="green")))
|
||||||
elif ":FAIL:" in line:
|
elif ":FAIL:" in line:
|
||||||
passed = False
|
passed = False
|
||||||
click.secho(line, fg="red")
|
click.echo("%s\t%s" % (
|
||||||
|
line, click.style("FAILED", fg="red")))
|
||||||
else:
|
else:
|
||||||
click.echo(line)
|
click.echo(line)
|
||||||
if all([l in line for l in ("Tests", "Failures", "Ignored")]):
|
if all([l in line for l in ("Tests", "Failures", "Ignored")]):
|
||||||
|
Reference in New Issue
Block a user