Skip to content

Commit

Permalink
Merge pull request #86 from gregoil/save_state_to_tests
Browse files Browse the repository at this point in the history
Move save state to the tests
  • Loading branch information
UnDarkle committed Aug 16, 2018
2 parents 18cbb66 + 1b47567 commit 56fcfd8
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 154 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from setuptools import setup, find_packages

__version__ = "3.2.2"
__version__ = "3.3.0"

result_handlers = [
"db = rotest.core.result.handlers.db_handler:DBHandler",
Expand Down
73 changes: 69 additions & 4 deletions src/rotest/core/abstract_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@
# pylint: disable=too-many-arguments,too-many-locals,broad-except
# pylint: disable=dangerous-default-value,access-member-before-definition
# pylint: disable=bare-except,protected-access,too-many-instance-attributes
import os
import sys
import unittest
from bdb import BdbQuit
from functools import wraps
from itertools import count

from ipdbugger import debug
from attrdict import AttrDict

from rotest.core.models.case_data import TestOutcome
from rotest.management.base_resource import BaseResource
from rotest.management.client.manager import ResourceRequest
from rotest.management.client.manager import ClientResourceManager


request = ResourceRequest


Expand Down Expand Up @@ -46,14 +49,14 @@ class AbstractTest(unittest.TestCase):
TEARDOWN_METHOD_NAME = 'tearDown'

TIMEOUT = 1800 # 30 minutes
SETUP_METHOD_NAME = 'setUp'
TEARDOWN_METHOD_NAME = 'tearDown'

resources = ()

TAGS = []
IS_COMPLEX = False

STATE_DIR_NAME = "state"

def __init__(self, indexer=count(), methodName='runTest', save_state=True,
force_initialize=False, config=None, parent=None,
enable_debug=True, resource_manager=None, skip_init=False):
Expand Down Expand Up @@ -198,7 +201,6 @@ def request_resources(self, resources_to_request, use_previous=False):
config=self.config,
skip_init=self.skip_init,
use_previous=use_previous,
save_state=self.save_state,
base_work_dir=self.work_dir,
requests=resources_to_request,
enable_debug=self.enable_debug,
Expand Down Expand Up @@ -267,3 +269,66 @@ def end(self, test_outcome, details=None):
details (str): details of the result (traceback/skip reason).
"""
self.data.update_result(test_outcome, details)

def _decorate_teardown(self, teardown_method, result):
"""Decorate the tearDown method to handle resource release.
Args:
teardown_method (function): the original tearDown method.
result (rotest.core.result.result.Result): test result information.
Returns:
function. the wrapped tearDown method.
"""
@wraps(teardown_method)
def teardown_method_wrapper(*args, **kwargs):
"""tearDown method wrapper.
* Executes the original tearDown method.
* Releases the test resources.
* Closes the client if needed
"""
self.result.startTeardown(self)
try:
teardown_method(*args, **kwargs)

except Exception:
result.addError(self, sys.exc_info())

finally:
self.store_state()
self.release_resources(
dirty=self.data.exception_type == TestOutcome.ERROR,
force_release=False)

if (self._is_client_local and
self.resource_manager.is_connected()):

self.resource_manager.disconnect()

return teardown_method_wrapper

def store_state(self):
"""Store the state of the resources in the work dir."""
status = self.data.exception_type
if (not self.save_state or status is None or
status in TestOutcome.POSITIVE_RESULTS):

self.logger.debug("Skipping saving error state")
return

store_dir = os.path.join(self.work_dir, self.STATE_DIR_NAME)

# In case a state dir already exists, create a new one.
state_dir_index = 1
while os.path.exists(store_dir):
state_dir_index += 1
store_dir = os.path.join(self.work_dir,
self.STATE_DIR_NAME + str(
state_dir_index))

self.logger.debug("Creating state dir %r", store_dir)
os.makedirs(store_dir)

for resource in self.all_resources.itervalues():
resource.store_state(store_dir)
41 changes: 3 additions & 38 deletions src/rotest/core/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@
# pylint: disable=too-many-public-methods,too-many-arguments
# pylint: disable=too-many-instance-attributes,too-few-public-methods
# pylint: disable=no-member,method-hidden,broad-except,bare-except,invalid-name
import sys
import unittest
from functools import wraps
from itertools import count

from rotest.common import core_log
from rotest.common.utils import get_work_dir
from rotest.common.config import ROTEST_WORK_DIR
from rotest.core.models.case_data import CaseData
from rotest.core.abstract_test import AbstractTest, request
from rotest.core.models.case_data import TestOutcome, CaseData


assert request
Expand Down Expand Up @@ -107,10 +106,10 @@ def _decorate_setup(self, setup_method):
"""Decorate setUp method to handle link skips, and resources requests.
Args:
setup_method (method): the original setUp method.
setup_method (function): the original setUp method.
Returns:
method. the wrapped setUp method.
function. the wrapped setUp method.
"""
@wraps(setup_method)
def setup_method_wrapper(*args, **kwargs):
Expand All @@ -137,40 +136,6 @@ def setup_method_wrapper(*args, **kwargs):

return setup_method_wrapper

def _decorate_teardown(self, teardown_method, result):
"""Decorate the tearDown method to handle resource release.
Args:
test_method (method): the original tearDown method.
result (rotest.core.result.result.Result): test result information.
Returns:
method. the wrapped tearDown method.
"""
@wraps(teardown_method)
def teardown_method_wrapper(*args, **kwargs):
"""tearDown method wrapper.
* Executes the original tearDown method.
* Releases the test resources.
"""
self.result.startTeardown(self)
try:
teardown_method(*args, **kwargs)

except Exception:
result.addError(self, sys.exc_info())

finally:
self.release_resources(
dirty=self.data.exception_type == TestOutcome.ERROR,
force_release=False)

if self._is_client_local:
self.resource_manager.disconnect()

return teardown_method_wrapper

def run(self, result=None):
"""Run the test case.
Expand Down
42 changes: 5 additions & 37 deletions src/rotest/core/flow_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
# pylint: disable=too-many-arguments,too-many-locals,broad-except
# pylint: disable=dangerous-default-value,access-member-before-definition
# pylint: disable=bare-except,protected-access,too-many-instance-attributes
import sys
import unittest
from functools import wraps
from itertools import count
Expand Down Expand Up @@ -243,46 +242,15 @@ def setup_method_wrapper(*args, **kwargs):

return setup_method_wrapper

def _decorate_teardown(self, teardown_method, result):
"""Decorate the tearDown method to handle resource release.
Args:
teardown_method (method): the original tearDown method.
result (rotest.core.result.result.Result): test result information.
Returns:
method. the wrapped tearDown method.
"""
@wraps(teardown_method)
def teardown_method_wrapper(*args, **kwargs):
"""tearDown method wrapper.
* Executes the original tearDown method.
* Releases the test resources.
"""
self.result.startTeardown(self)
try:
teardown_method(*args, **kwargs)

except Exception:
result.addError(self, sys.exc_info())

finally:
self.release_resources(
dirty=self.data.exception_type == TestOutcome.ERROR,
force_release=False)

if (self._is_client_local and
self.resource_manager.is_connected()):

self.resource_manager.disconnect()

return teardown_method_wrapper

def tearDown(self):
"""TearDown method."""
pass

def store_state(self):
"""Store the state of the resources in the work dir."""
if self.is_main:
super(AbstractFlowComponent, self).store_state()

def run(self, result=None):
"""Run the test component.
Expand Down
31 changes: 2 additions & 29 deletions src/rotest/management/base_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
responsible for the resource static & dynamic information.
"""
# pylint: disable=too-many-instance-attributes,no-self-use,broad-except
import os
from bdb import BdbQuit

from ipdbugger import debug
Expand Down Expand Up @@ -57,7 +56,6 @@ class BaseResource(object):
data (ResourceData): assigned data instance.
config (AttrDict): run configuration.
work_dir (str): working directory for this resource.
save_state (bool): flag to indicate if the resource is a duplication.
force_initialize (bool): a flag to determine if the resource will be
initialized even if the validation succeeds.
"""
Expand Down Expand Up @@ -88,7 +86,6 @@ def __init__(self, data=None, **kwargs):
self.config = None
self.parent = None
self.work_dir = None
self.save_state = None
self.force_initialize = None

self._sub_resources = None
Expand Down Expand Up @@ -185,33 +182,9 @@ def store_state(self, state_dir_path):
Args:
state_dir_path (str): path of state directory to be saved.
"""
self._safe_execute([resource.store_state_dir for resource
in self.get_sub_resources()], state_dir_path)

def store_state_dir(self, dir_name):
"""Store the resource state under a sub-directory of the work_dir.
Create a directory under the resource work directory and calls
store_state on that directory.
Args:
dir_name (str): sub-directory name.
"""
store_dir = os.path.join(self.work_dir, dir_name)
self.logger.debug("Creating dir %r", store_dir)

# In case a state dir already exists, create a new one.
state_dir_index = 1
while os.path.exists(store_dir):
state_dir_index += 1
store_dir = os.path.join(self.work_dir,
dir_name + str(state_dir_index))

os.makedirs(store_dir)

self.logger.debug("Storing resource %r state", self.name)
self.store_state(store_dir)
self.logger.debug("Resource %r state stored", self.name)
self._safe_execute([resource.store_state for resource
in self.get_sub_resources()], state_dir_path)

def initialize(self):
"""Hook method for setting up the resource before using it.
Expand Down

0 comments on commit 56fcfd8

Please sign in to comment.