Add some tests to validate specs

Tests were added to
- Compare titles with the skeleton template.rst.
- Detect trailing whitespaces
- Check lines are limited to a maximum of 79 characters.
- Detect literal carriage returns

Note: Taken from nova-specs/tests/test_titles.py and modified for
Heat.

Change-Id: Ib8bc85c086cbf37ec79b787c07657b9ffd7d17ac
This commit is contained in:
Sirushti Murugesan 2015-04-21 12:33:12 +05:30
parent 9740d961d5
commit 29e22e45c5
8 changed files with 133 additions and 8 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
heat_specs.egg-info/ heat_specs.egg-info/
doc/build/ doc/build/
.tox/ .tox/
*.pyc
.testrepository

4
.testr.conf Normal file
View File

@ -0,0 +1,4 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 OS_TEST_TIMEOUT=60 ${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

View File

@ -11,14 +11,16 @@
https://blueprints.launchpad.net/heat/+spec/support-to-generate-hot-templates https://blueprints.launchpad.net/heat/+spec/support-to-generate-hot-templates
This Blueprint will support to generate hot templates based on the specified type. This Blueprint will support to generate hot templates based on the specified
type.
Problem description Problem description
=================== ===================
Currently Heat only supports to generate the 'HeatTemplateFormatVersion' template Currently Heat only supports to generate the 'HeatTemplateFormatVersion'
based on the specified resource type, this is the functionality exposed via the template based on the specified resource type, this is the functionality
'heat resource-type-template' command. And the link of the API: exposed via the 'heat resource-type-template' command. And the link of the
API:
http://developer.openstack.org/api-ref-orchestration-v1.html http://developer.openstack.org/api-ref-orchestration-v1.html

View File

@ -24,9 +24,9 @@ attributes also becomes a issue without the knowledge of the attribute type.
Proposed change Proposed change
=============== ===============
The changes will be made in each resource plugin to add type field in the attribute The changes will be made in each resource plugin to add type field in the
schema. Type can be a String, Map or List. This will also generate the docs telling attribute schema. Type can be a String, Map or List. This will also generate
the users what type of value to expect from get_attr. the docs telling the users what type of value to expect from get_attr.
Alternatives Alternatives
------------ ------------

View File

@ -0,0 +1,2 @@
testrepository>=0.0.18
testtools>=0.9.34

0
tests/__init__.py Normal file
View File

111
tests/test_titles.py Normal file
View File

@ -0,0 +1,111 @@
# 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 glob
import re
import docutils.core
import testtools
class TestTitles(testtools.TestCase):
def _get_title(self, section_tree):
section = {
'subtitles': [],
}
for node in section_tree:
if node.tagname == 'title':
section['name'] = node.rawsource
elif node.tagname == 'section':
subsection = self._get_title(node)
section['subtitles'].append(subsection['name'])
return section
def _get_titles(self, spec):
titles = {}
for node in spec:
if node.tagname == 'section':
# Note subsection subtitles are thrown away
section = self._get_title(node)
titles[section['name']] = section['subtitles']
return titles
def _check_titles(self, filename, expect, actual):
missing_sections = [x for x in expect.keys() if (
x not in actual.keys())]
extra_sections = [x for x in actual.keys() if x not in expect.keys()]
msgs = []
if len(missing_sections) > 0:
msgs.append("Missing sections: %s" % missing_sections)
if len(extra_sections) > 0:
msgs.append("Extra sections: %s" % extra_sections)
for section in expect.keys():
missing_subsections = [x for x in expect[section]
if x not in actual[section]]
# extra subsections are allowed
if len(missing_subsections) > 0:
msgs.append("Section '%s' is missing subsections: %s"
% (section, missing_subsections))
if len(msgs) > 0:
self.fail("While checking '%s':\n %s"
% (filename, "\n ".join(msgs)))
def _check_lines_wrapping(self, tpl, raw):
for i, line in enumerate(raw.split("\n")):
if "http://" in line or "https://" in line:
continue
self.assertTrue(
len(line) < 80,
msg="%s:%d: Line limited to a maximum of 79 characters." %
(tpl, i+1))
def _check_no_cr(self, tpl, raw):
matches = re.findall('\r', raw)
self.assertEqual(
0, len(matches),
"Found %s literal carriage returns in file %s" %
(len(matches), tpl))
def _check_trailing_spaces(self, tpl, raw):
for i, line in enumerate(raw.split("\n")):
trailing_spaces = re.findall(" +$", line)
self.assertEqual(
0, len(trailing_spaces),
"Found trailing spaces on line %s of %s" % (i+1, tpl))
def test_template(self):
releases = [x.split('/')[1] for x in glob.glob('specs/*/')]
# Ignore juno and kilo.
releases.remove('juno')
releases.remove('kilo')
for release in releases:
with open("specs/%s/template.rst" % release) as f:
template = f.read()
spec = docutils.core.publish_doctree(template)
template_titles = self._get_titles(spec)
files = glob.glob("specs/%s/*" % release)
for filename in files:
self.assertTrue(filename.endswith(".rst"),
"spec's file must uses 'rst' extension.")
with open(filename) as f:
data = f.read()
spec = docutils.core.publish_doctree(data)
titles = self._get_titles(spec)
self._check_titles(filename, template_titles, titles)
self._check_lines_wrapping(filename, data)
self._check_no_cr(filename, data)
self._check_trailing_spaces(filename, data)

View File

@ -1,6 +1,6 @@
[tox] [tox]
minversion = 1.6 minversion = 1.6
envlist = docs envlist = docs,py27
skipsdist = True skipsdist = True
[testenv] [testenv]
@ -10,6 +10,10 @@ setenv =
VIRTUAL_ENV={envdir} VIRTUAL_ENV={envdir}
deps = -r{toxinidir}/requirements.txt deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt -r{toxinidir}/test-requirements.txt
whitelist_externals = find
commands =
find . -type f -name "*.pyc" -delete
python setup.py testr --slowest --testr-args='{posargs}'
[testenv:venv] [testenv:venv]
commands = {posargs} commands = {posargs}