Refactor test execution scripts
- Acreate a new tools/run_tests.py script to execute test cases - Move report generation to such script and remove 'report' tox environment - Running test cases generates report files (.log, .html, .xml) into 'report/{envname}' directory - Test cases failures will returns exit code 1 Other script test runner failures returns exit code 2 Big refactory to tox.ini file to try semplifying it: - create the new 'py3' tox environment for running unit tests as default platform python 3 interpreter - use same as py3 '{envdir}' for scenario, functional, neutron and faults tox environments Change-Id: Id09425245cc86b84b41e6b3b1c1db759cc686f3a
This commit is contained in:
parent
55b05ea70a
commit
92248c8506
4
.gitignore
vendored
4
.gitignore
vendored
@ -21,11 +21,11 @@ __pycache__
|
|||||||
AUTHORS
|
AUTHORS
|
||||||
build/*
|
build/*
|
||||||
ChangeLog
|
ChangeLog
|
||||||
cover/
|
|
||||||
doc/build/*
|
doc/build/*
|
||||||
|
cover/
|
||||||
dist/
|
dist/
|
||||||
etc/*.sample
|
etc/*.sample
|
||||||
tobiko_results*
|
report/
|
||||||
test_results*
|
test_results*
|
||||||
zuul/versioninfo
|
zuul/versioninfo
|
||||||
|
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
# Requirements file for 'report' Tox environment
|
|
||||||
|
|
||||||
junitxml>=0.7 # LGPL-3
|
|
||||||
os-testr>=1.0 # Apache-2.0
|
|
||||||
python-subunit>=1.4 ; python_version >= '3.0' # Apache-2.0
|
|
||||||
python-subunit<1.4 ; python_version < '3.0' # Apache-2.0
|
|
||||||
stestr>=2.0 # Apache-2.0
|
|
@ -31,6 +31,7 @@
|
|||||||
loop:
|
loop:
|
||||||
- tobiko.log
|
- tobiko.log
|
||||||
- tobiko.conf
|
- tobiko.conf
|
||||||
|
- '{{ test_report_name }}.log'
|
||||||
- '{{ test_report_name }}.html'
|
- '{{ test_report_name }}.html'
|
||||||
- '{{ test_report_name }}.subunit'
|
- '{{ test_report_name }}.subunit'
|
||||||
- '{{ test_report_name }}.xml'
|
- '{{ test_report_name }}.xml'
|
||||||
|
@ -52,7 +52,7 @@ test_conf: {}
|
|||||||
# --- Test report options -----------------------------------------------------
|
# --- Test report options -----------------------------------------------------
|
||||||
|
|
||||||
# Remote directory where test cases shoulw write report files to
|
# Remote directory where test cases shoulw write report files to
|
||||||
test_report_dir: "{{ test_dir | realpath }}"
|
test_report_dir: "{{ test_dir | realpath }}/report"
|
||||||
test_report_files:
|
test_report_files:
|
||||||
- '{{ test_conf_file | realpath }}'
|
- '{{ test_conf_file | realpath }}'
|
||||||
- '{{ test_log_file | realpath }}'
|
- '{{ test_log_file | realpath }}'
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
tox_command: tox
|
tox_command: tox
|
||||||
tox_min_version: 3.4
|
tox_min_version: 3.8
|
||||||
|
@ -14,11 +14,10 @@ tox_step_name:
|
|||||||
tox_step_index: 0
|
tox_step_index: 0
|
||||||
tox_report_name:
|
tox_report_name:
|
||||||
"{{ test_report_name }}{% if tox_step_index %}_{{ '{:02d}'.format(tox_step_index | int) }}{% endif %}{% if tox_step_name %}_{{ tox_step_name }}{% endif %}{% if tox_envlist %}_{{ tox_envlist }}{% endif %}"
|
"{{ test_report_name }}{% if tox_step_index %}_{{ '{:02d}'.format(tox_step_index | int) }}{% endif %}{% if tox_step_name %}_{{ tox_step_name }}{% endif %}{% if tox_envlist %}_{{ tox_envlist }}{% endif %}"
|
||||||
tox_report_env:
|
|
||||||
TOBIKO_TEST_REPORT_DIR: '{{ tox_report_dir }}'
|
|
||||||
TOBIKO_TEST_REPORT_NAME: '{{ tox_report_name }}'
|
|
||||||
|
|
||||||
tox_constraints_file: '{{ remote_constraints_file }}'
|
tox_constraints_file: '{{ remote_constraints_file }}'
|
||||||
|
|
||||||
tox_constrain_env:
|
tox_constrain_env:
|
||||||
UPPER_CONSTRAINTS_FILE: '{{ tox_constraints_file }}'
|
TOX_REPORT_DIR: '{{ tox_report_dir }}'
|
||||||
|
TOX_REPORT_NAME: '{{ tox_report_name }}'
|
||||||
|
TOX_CONSTRAINTS_FILE: '{{ tox_constraints_file }}'
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
tox_description: '{{ tox_description }}'
|
tox_description: '{{ tox_description }}'
|
||||||
tox_dir: '{{ tox_dir }}'
|
tox_dir: '{{ tox_dir }}'
|
||||||
tox_environment: '{{ tox_environment | combine(tox_constrain_env) }}'
|
tox_environment: '{{ tox_environment | combine(tox_constrain_env) }}'
|
||||||
tox_report_env: '{{ tox_report_env | combine(tox_constrain_env) }}'
|
|
||||||
|
|
||||||
|
|
||||||
- name: "{{ tox_description }}"
|
- name: "{{ tox_description }}"
|
||||||
@ -39,17 +38,6 @@
|
|||||||
- (run_tox.stdout_lines | length) > 0
|
- (run_tox.stdout_lines | length) > 0
|
||||||
|
|
||||||
|
|
||||||
- name: "generate test case report files"
|
|
||||||
shell:
|
|
||||||
chdir: "{{ tobiko_dir }}"
|
|
||||||
cmd: |
|
|
||||||
{{ tox_command }} -e report
|
|
||||||
register:
|
|
||||||
make_report
|
|
||||||
environment: '{{ tox_report_env | combine(tox_constrain_env) }}'
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
|
|
||||||
- name:
|
- name:
|
||||||
block:
|
block:
|
||||||
- name: "show test cases errors"
|
- name: "show test cases errors"
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
# Unit tests requirements
|
# Unit tests requirements
|
||||||
|
|
||||||
coverage!=4.4,>=4.0 # Apache-2.0
|
coverage!=4.4,>=4.0 # Apache-2.0
|
||||||
mock>=2.0 # BSD
|
junitxml>=0.7 # LGPL-3
|
||||||
testscenarios>=0.4 # Apache-2.0/BSD
|
mock>=2.0 # BSD
|
||||||
|
os-testr>=1.0 # Apache-2.0
|
||||||
|
python-subunit>=1.4 ; python_version >= '3.0' # Apache-2.0
|
||||||
|
python-subunit<1.4 ; python_version < '3.0' # Apache-2.0
|
||||||
|
stestr>=2.0 # Apache-2.0
|
||||||
|
0
tools/__init__.py
Normal file
0
tools/__init__.py
Normal file
95
tools/common.py
Normal file
95
tools/common.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
# Copyright 2018 Red Hat
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def get_logger(name):
|
||||||
|
module = sys.modules.get(name)
|
||||||
|
if module:
|
||||||
|
name = name_from_path(module.__file__)
|
||||||
|
return logging.getLogger(name)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_logging(main_script=None, level=logging.DEBUG):
|
||||||
|
main_script = main_script or sys.modules['__main__'].__file__
|
||||||
|
logging.basicConfig(
|
||||||
|
level=level,
|
||||||
|
stream=sys.stderr,
|
||||||
|
format='%(name)-s: %(levelname)-7s %(asctime)-15s | %(message)s')
|
||||||
|
return logging.getLogger(name=name_from_path(main_script))
|
||||||
|
|
||||||
|
|
||||||
|
def name_from_path(path):
|
||||||
|
return os.path.splitext(os.path.basename(path))[0]
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_path(path):
|
||||||
|
return os.path.realpath(os.path.expanduser(path))
|
||||||
|
|
||||||
|
|
||||||
|
def execute(command, *args, **kwargs):
|
||||||
|
capture_stdout = kwargs.pop('capture_stdout', True)
|
||||||
|
universal_newlines = kwargs.pop('universal_newlines', True)
|
||||||
|
|
||||||
|
if args or kwargs:
|
||||||
|
command = command.format(*args, **kwargs)
|
||||||
|
command = command.strip()
|
||||||
|
|
||||||
|
if capture_stdout:
|
||||||
|
execute_func = subprocess.check_output
|
||||||
|
else:
|
||||||
|
execute_func = subprocess.check_call
|
||||||
|
|
||||||
|
return execute_func(['/bin/bash', '-x', '-c', command],
|
||||||
|
shell=False, universal_newlines=universal_newlines)
|
||||||
|
|
||||||
|
|
||||||
|
def get_posargs(args=None):
|
||||||
|
if args is None:
|
||||||
|
args = sys.argv[1:]
|
||||||
|
return ' '.join(shlex.quote(s) for s in args)
|
||||||
|
|
||||||
|
|
||||||
|
def make_temp(*args, **kwargs):
|
||||||
|
fd, filename = tempfile.mkstemp(*args, **kwargs)
|
||||||
|
os.close(fd)
|
||||||
|
return filename
|
||||||
|
|
||||||
|
|
||||||
|
def make_dir(dirname):
|
||||||
|
if os.path.isdir(dirname):
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
LOG.debug("Create directory: '%s'", dirname)
|
||||||
|
os.makedirs(dirname)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def remove_file(filename):
|
||||||
|
if os.path.isfile(filename):
|
||||||
|
LOG.debug("Remove file: '%s'", filename)
|
||||||
|
os.unlink(filename)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
137
tools/run_tests.py
Normal file
137
tools/run_tests.py
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
# Copyright 2018 Red Hat
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
TOP_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||||
|
if TOP_DIR not in sys.path:
|
||||||
|
sys.path.insert(0, TOP_DIR)
|
||||||
|
|
||||||
|
from tools import common # noqa
|
||||||
|
|
||||||
|
LOG = common.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
# Output dirs
|
||||||
|
TOX_REPORT_DIR = common.normalize_path(
|
||||||
|
os.environ.get('TOX_REPORT_DIR', os.getcwd()))
|
||||||
|
|
||||||
|
TOX_REPORT_NAME = os.environ.get('TOX_REPORT_NAME', 'test_results')
|
||||||
|
TOX_REPORT_PREFIX = os.path.join(TOX_REPORT_DIR, TOX_REPORT_NAME)
|
||||||
|
|
||||||
|
TOX_REPORT_LOG = os.environ.get(
|
||||||
|
'TOX_REPORT_LOG', TOX_REPORT_PREFIX + '.log')
|
||||||
|
|
||||||
|
TOX_REPORT_SUBUNIT = os.environ.get(
|
||||||
|
'TOX_REPORT_SUBUNIT', TOX_REPORT_PREFIX + '.subunit')
|
||||||
|
|
||||||
|
TOX_REPORT_HTML = os.environ.get(
|
||||||
|
'TOX_REPORT_HTML', TOX_REPORT_PREFIX + '.html')
|
||||||
|
|
||||||
|
TOX_REPORT_XML = os.environ.get(
|
||||||
|
'TOX_REPORT_XML', TOX_REPORT_PREFIX + '.xml')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
common.setup_logging()
|
||||||
|
try:
|
||||||
|
succeeded = run_tests()
|
||||||
|
if succeeded:
|
||||||
|
LOG.info('SUCCEEDED')
|
||||||
|
else:
|
||||||
|
LOG.info('FAILED')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
LOG.exception('ERROR')
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
|
||||||
|
def run_tests():
|
||||||
|
cleanup_report_dir()
|
||||||
|
log_environ()
|
||||||
|
|
||||||
|
succeeded = True
|
||||||
|
try:
|
||||||
|
run_test_cases()
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
succeeded = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
log_tests_results()
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
if succeeded:
|
||||||
|
raise
|
||||||
|
|
||||||
|
make_subunit_file()
|
||||||
|
make_html_file()
|
||||||
|
try:
|
||||||
|
make_xml_file()
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
if succeeded:
|
||||||
|
raise
|
||||||
|
|
||||||
|
return succeeded
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup_report_dir():
|
||||||
|
for report_file in [TOX_REPORT_LOG, TOX_REPORT_SUBUNIT, TOX_REPORT_HTML,
|
||||||
|
TOX_REPORT_XML]:
|
||||||
|
if not common.make_dir(os.path.dirname(report_file)):
|
||||||
|
common.remove_file(report_file)
|
||||||
|
|
||||||
|
|
||||||
|
def log_environ():
|
||||||
|
common.execute('env | sort >> "{log_file}"', log_file=TOX_REPORT_LOG,
|
||||||
|
capture_stdout=False)
|
||||||
|
|
||||||
|
|
||||||
|
def log_tests_results():
|
||||||
|
common.execute('stestr last --all-attachments >> "{log_file}"',
|
||||||
|
log_file=TOX_REPORT_LOG,
|
||||||
|
capture_stdout=False)
|
||||||
|
|
||||||
|
|
||||||
|
def run_test_cases():
|
||||||
|
common.execute('stestr run --slowest {posargs}',
|
||||||
|
posargs=common.get_posargs(),
|
||||||
|
capture_stdout=False)
|
||||||
|
|
||||||
|
|
||||||
|
def make_subunit_file():
|
||||||
|
common.execute('stestr last --subunit > "{subunit_file}"',
|
||||||
|
subunit_file=TOX_REPORT_SUBUNIT,
|
||||||
|
capture_stdout=False)
|
||||||
|
|
||||||
|
|
||||||
|
def make_html_file():
|
||||||
|
common.execute('subunit2html "{subunit_file}" "{html_file}"',
|
||||||
|
subunit_file=TOX_REPORT_SUBUNIT,
|
||||||
|
html_file=TOX_REPORT_HTML,
|
||||||
|
capture_stdout=False)
|
||||||
|
|
||||||
|
|
||||||
|
def make_xml_file():
|
||||||
|
common.execute('subunit2junitxml "{subunit_file}" -o "{xml_file}"',
|
||||||
|
subunit_file=TOX_REPORT_SUBUNIT,
|
||||||
|
xml_file=TOX_REPORT_XML,
|
||||||
|
capture_stdout=False)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright 2018 Red Hat
|
# Copyright 2020 Red Hat
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@ -13,29 +13,26 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
TOP_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||||
|
if TOP_DIR not in sys.path:
|
||||||
|
sys.path.insert(0, TOP_DIR)
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
from tools import common # noqa
|
||||||
|
|
||||||
|
LOG = common.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
setup_logging()
|
common.setup_logging()
|
||||||
add_tobiko_plugin()
|
add_tobiko_plugin()
|
||||||
ensure_workspace()
|
ensure_workspace()
|
||||||
copy_inventory()
|
copy_inventory()
|
||||||
|
|
||||||
|
|
||||||
def setup_logging(level=logging.DEBUG):
|
|
||||||
logging.basicConfig(
|
|
||||||
level=level,
|
|
||||||
stream=sys.stderr,
|
|
||||||
format='%(name)-s: %(levelname)-7s %(asctime)-15s | %(message)s')
|
|
||||||
|
|
||||||
|
|
||||||
def add_tobiko_plugin(path=None):
|
def add_tobiko_plugin(path=None):
|
||||||
path = path or os.environ.get('IR_TOBIKO_PLUGIN')
|
path = path or os.environ.get('IR_TOBIKO_PLUGIN')
|
||||||
if path:
|
if path:
|
||||||
@ -43,19 +40,19 @@ def add_tobiko_plugin(path=None):
|
|||||||
|
|
||||||
|
|
||||||
def add_plugin(name, path):
|
def add_plugin(name, path):
|
||||||
path = normalize_path(path)
|
path = common.normalize_path(path)
|
||||||
if not os.path.isdir(path):
|
if not os.path.isdir(path):
|
||||||
message = ("invalid plug-in '{}' directory: '{}'").format(name, path)
|
message = ("invalid plug-in '{}' directory: '{}'").format(name, path)
|
||||||
raise RuntimeError(message)
|
raise RuntimeError(message)
|
||||||
|
|
||||||
remove_plugin(name)
|
remove_plugin(name)
|
||||||
execute('ir plugin add "{}"', path)
|
common.execute('ir plugin add "{}"', path)
|
||||||
LOG.info("plug-in '%s' added from path '%s'", name, path)
|
LOG.info("plug-in '%s' added from path '%s'", name, path)
|
||||||
|
|
||||||
|
|
||||||
def remove_plugin(name):
|
def remove_plugin(name):
|
||||||
try:
|
try:
|
||||||
execute('ir plugin remove "{}"', name)
|
common.execute('ir plugin remove "{}"', name)
|
||||||
except subprocess.CalledProcessError as ex:
|
except subprocess.CalledProcessError as ex:
|
||||||
LOG.debug("plug-in '%s' not removed: %s", name, ex)
|
LOG.debug("plug-in '%s' not removed: %s", name, ex)
|
||||||
return False
|
return False
|
||||||
@ -68,11 +65,11 @@ def ensure_workspace(filename=None):
|
|||||||
filename = (filename or
|
filename = (filename or
|
||||||
os.environ.get('IR_WORKSPACE_FILE') or
|
os.environ.get('IR_WORKSPACE_FILE') or
|
||||||
'workspace.tgz')
|
'workspace.tgz')
|
||||||
filename = normalize_path(filename)
|
filename = common.normalize_path(filename)
|
||||||
workspace = name_from_path(filename)
|
workspace = common.name_from_path(filename)
|
||||||
if os.path.isfile(filename):
|
if os.path.isfile(filename):
|
||||||
try:
|
try:
|
||||||
execute('ir workspace import "{}"', filename)
|
common.execute('ir workspace import "{}"', filename)
|
||||||
except subprocess.CalledProcessError as ex:
|
except subprocess.CalledProcessError as ex:
|
||||||
LOG.debug("workspace file '%s' not imported: %s", filename, ex)
|
LOG.debug("workspace file '%s' not imported: %s", filename, ex)
|
||||||
else:
|
else:
|
||||||
@ -82,14 +79,14 @@ def ensure_workspace(filename=None):
|
|||||||
LOG.debug("workspace file not found: '%s'", filename)
|
LOG.debug("workspace file not found: '%s'", filename)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
execute('ir workspace checkout "{}"', workspace)
|
common.execute('ir workspace checkout "{}"', workspace)
|
||||||
except subprocess.CalledProcessError as ex:
|
except subprocess.CalledProcessError as ex:
|
||||||
LOG.debug("workspace '%s' not checked out: %s", workspace, ex)
|
LOG.debug("workspace '%s' not checked out: %s", workspace, ex)
|
||||||
else:
|
else:
|
||||||
LOG.info("workspace '%s' checked out", workspace)
|
LOG.info("workspace '%s' checked out", workspace)
|
||||||
return
|
return
|
||||||
|
|
||||||
execute('infrared workspace checkout --create "{}"', workspace)
|
common.execute('infrared workspace checkout --create "{}"', workspace)
|
||||||
LOG.info("workspace '%s' created", workspace)
|
LOG.info("workspace '%s' created", workspace)
|
||||||
|
|
||||||
|
|
||||||
@ -101,7 +98,7 @@ def copy_inventory(filename=None):
|
|||||||
LOG.debug('inventary file not found: %r', filename)
|
LOG.debug('inventary file not found: %r', filename)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
dest_file = execute('ir workspace inventory')
|
dest_file = common.execute('ir workspace inventory')
|
||||||
LOG.debug("got workspace inventory file: '%s'", dest_file)
|
LOG.debug("got workspace inventory file: '%s'", dest_file)
|
||||||
|
|
||||||
dest_dir = os.path.basename(dest_file)
|
dest_dir = os.path.basename(dest_file)
|
||||||
@ -109,27 +106,10 @@ def copy_inventory(filename=None):
|
|||||||
os.makedirs(dest_dir)
|
os.makedirs(dest_dir)
|
||||||
LOG.info("directory created: '%s'", dest_dir)
|
LOG.info("directory created: '%s'", dest_dir)
|
||||||
|
|
||||||
execute('cp {} {}', filename, dest_file)
|
common.execute('cp {} {}', filename, dest_file)
|
||||||
LOG.info("inventary file '%s' copied to '%s'", filename, dest_file)
|
LOG.info("inventary file '%s' copied to '%s'", filename, dest_file)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def normalize_path(path):
|
|
||||||
return os.path.realpath(os.path.expanduser(path))
|
|
||||||
|
|
||||||
|
|
||||||
def execute(command, *args, **kwargs):
|
|
||||||
if args or kwargs:
|
|
||||||
command = command.format(*args, **kwargs)
|
|
||||||
LOG.debug("execute command: '%s'", command)
|
|
||||||
return subprocess.check_output(command, shell=True,
|
|
||||||
universal_newlines=True)
|
|
||||||
|
|
||||||
|
|
||||||
def name_from_path(path):
|
|
||||||
return os.path.splitext(os.path.basename(path))[0]
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
LOG = logging.getLogger(name_from_path(__file__))
|
|
||||||
main()
|
main()
|
||||||
|
230
tox.ini
230
tox.ini
@ -1,59 +1,63 @@
|
|||||||
[tox]
|
[tox]
|
||||||
|
|
||||||
envlist = bindep,linters,cover
|
envlist = bindep,linters,py3
|
||||||
minversion = 3.4.0
|
minversion = 3.8.0
|
||||||
|
|
||||||
|
|
||||||
# --- unit test environments -------------------------------------------------
|
# --- unit test environments -------------------------------------------------
|
||||||
|
|
||||||
[base]
|
|
||||||
|
|
||||||
deps =
|
|
||||||
-c{env:UPPER_CONSTRAINTS_FILE}
|
|
||||||
-r{toxinidir}/requirements.txt
|
|
||||||
passenv =
|
|
||||||
PS1
|
|
||||||
TOBIKO_*
|
|
||||||
setenv =
|
|
||||||
OS_LOG_CAPTURE={env:OS_LOG_CAPTURE:true}
|
|
||||||
OS_STDOUT_CAPTURE={env:OS_STDOUT_CAPTURE:true}
|
|
||||||
OS_STDERR_CAPTURE={env:OS_STDERR_CAPTURE:true}
|
|
||||||
PS1=[tobiko@{envname}] {env:PS1:}
|
|
||||||
PYTHON={env:PYTHON:python3}
|
|
||||||
PYTHONWARNINGS=ignore::Warning,{env:PYTHONWARNINGS:}
|
|
||||||
TOBIKO_PREVENT_CREATE={env:TOBIKO_PREVENT_CREATE:false}
|
|
||||||
VIRTUAL_ENV={envdir}
|
|
||||||
UPPER_CONSTRAINTS_FILE={env:UPPER_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt}
|
|
||||||
commands =
|
|
||||||
stestr run {posargs}
|
|
||||||
|
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
|
|
||||||
usedevelop = True
|
usedevelop = True
|
||||||
deps =
|
deps =
|
||||||
{[base]deps}
|
-c{env:TOX_CONSTRAINTS_FILE}
|
||||||
|
-r{toxinidir}/requirements.txt
|
||||||
-r{toxinidir}/test-requirements.txt
|
-r{toxinidir}/test-requirements.txt
|
||||||
passenv = {[base]passenv}
|
passenv =
|
||||||
|
JENKINS_*
|
||||||
|
PS1
|
||||||
|
OS_*
|
||||||
|
TOBIKO_*
|
||||||
|
TOX_*
|
||||||
setenv =
|
setenv =
|
||||||
{[base]setenv}
|
OS_LOG_CAPTURE = {env:OS_LOG_CAPTURE:true}
|
||||||
OS_TEST_PATH={toxinidir}/tobiko/tests/unit
|
OS_STDOUT_CAPTURE = {env:OS_STDOUT_CAPTURE:true}
|
||||||
commands = {[base]commands}
|
OS_STDERR_CAPTURE = {env:OS_STDERR_CAPTURE:true}
|
||||||
|
OS_TEST_PATH = {toxinidir}/tobiko/tests/unit
|
||||||
|
PS1 = [tobiko@{envname}] {env:PS1:}
|
||||||
|
PYTHONWARNINGS = ignore::Warning,{env:PYTHONWARNINGS:}
|
||||||
|
RUN_TESTS_EXTRA_ARGS =
|
||||||
|
TOBIKO_PREVENT_CREATE = {env:TOBIKO_PREVENT_CREATE:false}
|
||||||
|
TOX_REPORT_NAME = {env:TOX_REPORT_NAME:test_results}
|
||||||
|
TOX_REPORT_DIR = {env:TOX_REPORT_DIR:{toxinidir}/report/{envname}}
|
||||||
|
TOX_CONSTRAINTS_FILE = {env:TOX_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt}
|
||||||
|
VIRTUAL_ENV = {envdir}
|
||||||
|
commands =
|
||||||
|
{envpython} {toxinidir}/tools/run_tests.py {env:RUN_TESTS_EXTRA_ARGS} {posargs}
|
||||||
|
|
||||||
|
|
||||||
|
[testenv:py3]
|
||||||
|
|
||||||
|
basepython = {env:TOX_PYTHON:python3}
|
||||||
|
envdir = {toxworkdir}/py3
|
||||||
|
|
||||||
|
|
||||||
[testenv:cover]
|
[testenv:cover]
|
||||||
|
|
||||||
basepython = python3
|
basepython = {[testenv:py3]basepython}
|
||||||
|
envdir = {[testenv:py3]envdir}
|
||||||
setenv =
|
setenv =
|
||||||
{[testenv]setenv}
|
{[testenv]setenv}
|
||||||
PYTHON=coverage run --parallel-mode
|
PYTHON = coverage run --parallel-mode
|
||||||
|
RUN_TESTS_EXTRA_ARGS = --no-subunit-trace
|
||||||
|
TOX_COVER_DIR={env:TOX_COVER_DIR:{toxinidir}/cover}
|
||||||
commands =
|
commands =
|
||||||
find . -type f -name ".coverage.*" -delete
|
find . -type f -name ".coverage.*" -delete
|
||||||
coverage erase
|
coverage erase
|
||||||
stestr run --no-subunit-trace {posargs}
|
{[testenv]commands}
|
||||||
coverage combine
|
coverage combine
|
||||||
coverage html -d cover
|
coverage html -d "{env:TOX_COVER_DIR}"
|
||||||
coverage xml -o cover/coverage.xml
|
coverage xml -o "{env:TOX_COVER_DIR}/cover/coverage.xml"
|
||||||
coverage report --fail-under=40 --skip-covered
|
coverage report --fail-under=40 --skip-covered
|
||||||
find . -type f -name ".coverage.*" -delete
|
find . -type f -name ".coverage.*" -delete
|
||||||
whitelist_externals =
|
whitelist_externals =
|
||||||
@ -62,10 +66,9 @@ whitelist_externals =
|
|||||||
|
|
||||||
# --- static analisys environments -------------------------------------------
|
# --- static analisys environments -------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
[testenv:pep8]
|
[testenv:pep8]
|
||||||
|
|
||||||
basepython = {env:PYTHON:python3}
|
basepython = python3
|
||||||
deps =
|
deps =
|
||||||
{[testenv]deps}
|
{[testenv]deps}
|
||||||
-r{toxinidir}/linters-requirements.txt
|
-r{toxinidir}/linters-requirements.txt
|
||||||
@ -91,6 +94,7 @@ commands =
|
|||||||
pylint -j0 --max-line-length=80 -E -e W,E \
|
pylint -j0 --max-line-length=80 -E -e W,E \
|
||||||
-d unused-import,broad-except,fixme tobiko
|
-d unused-import,broad-except,fixme tobiko
|
||||||
|
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
# H106: Don't put vim configuration in source files
|
# H106: Don't put vim configuration in source files
|
||||||
# H203: Use assertIs(Not)None to check for None
|
# H203: Use assertIs(Not)None to check for None
|
||||||
@ -106,76 +110,68 @@ import-order-style = pep8
|
|||||||
|
|
||||||
# --- integration test environments ------------------------------------------
|
# --- integration test environments ------------------------------------------
|
||||||
|
|
||||||
[openstack]
|
[integration]
|
||||||
|
|
||||||
basepython = {env:PYTHON:python3}
|
basepython = {[testenv:py3]basepython}
|
||||||
deps =
|
envdir = {[testenv:py3]envdir}
|
||||||
{[base]deps}
|
|
||||||
passenv =
|
passenv =
|
||||||
{[base]passenv}
|
{[testenv]passenv}
|
||||||
*_proxy
|
*_proxy
|
||||||
OS_*
|
setenv = {[testenv]setenv}
|
||||||
setenv =
|
|
||||||
{[base]setenv}
|
|
||||||
ANSIBLE_CONFIG={env:ANSIBLE_CONFIG:{toxinidir}/ansible.cfg}
|
|
||||||
commands = {[base]commands}
|
|
||||||
|
|
||||||
|
|
||||||
[testenv:functional]
|
|
||||||
|
|
||||||
basepython = {[openstack]basepython}
|
|
||||||
deps = {[openstack]deps}
|
|
||||||
passenv = {[openstack]passenv}
|
|
||||||
setenv =
|
|
||||||
{[openstack]setenv}
|
|
||||||
OS_TEST_PATH={toxinidir}/tobiko/tests/functional
|
|
||||||
|
|
||||||
|
|
||||||
[testenv:scenario]
|
|
||||||
|
|
||||||
basepython = {[openstack]basepython}
|
|
||||||
deps = {[openstack]deps}
|
|
||||||
passenv = {[openstack]passenv}
|
|
||||||
setenv =
|
|
||||||
{[openstack]setenv}
|
|
||||||
OS_TEST_PATH={toxinidir}/tobiko/tests/scenario
|
|
||||||
|
|
||||||
|
|
||||||
[testenv:neutron]
|
|
||||||
|
|
||||||
basepython = {[openstack]basepython}
|
|
||||||
envdir = {toxworkdir}/scenario
|
|
||||||
deps = {[testenv:scenario]deps}
|
|
||||||
passenv = {[testenv:scenario]passenv}
|
|
||||||
setenv =
|
|
||||||
{[testenv:scenario]setenv}
|
|
||||||
OS_TEST_PATH={toxinidir}/tobiko/tests/scenario/neutron
|
|
||||||
|
|
||||||
|
|
||||||
[testenv:faults]
|
|
||||||
|
|
||||||
basepython = {[openstack]basepython}
|
|
||||||
envdir = {toxworkdir}/scenario
|
|
||||||
deps = {[testenv:scenario]deps}
|
|
||||||
passenv = {[testenv:scenario]passenv}
|
|
||||||
setenv =
|
|
||||||
{[testenv:scenario]setenv}
|
|
||||||
OS_TEST_PATH={toxinidir}/tobiko/tests/faults
|
|
||||||
commands =
|
|
||||||
stestr run --serial {posargs}
|
|
||||||
|
|
||||||
|
|
||||||
[testenv:venv]
|
[testenv:venv]
|
||||||
|
|
||||||
basepython = {[openstack]basepython}
|
basepython = {[integration]basepython}
|
||||||
envdir = {toxworkdir}/scenario
|
envdir = {[integration]envdir}
|
||||||
deps = {[testenv:scenario]deps}
|
passenv = {[integration]passenv}
|
||||||
passenv = {[testenv:scenario]passenv}
|
|
||||||
setenv = {[testenv:scenario]setenv}
|
|
||||||
whitelist_externals = *
|
whitelist_externals = *
|
||||||
commands = {posargs:bash}
|
commands = {posargs:bash}
|
||||||
|
|
||||||
|
|
||||||
|
[testenv:functional]
|
||||||
|
|
||||||
|
basepython = {[integration]basepython}
|
||||||
|
envdir = {[integration]envdir}
|
||||||
|
passenv = {[integration]passenv}
|
||||||
|
setenv =
|
||||||
|
{[integration]setenv}
|
||||||
|
OS_TEST_PATH = {toxinidir}/tobiko/tests/functional
|
||||||
|
|
||||||
|
|
||||||
|
[testenv:scenario]
|
||||||
|
|
||||||
|
basepython = {[integration]basepython}
|
||||||
|
envdir = {[integration]envdir}
|
||||||
|
passenv = {[integration]passenv}
|
||||||
|
setenv =
|
||||||
|
{[integration]setenv}
|
||||||
|
OS_TEST_PATH = {toxinidir}/tobiko/tests/scenario
|
||||||
|
|
||||||
|
|
||||||
|
[testenv:neutron]
|
||||||
|
|
||||||
|
basepython = {[integration]basepython}
|
||||||
|
envdir = {[integration]envdir}
|
||||||
|
passenv = {[integration]passenv}
|
||||||
|
setenv =
|
||||||
|
{[integration]setenv}
|
||||||
|
OS_TEST_PATH = {toxinidir}/tobiko/tests/scenario/neutron
|
||||||
|
|
||||||
|
|
||||||
|
[testenv:faults]
|
||||||
|
|
||||||
|
basepython = {[integration]basepython}
|
||||||
|
envdir = {[integration]envdir}
|
||||||
|
passenv = {[integration]passenv}
|
||||||
|
setenv =
|
||||||
|
{[integration]setenv}
|
||||||
|
OS_TEST_PATH = {toxinidir}/tobiko/tests/faults
|
||||||
|
RUN_TESTS_EXTRA_ARGS = --serial
|
||||||
|
|
||||||
|
|
||||||
|
# --- CI workflow test environments -------------------------------------------
|
||||||
|
|
||||||
[testenv:infrared]
|
[testenv:infrared]
|
||||||
|
|
||||||
# On RedHat Linux must use the default unversioned python because of dependency on native SELinux
|
# On RedHat Linux must use the default unversioned python because of dependency on native SELinux
|
||||||
@ -189,43 +185,40 @@ whitelist_externals =
|
|||||||
rm
|
rm
|
||||||
|
|
||||||
deps =
|
deps =
|
||||||
-c{env:UPPER_CONSTRAINTS_FILE}
|
-c{env:TOX_CONSTRAINTS_FILE}
|
||||||
-rinfrared-requirements.txt
|
-rinfrared-requirements.txt
|
||||||
passenv =
|
passenv =
|
||||||
{[testenv:venv]passenv}
|
{[testenv]passenv}
|
||||||
ANSIBLE_*
|
ANSIBLE_*
|
||||||
IR_*
|
IR_*
|
||||||
PYTHON
|
|
||||||
TERM
|
TERM
|
||||||
|
|
||||||
setenv =
|
setenv =
|
||||||
{[testenv:venv]setenv}
|
{[testenv]setenv}
|
||||||
ANSIBLE_CONFIG={env:ANSIBLE_CONFIG:{toxinidir}/ansible.cfg}
|
ANSIBLE_CONFIG = {env:ANSIBLE_CONFIG:{toxinidir}/ansible.cfg}
|
||||||
ANSIBLE_INVENTORY={env:ANSIBLE_INVENTORY:{toxinidir}/ansible_hosts}
|
ANSIBLE_INVENTORY = {env:ANSIBLE_INVENTORY:{toxinidir}/ansible_hosts}
|
||||||
IR_HOME={env:IR_HOME:{envdir}/home/infrared}
|
IR_HOME = {env:IR_HOME:{envdir}/home/infrared}
|
||||||
IR_TOBIKO_PLUGIN={env:IR_TOBIKO_PLUGIN:{toxinidir}/infrared_plugin}
|
IR_TOBIKO_PLUGIN = {env:IR_TOBIKO_PLUGIN:{toxinidir}/infrared_plugin}
|
||||||
IR_WORKSPACE_FILE={env:IR_WORKSPACE_FILE:{toxinidir}/workspace.tgz}
|
IR_WORKSPACE_FILE = {env:IR_WORKSPACE_FILE:{toxinidir}/workspace.tgz}
|
||||||
|
|
||||||
commands_pre =
|
commands_pre =
|
||||||
{envpython} {toxinidir}/tools/setup_infrared.py
|
{envpython} {toxinidir}/tools/setup_infrared.py
|
||||||
|
|
||||||
commands =
|
commands =
|
||||||
rm -fR '{toxinidir}/test_results'
|
ir tobiko --tobiko-src-dir '{toxinidir}' \
|
||||||
ir tobiko \
|
--collect-dir '{env:TOX_REPORT_DIR}' \
|
||||||
--tobiko-src-dir {toxinidir} \
|
--upper-constraints '{env:TOX_CONSTRAINTS_FILE}' \
|
||||||
--collect-dir '{toxinidir}/test_results' \
|
{posargs}
|
||||||
--upper-constraints '{env:UPPER_CONSTRAINTS_FILE}' \
|
|
||||||
{posargs}
|
|
||||||
|
|
||||||
|
|
||||||
# --- documentation environments ----------------------------------------------
|
# --- documentation environments ----------------------------------------------
|
||||||
|
|
||||||
[docs]
|
[docs]
|
||||||
|
|
||||||
basepython = {env:PYTHON:python3}
|
basepython = {[testenv:py3]basepython}
|
||||||
envdir = {toxworkdir}/docs
|
envdir = {toxworkdir}/docs
|
||||||
deps =
|
deps =
|
||||||
{[base]deps}
|
{[testenv]deps}
|
||||||
-r{toxinidir}/doc/requirements.txt
|
-r{toxinidir}/doc/requirements.txt
|
||||||
|
|
||||||
|
|
||||||
@ -257,20 +250,9 @@ commands =
|
|||||||
|
|
||||||
# --- CI report environments --------------------------------------------------
|
# --- CI report environments --------------------------------------------------
|
||||||
|
|
||||||
[testenv:report]
|
|
||||||
|
|
||||||
basepython = {env:PYTHON:python3}
|
|
||||||
usedevelop = false
|
|
||||||
skipdist = true
|
|
||||||
skip_install = true
|
|
||||||
deps = -r {toxinidir}/report-requirements.txt
|
|
||||||
passenv = {[base]passenv}
|
|
||||||
setenv = {[base]setenv}
|
|
||||||
commands = {toxinidir}/tools/ci/make_report
|
|
||||||
|
|
||||||
|
|
||||||
[testenv:bindep]
|
[testenv:bindep]
|
||||||
basepython = {env:PYTHON:python3}
|
basepython = {[testenv:py3]basepython}
|
||||||
# Do not install any requirements. We want this to be fast and work even if
|
# 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
|
# system dependencies are missing, since it's used to tell you what system
|
||||||
# dependencies are missing! This also means that bindep must be installed
|
# dependencies are missing! This also means that bindep must be installed
|
||||||
|
Loading…
Reference in New Issue
Block a user