@@ -349,7 +349,7 @@ def gather_conftest_functions(conftest_path, target):
349
349
conftest_path = str (conftest_path )
350
350
if os .path .exists (conftest_path ):
351
351
print (
352
- f"Using \033 [1m{ conftest_path } \033 [0m for global setup and teardown in \033 [1m{ target } \033 [0m."
352
+ f"Using \033 [1m{ conftest_path } \033 [0m for setup and teardown for tests in \033 [1m{ target } \033 [0m."
353
353
)
354
354
conftest = import_module (conftest_path )
355
355
setup = conftest .setup if hasattr (conftest , "setup" ) else None
@@ -378,24 +378,57 @@ def discover(targets, pattern, setup=None, teardown=None):
378
378
setup and teardown functions can be overridden in the individual test
379
379
modules.
380
380
"""
381
+ # To contain the various conftest.py modules for subdirectories. The key
382
+ # will be the directory path, and the value will be a tuple containing the
383
+ # setup and teardown functions.
384
+ conftests = {}
385
+ # To contain the TestModule instances.
381
386
result = []
382
387
for target in targets :
383
388
if "::" in target :
384
389
conftest_path = Path (target .split ("::" )[0 ]).parent / "conftest.py"
385
- setup , teardown = gather_conftest_functions (conftest_path , target )
390
+ if str (conftest_path ) not in conftests :
391
+ conftests [str (conftest_path )] = gather_conftest_functions (
392
+ conftest_path , target
393
+ )
394
+ setup , teardown = conftests [str (conftest_path )]
386
395
module_path , test_names = target .split ("::" )
387
396
module_instance = import_module (module_path )
388
397
module = TestModule (module_path , module_instance , setup , teardown )
389
398
module .limit_tests_to (test_names .split ("," ))
390
399
result .append (module )
391
400
elif os .path .isdir (target ):
392
401
conftest_path = Path (target ) / "conftest.py"
393
- setup , teardown = gather_conftest_functions (conftest_path , target )
402
+ if str (conftest_path ) not in conftests :
403
+ conftests [str (conftest_path )] = gather_conftest_functions (
404
+ conftest_path , target
405
+ )
406
+ setup , teardown = conftests [str (conftest_path )]
394
407
for module_path in Path (target ).rglob (pattern ):
395
408
module_instance = import_module (module_path )
396
- module = TestModule (
397
- module_path , module_instance , setup , teardown
398
- )
409
+ parent_dir = "/" .join (str (module_path ).split ("/" )[:- 1 ])
410
+ if parent_dir != target :
411
+ # This is a module in a subdirectory of the target
412
+ # directory, so ensure any conftest.py in the sub directory
413
+ # is imported for setup and teardown.
414
+ conftest_path = Path (parent_dir ) / "conftest.py"
415
+ if str (conftest_path ) not in conftests :
416
+ conftests [str (conftest_path )] = (
417
+ gather_conftest_functions (
418
+ conftest_path , parent_dir
419
+ )
420
+ )
421
+ local_setup , local_teardown = conftests [str (conftest_path )]
422
+ module = TestModule (
423
+ module_path ,
424
+ module_instance ,
425
+ local_setup ,
426
+ local_teardown ,
427
+ )
428
+ else :
429
+ module = TestModule (
430
+ module_path , module_instance , setup , teardown
431
+ )
399
432
result .append (module )
400
433
else :
401
434
conftest_path = Path (target ).parent / "conftest.py"
0 commit comments