13# Copyright (c) 2017 Mark D. Hill and David A. Wood 14# All rights reserved. 15# 16# Redistribution and use in source and binary forms, with or without 17# modification, are permitted provided that the following conditions are 18# met: redistributions of source code must retain the above copyright 19# notice, this list of conditions and the following disclaimer; 20# redistributions in binary form must reproduce the above copyright 21# notice, this list of conditions and the following disclaimer in the 22# documentation and/or other materials provided with the distribution; 23# neither the name of the copyright holders nor the names of its 24# contributors may be used to endorse or promote products derived from 25# this software without specific prior written permission. 26# 27# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 30# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 31# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 32# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 33# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 34# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 35# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38# 39# Authors: Sean Wilson 40 41''' 42Module contains wrappers for test items that have been 43loaded by the testlib :class:`testlib.loader.Loader`. 44''' 45import itertools 46 47import log 48import uid 49from state import Status, Result 50 51class TestCaseMetadata(): 52 def __init__(self, name, uid, path, result, status, suite_uid): 53 self.name = name 54 self.uid = uid 55 self.path = path 56 self.status = status 57 self.result = result 58 self.suite_uid = suite_uid 59 60 61class TestSuiteMetadata(): 62 def __init__(self, name, uid, tags, path, status, result): 63 self.name = name 64 self.uid = uid 65 self.tags = tags 66 self.path = path 67 self.status = status 68 self.result = result 69 70 71class LibraryMetadata(): 72 def __init__(self, name, result, status): 73 self.name = name 74 self.result = result 75 self.status = status 76 77 78class LoadedTestable(object): 79 ''' 80 Base class for loaded test items. 81 82 :property:`result` and :property:`status` setters 83 notify testlib via the :func:`log_result` and :func:`log_status` 84 of the updated status. 85 ''' 86 def __init__(self, obj): 87 self.obj = obj 88 self.metadata = self._generate_metadata() 89 90 @property 91 def status(self): 92 return self.metadata.status 93 94 @status.setter 95 def status(self, status): 96 self.log_status(status) 97 self.metadata.status = status 98 99 @property 100 def result(self): 101 return self.metadata.result 102 103 @result.setter 104 def result(self, result): 105 self.log_result(result) 106 self.metadata.result = result 107 108 @property 109 def uid(self): 110 return self.metadata.uid 111 112 @property 113 def name(self): 114 return self.metadata.name 115 116 @property 117 def fixtures(self): 118 return self.obj.fixtures 119 120 @fixtures.setter 121 def fixtures(self, fixtures): 122 self.obj.fixtures = fixtures 123 124 @property 125 def runner(self): 126 return self.obj.runner 127 128 # TODO Change log to provide status_update, result_update for all types. 129 def log_status(self, status): 130 log.test_log.status_update(self, status) 131 132 def log_result(self, result): 133 log.test_log.result_update(self, result) 134 135 def __iter__(self): 136 return iter(()) 137 138 139class LoadedTest(LoadedTestable): 140 def __init__(self, test_obj, loaded_suite, path): 141 self.parent_suite = loaded_suite 142 self._path = path 143 LoadedTestable.__init__(self, test_obj) 144 145 def test(self, *args, **kwargs): 146 self.obj.test(*args, **kwargs) 147 148 def _generate_metadata(self): 149 return TestCaseMetadata( **{ 150 'name':self.obj.name, 151 'path': self._path, 152 'uid': uid.TestUID(self._path, 153 self.obj.name, 154 self.parent_suite.name), 155 'status': Status.Unscheduled, 156 'result': Result(Result.NotRun), 157 'suite_uid': self.parent_suite.metadata.uid 158 }) 159 160 161class LoadedSuite(LoadedTestable): 162 def __init__(self, suite_obj, path): 163 self._path = path 164 LoadedTestable.__init__(self, suite_obj) 165 self.tests = self._wrap_children(suite_obj) 166 167 def _wrap_children(self, suite_obj): 168 return [LoadedTest(test, self, self.metadata.path) 169 for test in suite_obj] 170 171 def _generate_metadata(self): 172 return TestSuiteMetadata( **{ 173 'name': self.obj.name, 174 'tags':self.obj.tags, 175 'path': self._path, 176 'uid': uid.SuiteUID(self._path, self.obj.name), 177 'status': Status.Unscheduled, 178 'result': Result(Result.NotRun) 179 }) 180 181 def __iter__(self): 182 return iter(self.tests) 183 184 @property 185 def tags(self): 186 return self.metadata.tags 187 188 189class LoadedLibrary(LoadedTestable): 190 ''' 191 Wraps a collection of all loaded test suites and 192 provides utility functions for accessing fixtures. 193 '''
|