Unittest discovery ImportError / _FailedTest (tested)
If a test file fails to import — a typo'd import, a missing dependency, a syntax error — unittest discover doesn't show you a normal traceback. It reports a fake passing-looking test named _FailedTest that actually failed, which hides what really broke. We reproduced it directly.
1. The exact error, from a single bad import
We added one bad top-level import to an otherwise-valid test file:
import nonexistent_module
import unittest
class T(unittest.TestCase):
def test_x(self):
self.assertTrue(True)
Running python -m unittest discover gave:
E
======================================================================
ERROR: test_broken (unittest.loader._FailedTest.test_broken)
----------------------------------------------------------------------
ImportError: Failed to import test module: test_broken
Traceback (most recent call last):
File "/usr/lib/python3.13/unittest/loader.py", line 396, in _find_test_path
module = self._get_module_from_name(name)
...
File "tests/test_broken.py", line 1, in <module>
import nonexistent_module
ModuleNotFoundError: No module named 'nonexistent_module'
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (errors=1)
Why this is confusing: unittest.loader._FailedTest.test_broken looks like a real test case named "FailedTest" failed — it's actually the loader's own placeholder, substituted in place of every real test in the module because the module itself couldn't be imported. The real traceback is in there (scroll past the loader's own frames to find it), but the top line reads like a test assertion failure, not a module-level import error.
2. Running the module directly doesn't give a clean traceback either
We expected python -m unittest test_broken (naming the module instead of using discovery) to show a plain traceback. It still wraps it the same way:
$ python -m unittest test_broken
ERROR: test_broken (unittest.loader._FailedTest.test_broken)
ImportError: Failed to import test module: test_broken
...
Both discovery and direct module invocation go through the same loader, so both get the same _FailedTest wrapping.
3. The fix: import the module directly to see the real error
We confirmed the only way to get the unwrapped traceback is bypassing unittest's loader entirely and importing the module yourself:
$ python -c "import sys; sys.path.insert(0,'tests'); import test_broken"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "tests/test_broken.py", line 1, in <module>
import nonexistent_module
ModuleNotFoundError: No module named 'nonexistent_module'
Same root cause, but now it's the first and only traceback, with no loader frames and no misleading "test" name in front of it. Once the import itself works, discovery goes back to a normal pass:
$ python -m unittest discover -s tests
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Frequently asked questions
What does unittest.loader._FailedTest mean?
It's not a real test — it's the loader's placeholder, substituted for every test in a module that failed to import. We reproduced this with a single bad top-level import: the module had one real test, but the loader reported one _FailedTest instead, carrying the import error inside it.
Why does the error look like a test named FailedTest failed?
Because unittest reports it exactly like any other test result (an ERROR line with a dotted test name), just with the loader's internal class name instead of a real one. We measured that the actual ModuleNotFoundError is present in the traceback, but several loader frames appear before it.
Does running a specific module instead of discover avoid this?
No — we confirmed python -m unittest <module_name> goes through the same loader and wraps the import error identically. The wrapping happens regardless of how you invoke unittest.
What's the fastest way to see the real traceback?
Import the broken module directly with plain Python — python -c "import your_test_module" (with the right sys.path) — which we confirmed shows only the real traceback, with no loader frames and no misleading test name in front of it.
Written with AI assistance. Measured on 2026-10-03 with Python 3.13.5's built-in unittest module, using a test file with a top-level import of a nonexistent module, run via python -m unittest discover, python -m unittest <module>, and a direct import. Every message below is copy-pasted output, not paraphrased. PlainHeaders is our extension; Python's unittest is built in.