1from testfixtures import ( 2 Replacer, 3 Replace, 4 ShouldRaise, 5 TempDirectory, 6 replace, 7 compare, 8 not_there, 9 ) 10from unittest import TestCase 11 12import os 13 14from testfixtures.tests import sample1 15from testfixtures.tests import sample2 16from ..compat import PY3 17 18from warnings import catch_warnings 19 20 21class TestReplace(TestCase): 22 23 def test_function(self): 24 25 def test_z(): 26 return 'replacement z' 27 28 compare(sample1.z(), 'original z') 29 30 @replace('testfixtures.tests.sample1.z', test_z) 31 def test_something(): 32 compare(sample1.z(), 'replacement z') 33 34 compare(sample1.z(), 'original z') 35 36 test_something() 37 38 compare(sample1.z(), 'original z') 39 40 def test_class(self): 41 42 OriginalX = sample1.X 43 44 class ReplacementX(sample1.X): 45 pass 46 47 self.failIf(OriginalX is ReplacementX) 48 self.failUnless(isinstance(sample1.X(), OriginalX)) 49 50 @replace('testfixtures.tests.sample1.X', ReplacementX) 51 def test_something(): 52 self.failIf(OriginalX is ReplacementX) 53 self.failUnless(isinstance(sample1.X(), ReplacementX)) 54 55 self.failIf(OriginalX is ReplacementX) 56 self.failUnless(isinstance(sample1.X(), OriginalX)) 57 58 test_something() 59 60 self.failIf(OriginalX is ReplacementX) 61 self.failUnless(isinstance(sample1.X(), OriginalX)) 62 63 def test_method(self): 64 65 def test_y(self): 66 return self 67 68 compare(sample1.X().y(), 'original y') 69 70 @replace('testfixtures.tests.sample1.X.y', test_y) 71 def test_something(): 72 self.failUnless(isinstance(sample1.X().y(), sample1.X)) 73 74 compare(sample1.X().y(), 'original y') 75 76 test_something() 77 78 compare(sample1.X().y(), 'original y') 79 80 def test_class_method(self): 81 82 def rMethod(cls): 83 return (cls, 1) 84 85 compare(sample1.X().aMethod(), sample1.X) 86 87 @replace('testfixtures.tests.sample1.X.aMethod', rMethod) 88 def test_something(r): 89 compare(r, rMethod) 90 compare(sample1.X().aMethod(), (sample1.X, 1)) 91 92 compare(sample1.X().aMethod(), sample1.X) 93 94 test_something() 95 96 compare(sample1.X().aMethod(), sample1.X) 97 98 def test_multiple_replace(self): 99 100 def test_y(self): 101 return 'test y' 102 103 def test_z(): 104 return 'test z' 105 106 compare(sample1.z(), 'original z') 107 compare(sample1.X().y(), 'original y') 108 109 @replace('testfixtures.tests.sample1.z', test_z) 110 @replace('testfixtures.tests.sample1.X.y', test_y) 111 def test_something(passed_test_y, passed_test_z): 112 compare(test_z, passed_test_z) 113 compare(test_y, passed_test_y) 114 compare(sample1.z(), 'test z') 115 compare(sample1.X().y(), 'test y') 116 117 compare(sample1.z(), 'original z') 118 compare(sample1.X().y(), 'original y') 119 120 test_something() 121 122 compare(sample1.z(), 'original z') 123 compare(sample1.X().y(), 'original y') 124 125 def test_gotcha(self): 126 # Just because you replace an object in one context, 127 # doesn't meant that it's replaced in all contexts! 128 129 def test_z(): 130 return 'test z' 131 132 compare(sample1.z(), 'original z') 133 compare(sample2.z(), 'original z') 134 135 @replace('testfixtures.tests.sample1.z', test_z) 136 def test_something(): 137 compare(sample1.z(), 'test z') 138 compare(sample2.z(), 'original z') 139 140 compare(sample1.z(), 'original z') 141 compare(sample2.z(), 'original z') 142 143 test_something() 144 145 compare(sample1.z(), 'original z') 146 compare(sample2.z(), 'original z') 147 148 def test_raises(self): 149 150 def test_z(): 151 return 'replacement z' 152 153 compare(sample1.z(), 'original z') 154 155 @replace('testfixtures.tests.sample1.z', test_z) 156 def test_something(): 157 compare(sample1.z(), 'replacement z') 158 raise Exception() 159 160 compare(sample1.z(), 'original z') 161 162 with ShouldRaise(): 163 test_something() 164 165 compare(sample1.z(), 'original z') 166 167 def test_want_replacement(self): 168 169 o = object() 170 171 @replace('testfixtures.tests.sample1.z', o) 172 def test_something(r): 173 self.failUnless(r is o) 174 self.failUnless(sample1.z is o) 175 176 test_something() 177 178 def test_not_there(self): 179 180 o = object() 181 182 @replace('testfixtures.tests.sample1.bad', o) 183 def test_something(r): 184 pass # pragma: no cover 185 186 with ShouldRaise(AttributeError("Original 'bad' not found")): 187 test_something() 188 189 def test_not_there_ok(self): 190 191 o = object() 192 193 @replace('testfixtures.tests.sample1.bad', o, strict=False) 194 def test_something(r): 195 self.failUnless(r is o) 196 self.failUnless(sample1.bad is o) 197 198 test_something() 199 200 def test_replace_dict(self): 201 202 from testfixtures.tests.sample1 import someDict 203 204 original = someDict['key'] 205 replacement = object() 206 207 @replace('testfixtures.tests.sample1.someDict.key', replacement) 208 def test_something(obj): 209 self.failUnless(obj is replacement) 210 self.failUnless(someDict['key'] is replacement) 211 212 test_something() 213 214 self.failUnless(someDict['key'] is original) 215 216 def test_replace_delattr(self): 217 218 from testfixtures.tests import sample1 219 220 @replace('testfixtures.tests.sample1.someDict', not_there) 221 def test_something(obj): 222 self.failIf(hasattr(sample1, 'someDict')) 223 224 test_something() 225 226 self.assertEqual(sample1.someDict, 227 {'complex_key': [1, 2, 3], 'key': 'value'}) 228 229 def test_replace_delattr_not_there(self): 230 231 @replace('testfixtures.tests.sample1.foo', not_there) 232 def test_something(obj): 233 pass # pragma: no cover 234 235 with ShouldRaise(AttributeError("Original 'foo' not found")): 236 test_something() 237 238 def test_replace_delattr_not_there_not_strict(self): 239 240 from testfixtures.tests import sample1 241 242 @replace('testfixtures.tests.sample1.foo', 243 not_there, strict=False) 244 def test_something(obj): 245 self.failIf(hasattr(sample1, 'foo')) 246 247 test_something() 248 249 def test_replace_delattr_not_there_restored(self): 250 251 from testfixtures.tests import sample1 252 253 @replace('testfixtures.tests.sample1.foo', 254 not_there, strict=False) 255 def test_something(obj): 256 sample1.foo = 'bar' 257 258 test_something() 259 self.failIf(hasattr(sample1, 'foo')) 260 261 def test_replace_delattr_cant_remove(self): 262 with Replacer() as r: 263 with ShouldRaise(TypeError( 264 "can't set attributes of " 265 "built-in/extension type 'datetime.datetime'" 266 )): 267 r.replace('datetime.datetime.today', not_there) 268 269 def test_replace_delattr_cant_remove_not_strict(self): 270 with Replacer() as r: 271 with ShouldRaise(TypeError( 272 "can't set attributes of " 273 "built-in/extension type 'datetime.datetime'" 274 )): 275 r.replace('datetime.datetime.today', not_there, strict=False) 276 277 def test_replace_dict_remove_key(self): 278 279 from testfixtures.tests.sample1 import someDict 280 281 @replace('testfixtures.tests.sample1.someDict.key', not_there) 282 def test_something(obj): 283 self.failIf('key' in someDict) 284 285 test_something() 286 287 self.assertEqual(sorted(someDict.keys()), ['complex_key', 'key']) 288 289 def test_replace_dict_remove_key_not_there(self): 290 291 from testfixtures.tests.sample1 import someDict 292 293 @replace('testfixtures.tests.sample1.someDict.badkey', not_there) 294 def test_something(obj): 295 self.failIf('badkey' in someDict) # pragma: no cover 296 297 with ShouldRaise(AttributeError("Original 'badkey' not found")): 298 test_something() 299 300 self.assertEqual(sorted(someDict.keys()), ['complex_key', 'key']) 301 302 def test_replace_dict_remove_key_not_there_not_strict(self): 303 304 from testfixtures.tests.sample1 import someDict 305 306 @replace('testfixtures.tests.sample1.someDict.badkey', 307 not_there, strict=False) 308 def test_something(obj): 309 self.failIf('badkey' in someDict) 310 311 test_something() 312 313 self.assertEqual(sorted(someDict.keys()), ['complex_key', 'key']) 314 315 def test_replace_dict_ensure_key_not_there_restored(self): 316 317 from testfixtures.tests.sample1 import someDict 318 319 @replace('testfixtures.tests.sample1.someDict.badkey', 320 not_there, strict=False) 321 def test_something(obj): 322 someDict['badkey'] = 'some test value' 323 324 test_something() 325 326 self.assertEqual(sorted(someDict.keys()), ['complex_key', 'key']) 327 328 def test_replace_dict_not_there(self): 329 330 from testfixtures.tests.sample1 import someDict 331 332 replacement = object() 333 334 @replace('testfixtures.tests.sample1.someDict.key2', 335 replacement, 336 strict=False) 337 def test_something(obj): 338 self.failUnless(obj is replacement) 339 self.failUnless(someDict['key2'] is replacement) 340 341 test_something() 342 343 self.assertEqual(sorted(someDict.keys()), ['complex_key', 'key']) 344 345 def test_replace_dict_not_there_empty_string(self): 346 347 from testfixtures.tests.sample1 import someDict 348 349 @replace('testfixtures.tests.sample1.someDict.key2', '', strict=False) 350 def test_something(): 351 self.assertEqual(someDict['key2'], '') 352 353 test_something() 354 355 self.assertEqual(sorted(someDict.keys()), ['complex_key', 'key']) 356 357 def test_replace_complex(self): 358 359 from testfixtures.tests.sample1 import someDict 360 361 original = someDict['complex_key'][1] 362 replacement = object() 363 364 @replace('testfixtures.tests.sample1.someDict.complex_key.1', 365 replacement) 366 def test_something(obj): 367 self.failUnless(obj is replacement) 368 self.assertEqual(someDict['complex_key'], [1, obj, 3]) 369 370 test_something() 371 372 self.assertEqual(someDict['complex_key'], [1, 2, 3]) 373 374 self.failUnless(original is someDict['complex_key'][1]) 375 376 def test_replacer_del(self): 377 r = Replacer() 378 r.replace('testfixtures.tests.sample1.left_behind', 379 object(), strict=False) 380 with catch_warnings(record=True) as w: 381 del r 382 self.assertTrue(len(w), 1) 383 compare(str(w[0].message), 384 "Replacer deleted without being restored, originals left:" 385 " {'testfixtures.tests.sample1.left_behind': <not_there>}") 386 387 def test_multiple_replaces(self): 388 orig = os.path.sep 389 with Replacer() as r: 390 r.replace('os.path.sep', '$') 391 compare(os.path.sep, '$') 392 r.replace('os.path.sep', '=') 393 compare(os.path.sep, '=') 394 compare(orig, os.path.sep) 395 396 def test_sub_module_import(self): 397 with TempDirectory() as dir: 398 dir.write('module/__init__.py', b'') 399 dir.write('module/submodule.py', b'def foo(): return "foo"') 400 401 with Replacer() as r: 402 r.replace('sys.path', [dir.path]) 403 404 def bar(): 405 return "bar" 406 # now test 407 408 r.replace('module.submodule.foo', bar) 409 410 from module.submodule import foo 411 compare(foo(), "bar") 412 413 def test_staticmethod(self): 414 compare(sample1.X.bMethod(), 2) 415 with Replacer() as r: 416 r.replace('testfixtures.tests.sample1.X.bMethod', lambda: 1) 417 compare(sample1.X.bMethod(), 1) 418 compare(sample1.X.bMethod(), 2) 419 420 def test_use_as_cleanup(self): 421 def test_z(): 422 return 'replacement z' 423 424 compare(sample1.z(), 'original z') 425 replace = Replacer() 426 compare(sample1.z(), 'original z') 427 replace('testfixtures.tests.sample1.z', test_z) 428 cleanup = replace.restore 429 try: 430 compare(sample1.z(), 'replacement z') 431 finally: 432 cleanup() 433 compare(sample1.z(), 'original z') 434 435 def test_replace_context_manager(self): 436 def test_z(): 437 return 'replacement z' 438 439 compare(sample1.z(), 'original z') 440 441 with Replace('testfixtures.tests.sample1.z', test_z) as z: 442 compare(z(), 'replacement z') 443 compare(sample1.z(), 'replacement z') 444 445 compare(sample1.z(), 'original z') 446 447 def test_multiple_context_managers(self): 448 449 def test_y(self): 450 return 'test y' 451 452 def test_z(): 453 return 'test z' 454 455 compare(sample1.z(), 'original z') 456 compare(sample1.X().y(), 'original y') 457 458 with Replacer() as replace: 459 z = replace('testfixtures.tests.sample1.z', test_z) 460 y = replace('testfixtures.tests.sample1.X.y', test_y) 461 compare(z(), 'test z') 462 if PY3: 463 compare(y, sample1.X.y) 464 compare(sample1.X().y(), 'test y') 465 compare(sample1.z(), 'test z') 466 compare(sample1.X().y(), 'test y') 467 468 compare(sample1.z(), 'original z') 469 compare(sample1.X().y(), 'original y') 470 471 def test_context_manager_not_strict(self): 472 def test_z(): 473 return 'replacement z' 474 475 with Replace('testfixtures.tests.sample1.foo', test_z, strict=False): 476 compare(sample1.foo(), 'replacement z') 477