Skip to content

Commit b031b7d

Browse files
committed
hacking: Add tests
Change-Id: Ic973aaa0ea623575399868c47e8aac7b7d6d0561 Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
1 parent 73c6603 commit b031b7d

2 files changed

Lines changed: 109 additions & 0 deletions

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
13+
import importlib.util
14+
import os
15+
import re
16+
import subprocess
17+
import sys
18+
import unittest
19+
20+
import fixtures
21+
22+
ROOT_DIR = os.path.normpath(
23+
os.path.join(os.path.dirname(__file__), '..', '..', '..')
24+
)
25+
SELFTEST_REGEX = re.compile(r'\b(Okay|[HEW]\d{3}|O\d{3}):\s(.*)')
26+
27+
# Checks that filter on 'openstackclient/tests/unit' in the filename need the
28+
# temp file written into that path structure so the check is not skipped.
29+
_UNIT_TEST_SUBDIRS = {
30+
'O401': os.path.join('openstackclient', 'tests', 'unit'),
31+
'O402': os.path.join('openstackclient', 'tests', 'unit'),
32+
}
33+
34+
35+
def _load_checks():
36+
spec = importlib.util.spec_from_file_location(
37+
'_osc_hacking_checks',
38+
os.path.join(ROOT_DIR, 'hacking', 'checks.py'),
39+
)
40+
module = importlib.util.module_from_spec(spec)
41+
spec.loader.exec_module(module)
42+
return module
43+
44+
45+
def _get_examples(check):
46+
for line in check.__doc__.splitlines():
47+
line = line.lstrip()
48+
match = SELFTEST_REGEX.match(line)
49+
if match:
50+
yield match.group(1), match.group(2)
51+
52+
53+
class HackingTestCase(unittest.TestCase):
54+
def _test_check(self, code, source):
55+
lines = [
56+
part.replace(r'\t', '\t') + '\n' for part in source.split(r'\n')
57+
]
58+
subdir = {
59+
'O401': os.path.join('openstackclient', 'tests', 'unit'),
60+
'O402': os.path.join('openstackclient', 'tests', 'unit'),
61+
}.get(code, '')
62+
63+
with fixtures.TempDir() as tmp:
64+
dirpath = os.path.join(tmp.path, subdir) if subdir else tmp.path
65+
if subdir:
66+
os.makedirs(dirpath)
67+
68+
fpath = os.path.join(dirpath, 'test_tmp.py')
69+
with open(fpath, 'w') as f:
70+
f.write(''.join(lines))
71+
72+
cmd = [
73+
sys.executable,
74+
'-mflake8',
75+
'--config',
76+
os.path.join(ROOT_DIR, 'tox.ini'),
77+
f'--select={code}',
78+
'--format=%(code)s\t%(path)s\t%(row)d',
79+
fpath,
80+
]
81+
out, _ = subprocess.Popen(
82+
cmd, stdout=subprocess.PIPE, cwd=ROOT_DIR
83+
).communicate()
84+
out = out.decode('utf-8')
85+
86+
if code == 'Okay':
87+
self.assertEqual('', out)
88+
else:
89+
self.assertNotEqual('', out, f"Failed to trigger rule {code}")
90+
self.assertEqual(code, out.split('\t')[0].rstrip(':'), out)
91+
92+
def test_checks(self):
93+
checks_module = _load_checks()
94+
95+
for name in sorted(dir(checks_module)):
96+
check = getattr(checks_module, name)
97+
if not callable(check):
98+
continue
99+
100+
if getattr(check, 'skip_on_py3', None) is not False:
101+
continue
102+
103+
if not check.__doc__:
104+
continue
105+
106+
for code, source in _get_examples(check):
107+
with self.subTest(check=name, example=source):
108+
self._test_check(code, source)

test-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
coverage!=4.4,>=4.0 # Apache-2.0
22
fixtures>=3.0.0 # Apache-2.0/BSD
3+
hacking>=8.0.0 # Apache-2.0
34
requests-mock>=1.2.0 # Apache-2.0
45
stestr>=1.0.0 # Apache-2.0
56
testtools>=2.2.0 # MIT

0 commit comments

Comments
 (0)