Listeners hook into the test lifecycle to add cross-cutting behavior — logging, reporting, screenshots on failure, retry registration. TestNG uses ITestListener (and others); JUnit 5 uses the Extension model.
TestNG's ITestListener provides callbacks: onTestStart, onTestSuccess, onTestFailure (capture a screenshot here), onTestSkipped, onFinish. You register listeners via @Listeners, testng.xml <listeners>, or ServiceLoader. Other TestNG listeners: IAnnotationTransformer (inject retry analyzers globally), ISuiteListener, IReporter (custom reports). JUnit 5 replaces listeners with EXTENSIONS (implementing interfaces like TestWatcher, BeforeEachCallback, TestExecutionExceptionHandler) registered via @ExtendWith. Both let you centralize behavior (e.g. screenshot-on-failure) instead of duplicating it in every test — a hallmark of a mature framework and a common design question.
An ITestListener's onTestFailure captures a Selenium screenshot and attaches it to the report for EVERY failing test automatically — no screenshot code repeated in individual tests.
You want a screenshot captured automatically whenever ANY test fails, without adding code to each test. How, in TestNG and JUnit 5?