Пишу на джаве. В свое время создавал 2 слушателя: 1) имплементирующий ITestListener для перегрузки событий TestNG - onTestFailure и т.п. 2) экстендящий AbstractWebDriverEventListener для перегрузки событий WebDriver - beforeFindBy и т.п.
Собственно, первый слушатель можно подключить к Base классу посредством аннотации @Listeners. Второй нужно подключать при помощи EventFiringWebDriver с его регистратором.
По скриншотам: создавал аннотацию AfterTestFailure, которую привязал к методу снятия скринов. Далее, при генерации события onTestFailure вызывал аннотированный метод:
   @Override
    public void onTestFailure(ITestResult iTestResult) {
        try {
            Object testCase = iTestResult.getInstance();
            Method testMethod = iTestResult.getMethod().getConstructorOrMethod().getMethod();
 
            logger.error("Fail: " + testMethod.getName(), iTestResult.getThrowable());
 
            invokeAnnotatedMethods(testCase, testMethod, AfterTestFailure.class);
        } catch (Exception e) {
            logger.error(e);
        }
    }
 
   private static void invokeAnnotatedMethods(Object testCase, Method testMethod, Class<? extends Annotation> annotation) throws InvocationTargetException, IllegalAccessException {
        Method[] methods = testCase.getClass().getMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(annotation)) {
                method.setAccessible(true);
                method.invoke(testCase, testMethod);
            }
        }
    }
 
По поводу красоты: не перестану настаивать на том, что она тут даром не нужна. Главное, зафиксировать метод, на котором все посыпалось, и получить стектрейс. А красивенькие отчетики выдаст сам TestNG плагин в том же Jenkins.
P.S. Мы пишем тесты не для красоты, а для проверки функционала, UI и т.п. И в случае чего, нам нужно быстро определить точку, которая вызвала сбой. А если я буду хэндлить эксепшены завуалирвоанным кастомным текстом по типу "X method failed", то мне придется в итоге потратить гораздо больше времени на анализ причин сбоя. Мне кажется, что красивенький парсинг стектрейса - это необоснованная трата времени.