Add usage of namedtuples for run and tests status

To get possibility to change status in one place,
add consts.py with enum usage.

Closes-Bug: #1404866

Change-Id: I6a7873bc2de919ed4cc99dcfe8e3e1febda606c0
This commit is contained in:
Tatyana Leontovich 2016-03-30 21:18:46 +03:00
parent db8d83701a
commit ff9a20a192
5 changed files with 82 additions and 41 deletions

43
fuel_plugin/consts.py Normal file
View File

@ -0,0 +1,43 @@
# Copyright 2016 Mirantis, Inc.
#
# 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 collections
def Enum(*values, **kwargs):
names = kwargs.get('names')
if names:
return collections.namedtuple('Enum', names)(*values)
return collections.namedtuple('Enum', values)(*values)
TESTRUN_STATUSES = Enum(
'stopped',
'restarted',
'finished',
'running'
)
TEST_STATUSES = Enum(
'stopped',
'restarted',
'finished',
'running',
'error',
'skipped',
'success',
'failure',
'wait_running',
'disabled'
)

View File

@ -22,6 +22,7 @@ try:
except ImportError:
from oslo_config import cfg
from fuel_plugin import consts
from fuel_plugin.ostf_adapter.logger import ResultsLogger
from fuel_plugin.ostf_adapter.nose_plugin import nose_storage_plugin
from fuel_plugin.ostf_adapter.nose_plugin import nose_test_runner
@ -114,7 +115,7 @@ class NoseDriver(object):
except Exception:
LOG.exception('Test run ID: %s', test_run_id)
finally:
updated_data = {'status': 'finished',
updated_data = {'status': consts.TESTRUN_STATUSES.finished,
'pid': None}
models.TestRun.update_test_run(

View File

@ -22,6 +22,7 @@ try:
except ImportError:
from oslo_config import cfg
from fuel_plugin import consts
from fuel_plugin.ostf_adapter.nose_plugin import nose_utils
from fuel_plugin.ostf_adapter.storage import models
@ -72,7 +73,7 @@ class StoragePlugin(plugins.Plugin):
test_id,
data
)
if data['status'] != 'running':
if data['status'] != consts.TEST_STATUSES.running:
test_name = nose_utils.get_description(test)["title"]
self.results_log.log_results(
test_id,
@ -93,11 +94,11 @@ class StoragePlugin(plugins.Plugin):
if err:
exc_type, exc_value, exc_traceback = err
if not status == 'error':
if not status == consts.TEST_STATUSES.error:
data['step'], data['message'] = \
nose_utils.format_failure_message(exc_value)
if status != 'skipped':
if status != consts.TEST_STATUSES.skipped:
data['traceback'] = nose_utils.format_exception(err)
tests_to_update = nose_utils.get_tests_to_update(test)
@ -107,26 +108,30 @@ class StoragePlugin(plugins.Plugin):
self.session.commit()
def addSuccess(self, test, capt=None):
self._add_message(test, status='success')
self._add_message(test, status=consts.TEST_STATUSES.success)
def addFailure(self, test, err):
LOG.error('%s', test.id(), exc_info=err)
self._add_message(test, err=err, status='failure')
self._add_message(
test, err=err, status=consts.TEST_STATUSES.failure)
def addError(self, test, err):
if err[0] is AssertionError:
LOG.error('%s', test.id(), exc_info=err)
self._add_message(test, err=err, status='failure')
self._add_message(
test, err=err, status=consts.TEST_STATUSES.failure)
elif issubclass(err[0], plugins.skip.SkipTest):
LOG.warning('%s is skipped', test.id())
self._add_message(test, err=err, status='skipped')
self._add_message(
test, err=err, status=consts.TEST_STATUSES.skipped)
else:
LOG.error('%s', test.id(), exc_info=err)
self._add_message(test, err=err, status='error')
self._add_message(
test, err=err, status=consts.TEST_STATUSES.error)
def beforeTest(self, test):
self._start_time = time.time()
self._add_message(test, status='running')
self._add_message(test, status=consts.TEST_STATUSES.running)
def describeTest(self, test):
return test.test._testMethodDoc

View File

@ -22,6 +22,7 @@ from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import joinedload, relationship, object_mapper
from fuel_plugin import consts
from fuel_plugin.ostf_adapter import nose_plugin
from fuel_plugin.ostf_adapter.storage import engine
from fuel_plugin.ostf_adapter.storage import fields
@ -115,17 +116,6 @@ class Test(BASE):
__tablename__ = 'tests'
STATES = (
'wait_running',
'running',
'failure',
'success',
'error',
'stopped',
'disabled',
'skipped'
)
id = sa.Column(sa.Integer(), primary_key=True)
name = sa.Column(sa.String(512))
title = sa.Column(sa.String(512))
@ -133,7 +123,7 @@ class Test(BASE):
duration = sa.Column(sa.String(512))
message = sa.Column(sa.Text())
traceback = sa.Column(sa.Text())
status = sa.Column(sa.Enum(*STATES, name='test_states'))
status = sa.Column(sa.Enum(consts.TEST_STATUSES, name='test_states'))
step = sa.Column(sa.Integer())
time_taken = sa.Column(sa.Float())
meta = sa.Column(fields.JsonField())
@ -178,15 +168,19 @@ class Test(BASE):
update(data, synchronize_session='fetch')
@classmethod
def update_running_tests(cls, session, test_run_id, status='stopped'):
def update_running_tests(cls, session, test_run_id,
status=consts.TEST_STATUSES.stopped):
session.query(cls). \
filter(cls.test_run_id == test_run_id,
cls.status.in_(('running', 'wait_running'))). \
cls.status.in_(
(consts.TEST_STATUSES.running,
consts.TEST_STATUSES.wait_running))). \
update({'status': status}, synchronize_session='fetch')
@classmethod
def update_test_run_tests(cls, session, test_run_id,
tests_names, status='wait_running'):
tests_names,
status=consts.TEST_STATUSES.wait_running):
session.query(cls). \
filter(cls.name.in_(tests_names),
cls.test_run_id == test_run_id). \
@ -205,9 +199,9 @@ class Test(BASE):
setattr(new_test, column.key, getattr(self, column.key))
new_test.test_run_id = test_run.id
if predefined_tests and new_test.name not in predefined_tests:
new_test.status = 'disabled'
new_test.status = consts.TEST_STATUSES.disabled
else:
new_test.status = 'wait_running'
new_test.status = consts.TEST_STATUSES.wait_running
return new_test
@ -215,14 +209,10 @@ class TestRun(BASE):
__tablename__ = 'test_runs'
STATES = (
'running',
'finished'
)
id = sa.Column(sa.Integer(), primary_key=True)
cluster_id = sa.Column(sa.Integer(), nullable=False)
status = sa.Column(sa.Enum(*STATES, name='test_run_states'),
status = sa.Column(sa.Enum(consts.TESTRUN_STATUSES,
name='test_run_states'),
nullable=False)
meta = sa.Column(fields.JsonField())
started_at = sa.Column(sa.DateTime, default=datetime.datetime.utcnow)
@ -262,10 +252,10 @@ class TestRun(BASE):
@property
def enabled_tests(self):
return [test.name for test
in self.tests if test.status != 'disabled']
in self.tests if test.status != consts.TEST_STATUSES.disabled]
def is_finished(self):
return self.status == 'finished'
return self.status == consts.TESTRUN_STATUSES.finished
@property
def frontend(self):
@ -284,7 +274,8 @@ class TestRun(BASE):
return test_run_data
@classmethod
def add_test_run(cls, session, test_set, cluster_id, status='running',
def add_test_run(cls, session, test_set, cluster_id,
status=consts.TESTRUN_STATUSES.running,
tests=None):
"""Creates new test_run object with given data
and makes copy of tests that will be bound
@ -350,7 +341,7 @@ class TestRun(BASE):
@classmethod
def update_test_run(cls, session, test_run_id, updated_data):
if updated_data.get('status') in ['finished']:
if updated_data.get('status') in [consts.TESTRUN_STATUSES.finished]:
updated_data['ended_at'] = datetime.datetime.utcnow()
session.query(cls). \
@ -392,7 +383,7 @@ class TestRun(BASE):
self.cluster_id):
plugin = nose_plugin.get_plugin(self.test_set.driver)
self.update('running')
self.update(consts.TEST_STATUSES.running)
if tests:
Test.update_test_run_tests(
session, self.id, tests)
@ -409,5 +400,5 @@ class TestRun(BASE):
killed = plugin.kill(self)
if killed:
Test.update_running_tests(
session, self.id, status='stopped')
session, self.id, status=consts.TEST_STATUSES.stopped)
return self.frontend

View File

@ -29,6 +29,7 @@ from pecan import rest
from sqlalchemy import func
from sqlalchemy.orm import joinedload
from fuel_plugin import consts
from fuel_plugin.ostf_adapter import mixins
from fuel_plugin.ostf_adapter.storage import models
@ -190,9 +191,9 @@ class TestrunsController(BaseRestController):
test_run = models.TestRun.get_test_run(request.session,
test_run['id'])
if status == 'stopped':
if status == consts.TESTRUN_STATUSES.stopped:
data.append(test_run.stop(request.session))
elif status == 'restarted':
elif status == consts.TESTRUN_STATUSES.restarted:
data.append(test_run.restart(request.session,
cfg.CONF.adapter.dbpath,
ostf_os_access_creds,