Define extra hacking rules to ensure code quality
Enforce following codestyle rules: * no xrange * no LOG.warn usage (deprecated in favour of LOG.warning) * usage of assertTrue(x) instead assertEqual(True, x) * usage of assertIsNone(x) instead assertEqual(None, x) * usage of assertIsNotNone(x) instead assertNotEqual(None, x) or assertIsNot(None, x) Change-Id: Ib5b61816faae95937c99b1e4f651c6390b888070
This commit is contained in:
parent
3dbefbe900
commit
73659730ae
0
monasca_persister/hacking/__init__.py
Normal file
0
monasca_persister/hacking/__init__.py
Normal file
80
monasca_persister/hacking/checks.py
Normal file
80
monasca_persister/hacking/checks.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# Copyright 2017 FUJITSU LIMITED
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
import re
|
||||||
|
|
||||||
|
assert_no_xrange_re = re.compile(r"\s*xrange\s*\(")
|
||||||
|
assert_True = re.compile(r".*assertEqual\(True, .*\)")
|
||||||
|
assert_None = re.compile(r".*assertEqual\(None, .*\)")
|
||||||
|
assert_Not_Equal = re.compile(r".*assertNotEqual\(None, .*\)")
|
||||||
|
assert_Is_Not = re.compile(r".*assertIsNot\(None, .*\)")
|
||||||
|
assert_raises_regexp = re.compile(r"assertRaisesRegexp\(")
|
||||||
|
no_log_warn = re.compile(r".*LOG.warn\(.*\)")
|
||||||
|
mutable_default_args = re.compile(r"^\s*def .+\((.+=\{\}|.+=\[\])")
|
||||||
|
|
||||||
|
|
||||||
|
def no_mutable_default_args(logical_line):
|
||||||
|
msg = "M001: Method's default argument shouldn't be mutable!"
|
||||||
|
if mutable_default_args.match(logical_line):
|
||||||
|
yield (0, msg)
|
||||||
|
|
||||||
|
|
||||||
|
def no_xrange(logical_line):
|
||||||
|
if assert_no_xrange_re.match(logical_line):
|
||||||
|
yield (0, "M002: Do not use xrange().")
|
||||||
|
|
||||||
|
|
||||||
|
def validate_assertTrue(logical_line):
|
||||||
|
if re.match(assert_True, logical_line):
|
||||||
|
msg = ("M003: Unit tests should use assertTrue(value) instead"
|
||||||
|
" of using assertEqual(True, value).")
|
||||||
|
yield (0, msg)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_assertIsNone(logical_line):
|
||||||
|
if re.match(assert_None, logical_line):
|
||||||
|
msg = ("M004: Unit tests should use assertIsNone(value) instead"
|
||||||
|
" of using assertEqual(None, value).")
|
||||||
|
yield (0, msg)
|
||||||
|
|
||||||
|
|
||||||
|
def no_log_warn_check(logical_line):
|
||||||
|
if re.match(no_log_warn, logical_line):
|
||||||
|
msg = ("M005: LOG.warn is deprecated, please use LOG.warning!")
|
||||||
|
yield (0, msg)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_assertIsNotNone(logical_line):
|
||||||
|
if re.match(assert_Not_Equal, logical_line) or \
|
||||||
|
re.match(assert_Is_Not, logical_line):
|
||||||
|
msg = ("M006: Unit tests should use assertIsNotNone(value) instead"
|
||||||
|
" of using assertNotEqual(None, value) or"
|
||||||
|
" assertIsNot(None, value).")
|
||||||
|
yield (0, msg)
|
||||||
|
|
||||||
|
|
||||||
|
def assert_raisesRegexp(logical_line):
|
||||||
|
res = assert_raises_regexp.search(logical_line)
|
||||||
|
if res:
|
||||||
|
yield (0, "M007: assertRaisesRegex must be used instead "
|
||||||
|
"of assertRaisesRegexp")
|
||||||
|
|
||||||
|
|
||||||
|
def factory(register):
|
||||||
|
register(no_mutable_default_args)
|
||||||
|
register(no_xrange)
|
||||||
|
register(validate_assertTrue)
|
||||||
|
register(validate_assertIsNone)
|
||||||
|
register(no_log_warn_check)
|
||||||
|
register(validate_assertIsNotNone)
|
||||||
|
register(assert_raisesRegexp)
|
@ -141,7 +141,7 @@ class TestPersister(base.BaseTestCase):
|
|||||||
def test_clean_exit_does_nothing_when_exiting_is_true(self):
|
def test_clean_exit_does_nothing_when_exiting_is_true(self):
|
||||||
self.persister.exiting = True
|
self.persister.exiting = True
|
||||||
|
|
||||||
self.assertEqual(None, self.persister.clean_exit(0))
|
self.assertIsNone(self.persister.clean_exit(0))
|
||||||
|
|
||||||
self.assertFalse(self.mock_sys_exit.called)
|
self.assertFalse(self.mock_sys_exit.called)
|
||||||
|
|
||||||
|
15
tox.ini
15
tox.ini
@ -61,14 +61,18 @@ commands =
|
|||||||
[testenv:venv]
|
[testenv:venv]
|
||||||
commands = {posargs}
|
commands = {posargs}
|
||||||
|
|
||||||
|
[testenv:bindep]
|
||||||
|
# Do not install any requirements. We want this to be fast and work even if
|
||||||
|
# system dependencies are missing, since it's used to tell you what system
|
||||||
|
# dependencies are missing! This also means that bindep must be installed
|
||||||
|
# separately, outside of the requirements files.
|
||||||
|
deps = bindep
|
||||||
|
commands = bindep test
|
||||||
|
|
||||||
[testenv:flake8]
|
[testenv:flake8]
|
||||||
commands =
|
commands =
|
||||||
flake8 monasca_persister
|
flake8 monasca_persister
|
||||||
|
|
||||||
[testenv:bindep]
|
|
||||||
deps = bindep
|
|
||||||
commands = bindep test
|
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 120
|
max-line-length = 120
|
||||||
# TODO: ignored checks should be enabled in the future
|
# TODO: ignored checks should be enabled in the future
|
||||||
@ -80,3 +84,6 @@ exclude=.venv,.git,.tox,dist,*egg,build
|
|||||||
[bandit]
|
[bandit]
|
||||||
commands =
|
commands =
|
||||||
bandit -r monasca_persister -n5 -x monasca_persister/tests
|
bandit -r monasca_persister -n5 -x monasca_persister/tests
|
||||||
|
|
||||||
|
[hacking]
|
||||||
|
local-check-factory = monasca_persister.hacking.checks.factory
|
||||||
|
Loading…
Reference in New Issue
Block a user