1# testresources: extensions to python unittest to allow declaritive use 2# of resources by test cases. 3# 4# Copyright (c) 2005-2010 Testresources Contributors 5# 6# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause 7# license at the users choice. A copy of both licenses are available in the 8# project source as Apache-2.0 and BSD. You may not use this file except in 9# compliance with one of these two licences. 10# 11# Unless required by applicable law or agreed to in writing, software distributed 12# under these licenses is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 13# CONDITIONS OF ANY KIND, either express or implied. See the license you chose 14# for the specific language governing permissions and limitations under that 15# license. 16# 17 18from fixtures.tests.helpers import LoggingFixture 19import testtools 20 21import testresources 22from testresources.tests import ( 23 ResultWithResourceExtensions, 24 ResultWithoutResourceExtensions, 25 ) 26 27 28def test_suite(): 29 loader = testresources.tests.TestUtil.TestLoader() 30 result = loader.loadTestsFromName(__name__) 31 return result 32 33 34class MockResourceInstance(object): 35 36 def __init__(self, name): 37 self._name = name 38 39 def __eq__(self, other): 40 return self.__dict__ == other.__dict__ 41 42 def __cmp__(self, other): 43 return cmp(self.__dict__, other.__dict__) 44 45 def __repr__(self): 46 return self._name 47 48 49class MockResource(testresources.TestResourceManager): 50 """Mock resource that logs the number of make and clean calls.""" 51 52 def __init__(self): 53 super(MockResource, self).__init__() 54 self.makes = 0 55 self.cleans = 0 56 57 def clean(self, resource): 58 self.cleans += 1 59 60 def make(self, dependency_resources): 61 self.makes += 1 62 return MockResourceInstance("Boo!") 63 64 65class MockResettableResource(MockResource): 66 """Mock resource that logs the number of reset calls too.""" 67 68 def __init__(self): 69 super(MockResettableResource, self).__init__() 70 self.resets = 0 71 72 def _reset(self, resource, dependency_resources): 73 self.resets += 1 74 resource._name += "!" 75 self._dirty = False 76 return resource 77 78 79class TestTestResource(testtools.TestCase): 80 81 def testUnimplementedGetResource(self): 82 # By default, TestResource raises NotImplementedError on getResource 83 # because make is not defined initially. 84 resource_manager = testresources.TestResource() 85 self.assertRaises(NotImplementedError, resource_manager.getResource) 86 87 def testInitiallyNotDirty(self): 88 resource_manager = testresources.TestResource() 89 self.assertEqual(False, resource_manager._dirty) 90 91 def testInitiallyUnused(self): 92 resource_manager = testresources.TestResource() 93 self.assertEqual(0, resource_manager._uses) 94 95 def testInitiallyNoCurrentResource(self): 96 resource_manager = testresources.TestResource() 97 self.assertEqual(None, resource_manager._currentResource) 98 99 def testneededResourcesDefault(self): 100 # Calling neededResources on a default TestResource returns the 101 # resource. 102 resource = testresources.TestResource() 103 self.assertEqual([resource], resource.neededResources()) 104 105 def testneededResourcesDependenciesFirst(self): 106 # Calling neededResources on a TestResource with dependencies puts the 107 # dependencies first. 108 resource = testresources.TestResource() 109 dep1 = testresources.TestResource() 110 dep2 = testresources.TestResource() 111 resource.resources.append(("dep1", dep1)) 112 resource.resources.append(("dep2", dep2)) 113 self.assertEqual([dep1, dep2, resource], resource.neededResources()) 114 115 def testneededResourcesClosure(self): 116 # Calling neededResources on a TestResource with dependencies includes 117 # the needed resources of the needed resources. 118 resource = testresources.TestResource() 119 dep1 = testresources.TestResource() 120 dep2 = testresources.TestResource() 121 resource.resources.append(("dep1", dep1)) 122 dep1.resources.append(("dep2", dep2)) 123 self.assertEqual([dep2, dep1, resource], resource.neededResources()) 124 125 def testDefaultCosts(self): 126 # The base TestResource costs 1 to set up and to tear down. 127 resource_manager = testresources.TestResource() 128 self.assertEqual(resource_manager.setUpCost, 1) 129 self.assertEqual(resource_manager.tearDownCost, 1) 130 131 def testGetResourceReturnsMakeResource(self): 132 resource_manager = MockResource() 133 resource = resource_manager.getResource() 134 self.assertEqual(resource_manager.make({}), resource) 135 136 def testGetResourceIncrementsUses(self): 137 resource_manager = MockResource() 138 resource_manager.getResource() 139 self.assertEqual(1, resource_manager._uses) 140 resource_manager.getResource() 141 self.assertEqual(2, resource_manager._uses) 142 143 def testGetResourceDoesntDirty(self): 144 resource_manager = MockResource() 145 resource_manager.getResource() 146 self.assertEqual(resource_manager._dirty, False) 147 148 def testGetResourceSetsCurrentResource(self): 149 resource_manager = MockResource() 150 resource = resource_manager.getResource() 151 self.assertIs(resource_manager._currentResource, resource) 152 153 def testGetResourceTwiceReturnsIdenticalResource(self): 154 resource_manager = MockResource() 155 resource1 = resource_manager.getResource() 156 resource2 = resource_manager.getResource() 157 self.assertIs(resource1, resource2) 158 159 def testGetResourceCallsMakeResource(self): 160 resource_manager = MockResource() 161 resource_manager.getResource() 162 self.assertEqual(1, resource_manager.makes) 163 164 def testIsDirty(self): 165 resource_manager = MockResource() 166 r = resource_manager.getResource() 167 resource_manager.dirtied(r) 168 self.assertTrue(resource_manager.isDirty()) 169 resource_manager.finishedWith(r) 170 171 def testIsDirtyIsTrueIfDependenciesChanged(self): 172 resource_manager = MockResource() 173 dep1 = MockResource() 174 dep2 = MockResource() 175 dep3 = MockResource() 176 resource_manager.resources.append(("dep1", dep1)) 177 resource_manager.resources.append(("dep2", dep2)) 178 resource_manager.resources.append(("dep3", dep3)) 179 r = resource_manager.getResource() 180 dep2.dirtied(r.dep2) 181 r2 =dep2.getResource() 182 self.assertTrue(resource_manager.isDirty()) 183 resource_manager.finishedWith(r) 184 dep2.finishedWith(r2) 185 186 def testIsDirtyIsTrueIfDependenciesAreDirty(self): 187 resource_manager = MockResource() 188 dep1 = MockResource() 189 dep2 = MockResource() 190 dep3 = MockResource() 191 resource_manager.resources.append(("dep1", dep1)) 192 resource_manager.resources.append(("dep2", dep2)) 193 resource_manager.resources.append(("dep3", dep3)) 194 r = resource_manager.getResource() 195 dep2.dirtied(r.dep2) 196 self.assertTrue(resource_manager.isDirty()) 197 resource_manager.finishedWith(r) 198 199 def testRepeatedGetResourceCallsMakeResourceOnceOnly(self): 200 resource_manager = MockResource() 201 resource_manager.getResource() 202 resource_manager.getResource() 203 self.assertEqual(1, resource_manager.makes) 204 205 def testGetResourceResetsUsedResource(self): 206 resource_manager = MockResettableResource() 207 resource_manager.getResource() 208 resource = resource_manager.getResource() 209 self.assertEqual(1, resource_manager.makes) 210 resource_manager.dirtied(resource) 211 resource_manager.getResource() 212 self.assertEqual(1, resource_manager.makes) 213 self.assertEqual(1, resource_manager.resets) 214 resource_manager.finishedWith(resource) 215 216 def testIsResetIfDependenciesAreDirty(self): 217 resource_manager = MockResource() 218 dep1 = MockResettableResource() 219 resource_manager.resources.append(("dep1", dep1)) 220 r = resource_manager.getResource() 221 dep1.dirtied(r.dep1) 222 # if we get the resource again, it should be cleaned. 223 r = resource_manager.getResource() 224 self.assertFalse(resource_manager.isDirty()) 225 self.assertFalse(dep1.isDirty()) 226 resource_manager.finishedWith(r) 227 resource_manager.finishedWith(r) 228 229 def testUsedResourceResetBetweenUses(self): 230 resource_manager = MockResettableResource() 231 # take two refs; like happens with OptimisingTestSuite. 232 resource_manager.getResource() 233 resource = resource_manager.getResource() 234 resource_manager.dirtied(resource) 235 resource_manager.finishedWith(resource) 236 # Get again, but its been dirtied. 237 resource = resource_manager.getResource() 238 resource_manager.finishedWith(resource) 239 resource_manager.finishedWith(resource) 240 # The resource is made once, reset once and cleaned once. 241 self.assertEqual(1, resource_manager.makes) 242 self.assertEqual(1, resource_manager.resets) 243 self.assertEqual(1, resource_manager.cleans) 244 245 def testFinishedWithDecrementsUses(self): 246 resource_manager = MockResource() 247 resource = resource_manager.getResource() 248 resource = resource_manager.getResource() 249 self.assertEqual(2, resource_manager._uses) 250 resource_manager.finishedWith(resource) 251 self.assertEqual(1, resource_manager._uses) 252 resource_manager.finishedWith(resource) 253 self.assertEqual(0, resource_manager._uses) 254 255 def testFinishedWithResetsCurrentResource(self): 256 resource_manager = MockResource() 257 resource = resource_manager.getResource() 258 resource_manager.finishedWith(resource) 259 self.assertIs(None, resource_manager._currentResource) 260 261 def testFinishedWithCallsCleanResource(self): 262 resource_manager = MockResource() 263 resource = resource_manager.getResource() 264 resource_manager.finishedWith(resource) 265 self.assertEqual(1, resource_manager.cleans) 266 267 def testUsingTwiceMakesAndCleansTwice(self): 268 resource_manager = MockResource() 269 resource = resource_manager.getResource() 270 resource_manager.finishedWith(resource) 271 resource = resource_manager.getResource() 272 resource_manager.finishedWith(resource) 273 self.assertEqual(2, resource_manager.makes) 274 self.assertEqual(2, resource_manager.cleans) 275 276 def testFinishedWithCallsCleanResourceOnceOnly(self): 277 resource_manager = MockResource() 278 resource = resource_manager.getResource() 279 resource = resource_manager.getResource() 280 resource_manager.finishedWith(resource) 281 self.assertEqual(0, resource_manager.cleans) 282 resource_manager.finishedWith(resource) 283 self.assertEqual(1, resource_manager.cleans) 284 285 def testFinishedWithMarksNonDirty(self): 286 resource_manager = MockResource() 287 resource = resource_manager.getResource() 288 resource_manager.dirtied(resource) 289 resource_manager.finishedWith(resource) 290 self.assertEqual(False, resource_manager._dirty) 291 292 def testResourceAvailableBetweenFinishedWithCalls(self): 293 resource_manager = MockResource() 294 resource = resource_manager.getResource() 295 resource = resource_manager.getResource() 296 resource_manager.finishedWith(resource) 297 self.assertIs(resource, resource_manager._currentResource) 298 resource_manager.finishedWith(resource) 299 300 def testDirtiedSetsDirty(self): 301 resource_manager = MockResource() 302 resource = resource_manager.getResource() 303 self.assertEqual(False, resource_manager._dirty) 304 resource_manager.dirtied(resource) 305 self.assertEqual(True, resource_manager._dirty) 306 307 def testDirtyingResourceTriggersCleanOnGet(self): 308 resource_manager = MockResource() 309 resource1 = resource_manager.getResource() 310 resource2 = resource_manager.getResource() 311 resource_manager.dirtied(resource2) 312 resource_manager.finishedWith(resource2) 313 self.assertEqual(0, resource_manager.cleans) 314 resource3 = resource_manager.getResource() 315 self.assertEqual(1, resource_manager.cleans) 316 resource_manager.finishedWith(resource3) 317 resource_manager.finishedWith(resource1) 318 self.assertEqual(2, resource_manager.cleans) 319 320 def testDefaultResetMethodPreservesCleanResource(self): 321 resource_manager = MockResource() 322 resource = resource_manager.getResource() 323 self.assertEqual(1, resource_manager.makes) 324 self.assertEqual(False, resource_manager._dirty) 325 resource_manager.reset(resource) 326 self.assertEqual(1, resource_manager.makes) 327 self.assertEqual(0, resource_manager.cleans) 328 329 def testDefaultResetMethodRecreatesDirtyResource(self): 330 resource_manager = MockResource() 331 resource = resource_manager.getResource() 332 self.assertEqual(1, resource_manager.makes) 333 resource_manager.dirtied(resource) 334 resource_manager.reset(resource) 335 self.assertEqual(2, resource_manager.makes) 336 self.assertEqual(1, resource_manager.cleans) 337 338 def testDefaultResetResetsDependencies(self): 339 resource_manager = MockResettableResource() 340 dep1 = MockResettableResource() 341 dep2 = MockResettableResource() 342 resource_manager.resources.append(("dep1", dep1)) 343 resource_manager.resources.append(("dep2", dep2)) 344 # A typical OptimisingTestSuite workflow 345 r_outer = resource_manager.getResource() 346 # test 1 347 r_inner = resource_manager.getResource() 348 dep2.dirtied(r_inner.dep2) 349 resource_manager.finishedWith(r_inner) 350 # test 2 351 r_inner = resource_manager.getResource() 352 dep2.dirtied(r_inner.dep2) 353 resource_manager.finishedWith(r_inner) 354 resource_manager.finishedWith(r_outer) 355 # Dep 1 was clean, doesn't do a reset, and should only have one 356 # make+clean. 357 self.assertEqual(1, dep1.makes) 358 self.assertEqual(1, dep1.cleans) 359 self.assertEqual(0, dep1.resets) 360 # Dep 2 was dirty, so _reset happens, and likewise only one make and 361 # clean. 362 self.assertEqual(1, dep2.makes) 363 self.assertEqual(1, dep2.cleans) 364 self.assertEqual(1, dep2.resets) 365 # The top layer should have had a reset happen, and only one make and 366 # clean. 367 self.assertEqual(1, resource_manager.makes) 368 self.assertEqual(1, resource_manager.cleans) 369 self.assertEqual(1, resource_manager.resets) 370 371 def testDirtyingWhenUnused(self): 372 resource_manager = MockResource() 373 resource = resource_manager.getResource() 374 resource_manager.finishedWith(resource) 375 resource_manager.dirtied(resource) 376 self.assertEqual(1, resource_manager.makes) 377 resource = resource_manager.getResource() 378 self.assertEqual(2, resource_manager.makes) 379 380 def testFinishedActivityForResourceWithoutExtensions(self): 381 result = ResultWithoutResourceExtensions() 382 resource_manager = MockResource() 383 r = resource_manager.getResource() 384 resource_manager.finishedWith(r, result) 385 386 def testFinishedActivityForResourceWithExtensions(self): 387 result = ResultWithResourceExtensions() 388 resource_manager = MockResource() 389 r = resource_manager.getResource() 390 expected = [("clean", "start", resource_manager), 391 ("clean", "stop", resource_manager)] 392 resource_manager.finishedWith(r, result) 393 self.assertEqual(expected, result._calls) 394 395 def testGetActivityForResourceWithoutExtensions(self): 396 result = ResultWithoutResourceExtensions() 397 resource_manager = MockResource() 398 r = resource_manager.getResource(result) 399 resource_manager.finishedWith(r) 400 401 def testGetActivityForResourceWithExtensions(self): 402 result = ResultWithResourceExtensions() 403 resource_manager = MockResource() 404 r = resource_manager.getResource(result) 405 expected = [("make", "start", resource_manager), 406 ("make", "stop", resource_manager)] 407 resource_manager.finishedWith(r) 408 self.assertEqual(expected, result._calls) 409 410 def testResetActivityForResourceWithoutExtensions(self): 411 result = ResultWithoutResourceExtensions() 412 resource_manager = MockResource() 413 resource_manager.getResource() 414 r = resource_manager.getResource() 415 resource_manager.dirtied(r) 416 resource_manager.finishedWith(r) 417 r = resource_manager.getResource(result) 418 resource_manager.dirtied(r) 419 resource_manager.finishedWith(r) 420 resource_manager.finishedWith(resource_manager._currentResource) 421 422 def testResetActivityForResourceWithExtensions(self): 423 result = ResultWithResourceExtensions() 424 resource_manager = MockResource() 425 expected = [("reset", "start", resource_manager), 426 ("reset", "stop", resource_manager), 427 ] 428 resource_manager.getResource() 429 r = resource_manager.getResource() 430 resource_manager.dirtied(r) 431 resource_manager.finishedWith(r) 432 r = resource_manager.getResource(result) 433 resource_manager.dirtied(r) 434 resource_manager.finishedWith(r) 435 resource_manager.finishedWith(resource_manager._currentResource) 436 self.assertEqual(expected, result._calls) 437 438 439class TestGenericResource(testtools.TestCase): 440 441 def test_default_uses_setUp_tearDown(self): 442 calls = [] 443 class Wrapped: 444 def setUp(self): 445 calls.append('setUp') 446 def tearDown(self): 447 calls.append('tearDown') 448 mgr = testresources.GenericResource(Wrapped) 449 resource = mgr.getResource() 450 self.assertEqual(['setUp'], calls) 451 mgr.finishedWith(resource) 452 self.assertEqual(['setUp', 'tearDown'], calls) 453 self.assertIsInstance(resource, Wrapped) 454 455 def test_dependencies_passed_to_factory(self): 456 calls = [] 457 class Wrapped: 458 def __init__(self, **args): 459 calls.append(args) 460 def setUp(self):pass 461 def tearDown(self):pass 462 class Trivial(testresources.TestResource): 463 def __init__(self, thing): 464 testresources.TestResource.__init__(self) 465 self.thing = thing 466 def make(self, dependency_resources):return self.thing 467 def clean(self, resource):pass 468 mgr = testresources.GenericResource(Wrapped) 469 mgr.resources = [('foo', Trivial('foo')), ('bar', Trivial('bar'))] 470 resource = mgr.getResource() 471 self.assertEqual([{'foo':'foo', 'bar':'bar'}], calls) 472 mgr.finishedWith(resource) 473 474 def test_setup_teardown_controllable(self): 475 calls = [] 476 class Wrapped: 477 def start(self): 478 calls.append('setUp') 479 def stop(self): 480 calls.append('tearDown') 481 mgr = testresources.GenericResource(Wrapped, 482 setup_method_name='start', teardown_method_name='stop') 483 resource = mgr.getResource() 484 self.assertEqual(['setUp'], calls) 485 mgr.finishedWith(resource) 486 self.assertEqual(['setUp', 'tearDown'], calls) 487 self.assertIsInstance(resource, Wrapped) 488 489 def test_always_dirty(self): 490 class Wrapped: 491 def setUp(self):pass 492 def tearDown(self):pass 493 mgr = testresources.GenericResource(Wrapped) 494 resource = mgr.getResource() 495 self.assertTrue(mgr.isDirty()) 496 mgr.finishedWith(resource) 497 498 499class TestFixtureResource(testtools.TestCase): 500 501 def test_uses_setUp_cleanUp(self): 502 fixture = LoggingFixture() 503 mgr = testresources.FixtureResource(fixture) 504 resource = mgr.getResource() 505 self.assertEqual(fixture, resource) 506 self.assertEqual(['setUp'], fixture.calls) 507 mgr.finishedWith(resource) 508 self.assertEqual(['setUp', 'cleanUp'], fixture.calls) 509 510 def test_always_dirty(self): 511 fixture = LoggingFixture() 512 mgr = testresources.FixtureResource(fixture) 513 resource = mgr.getResource() 514 self.assertTrue(mgr.isDirty()) 515 mgr.finishedWith(resource) 516 517 def test_reset_called(self): 518 fixture = LoggingFixture() 519 mgr = testresources.FixtureResource(fixture) 520 resource = mgr.getResource() 521 mgr.reset(resource) 522 mgr.finishedWith(resource) 523 self.assertEqual( 524 ['setUp', 'reset', 'cleanUp'], fixture.calls) 525