Skip to content

Commit

Permalink
Align linter tests with the rest of the colcon packages (#33)
Browse files Browse the repository at this point in the history
This change makes colcon-lcov-result "catch up" to accumulated changes
to the linters run in other colcon packages.

The most noteworthy change is the switch from enchant to scspell to get
better cross-platform consistency.

There are no changes to the actual code in this package.
  • Loading branch information
cottsay committed Feb 7, 2024
1 parent beabff6 commit 78837ab
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 59 deletions.
9 changes: 7 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ install_requires =
colcon-core>=0.5.6
packages = find:
tests_require =
flake8
flake8>=3.6.0
flake8-blind-except
flake8-builtins
flake8-class-newline
Expand All @@ -38,10 +38,10 @@ tests_require =
flake8-import-order
flake8-quotes
pep8-naming
pyenchant
pylint
pytest
pytest-cov
scspell3k>=2.2
zip_safe = true

[options.package_data]
Expand All @@ -51,6 +51,11 @@ colcon_lcov_result.verb.configuration = lcovrc
colcon_core.verb =
lcov-result = colcon_lcov_result.verb.lcov_result:LcovResultVerb

[tool:pytest]
markers =
flake8
linter

[flake8]
import-order-style = google
max-line-length = 99
26 changes: 19 additions & 7 deletions test/spell_check.words
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
CMake
ament
apache
cmake
colcon
filt
demangle
gcno
gcov
genhtml
html
iterdir
lcov
lcovrc
linter
nargs
nofilt
noqa
pragma
pathlib
pkgs
plugin
pydocstyle
pytest
returncode
rtype
stderr
stdout
str
scspell
setuptools
staticmethod
thomas
tracefile
tracefiles
zerocounters
9 changes: 6 additions & 3 deletions test/test_copyright_license.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
from pathlib import Path
import sys

import pytest

def test_copyright_licence():

@pytest.mark.linter
def test_copyright_license():
missing = check_files([Path(__file__).parents[1]])
assert not len(missing), \
'In some files no copyright / license line was found'
Expand All @@ -25,8 +28,8 @@ def check_files(paths):
if not content:
continue
lines = content.splitlines()
has_copyright = \
any(line for line in lines if line.startswith('# Copyright'))
has_copyright = any(filter(
lambda line: line.startswith('# Copyright'), lines))
has_license = \
'# Licensed under the Apache License, Version 2.0' in lines
if not has_copyright or not has_license:
Expand Down
35 changes: 21 additions & 14 deletions test/test_flake8.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,27 @@
from pathlib import Path
import sys

from flake8 import LOG
from flake8.api.legacy import get_style_guide
import pytest


# avoid debug and info messages from flake8 internals
LOG.setLevel(logging.WARN)
@pytest.mark.flake8
@pytest.mark.linter
def test_flake8():
from flake8.api.legacy import get_style_guide

# avoid debug / info / warning messages from flake8 internals
logging.getLogger('flake8').setLevel(logging.ERROR)

# for some reason the pydocstyle logger changes to an effective level of 1
# set higher level to prevent the output to be flooded with debug messages
logging.getLogger('pydocstyle').setLevel(logging.WARNING)

def test_flake8():
style_guide = get_style_guide(
ignore=['D100', 'D104'],
extend_ignore=['D100', 'D104'],
show_source=True,
)
style_guide_tests = get_style_guide(
ignore=['D100', 'D101', 'D102', 'D103', 'D104', 'D105', 'D107'],
extend_ignore=['D100', 'D101', 'D102', 'D103', 'D104', 'D105', 'D107'],
show_source=True,
)

Expand All @@ -38,10 +44,11 @@ def test_flake8():
if total_errors: # pragma: no cover
# output summary with per-category counts
print()
report._application.formatter.show_statistics(report._stats)
print(
'flake8 reported {total_errors} errors'
.format_map(locals()), file=sys.stderr)

assert not report.total_errors, \
'flake8 reported {total_errors} errors'.format_map(locals())
if report.total_errors:
report._application.formatter.show_statistics(report._stats)
if report_tests.total_errors:
report_tests._application.formatter.show_statistics(
report_tests._stats)
print(f'flake8 reported {total_errors} errors', file=sys.stderr)

assert not total_errors, f'flake8 reported {total_errors} errors'
80 changes: 47 additions & 33 deletions test/test_spell_check.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,59 @@
# Copyright 2016-2018 Dirk Thomas
# Copyright 2016-2019 Dirk Thomas
# Licensed under the Apache License, Version 2.0

from pathlib import Path

from pylint.lint import Run
import pytest


spell_check_words_path = Path(__file__).parent / 'spell_check.words'


def test_spell_check():
@pytest.fixture(scope='module')
def known_words():
global spell_check_words_path
return spell_check_words_path.read_text().splitlines()

try:
import enchant # noqa: F401
except ImportError: # pragma: no cover
pytest.skip(
"Skipping spell checking tests since 'enchant' was not found")

try:
Run([
'--disable=all',
'--enable=spelling',
'--spelling-dict=en_US',
'--ignore-comments=no',
'--spelling-private-dict-file=' + str(spell_check_words_path),
str(Path(__file__).parents[1] / 'colcon_lcov_result'),
] + [
str(p) for p in
(Path(__file__).parents[1] / 'test').glob('**/*.py')
])
except SystemExit as e:
assert not e.code, 'Some spell checking errors'
else:
assert False, 'The pylint API is supposed to raise a SystemExit'


def test_spell_check_word_list():
global spell_check_words_path
with spell_check_words_path.open('r') as h:
lines = h.read().splitlines()
assert lines == sorted(lines), \

@pytest.mark.linter
def test_spell_check(known_words):
from scspell import Report
from scspell import SCSPELL_BUILTIN_DICT
from scspell import spell_check

source_filenames = [Path(__file__).parents[1] / 'setup.py'] + \
list(
(Path(__file__).parents[1] / 'colcon_lcov_result')
.glob('**/*.py')) + \
list((Path(__file__).parents[1] / 'test').glob('**/*.py'))

for source_filename in sorted(source_filenames):
print('Spell checking:', source_filename)

# check all files
report = Report(known_words)
spell_check(
[str(p) for p in source_filenames], base_dicts=[SCSPELL_BUILTIN_DICT],
report_only=report, additional_extensions=[('', 'Python')])

unknown_word_count = len(report.unknown_words)
assert unknown_word_count == 0, \
f'Found {unknown_word_count} unknown words: ' + \
', '.join(sorted(report.unknown_words))

unused_known_words = set(known_words) - report.found_known_words
unused_known_word_count = len(unused_known_words)
assert unused_known_word_count == 0, \
f'{unused_known_word_count} words in the word list are not used: ' + \
', '.join(sorted(unused_known_words))


@pytest.mark.linter
def test_spell_check_word_list_order(known_words):
assert known_words == sorted(known_words), \
'The word list should be ordered alphabetically'


@pytest.mark.linter
def test_spell_check_word_list_duplicates(known_words):
assert len(known_words) == len(set(known_words)), \
'The word list should not contain duplicates'

0 comments on commit 78837ab

Please sign in to comment.