t.me/atinfo_chat Telegram группа по автоматизации тестирования

Как реализовать перезапуск Rerun/retry упавших тестов с помощью Java + Junit4 + Cucumber + Selenium

Теги: #<Tag:0x00007f7489baf950> #<Tag:0x00007f7489baf888> #<Tag:0x00007f7489baf6f8> #<Tag:0x00007f7489baf5e0> #<Tag:0x00007f7489baf478> #<Tag:0x00007f7489baf338> #<Tag:0x00007f7489baf1f8> #<Tag:0x00007f7489baf130>

У меня не получилось реализовать перезапуск упавших тестов в своем фремворке (Java + Junit4 + Cucumber + Selenium) репорты Allure

Хотелось бы чтоб упавший тест перегонялся заново 1-2 раза.

Пример здесь

import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
 
/**
 * Предоставляет возможность автоматического перезапуска тестов,
 * завершившихся неудачей
 */
public class RerunFailedRunner extends BlockJUnit4ClassRunner {
 
    /**
     * Для фиксирования количества попыток выполнения тестов
     */
    private HashMap<FrameworkMethod, Integer> rerunMethods = 
                                new HashMap<FrameworkMethod, Integer>();
     
    public RerunFailedRunner(Class<?> klass) 
                                throws InitializationError {
        super(klass);
    }
 
    @Override
    protected void runChild(FrameworkMethod method, RunNotifier notifier) {
        FailerListener listener = new FailerListener();
        // подключаем listener для определения результата теста
        notifier.addListener(listener);
        int retryCount = 2;
        for (int i = 1; i <= retryCount; i++) {
            rerunMethods.put(method, i);
            // здесь подключаются RunListener для логирования
            super.runChild(method, notifier);
            // здесь отключаются
            if (!listener.isTestFailed()) {
                // если тест выполнился успешно, больше не запускаем
                break;
            }
        }
        notifier.removeListener(listener);
    }
 
    /**
     * Изменяем имя метода для отображения в отчете
     */
    @Override
    protected String testName(FrameworkMethod method) {
        Integer attempt = rerunMethods.get(method);
        if (attempt != null && attempt > 1) {
            return method.getName() + attempt;
        } else {
            return method.getName();
        }
    }
 
    /**
     * Слушатель выполнения теста, фиксирующий его неудачное завершение
     */
    private class FailerListener extends RunListener {
        private boolean isFailed = false;
 
        @Override
        public void testFailure(Failure failure) throws Exception {
            isFailed = true;
        }
 
        public boolean isTestFailed() {
            return isFailed;
        }
    }
}

Такое ощущение, что это счастье не сможет работать с Cucumber

package steps;

import cucumber.api.Scenario;
import cucumber.api.java.After;
import io.qameta.allure.Allure;
import libs.ActionsWithElements;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;

import java.io.ByteArrayInputStream;

public class ScreenshotHooks {
    private final ActionsWithElements actionsWithElements;

    public ScreenshotHooks(ActionsWithElements actionsWithElements) {
        this.actionsWithElements = actionsWithElements;
    }
    
    @After
    public void afterScenario(Scenario scenario) {
        if (!scenario.getStatus().equals("failed")) {
            actionsWithElements.getWebDriver().quit();
            return;
        }
        
        Allure.addAttachment("Screenshot", "image/png", new ByteArrayInputStream(((TakesScreenshot) actionsWithElements.getWebDriver()).getScreenshotAs(OutputType.BYTES)), "png");
        actionsWithElements.getWebDriver().quit();
    }
}

А второй вариант пробовали?

зачем перезапускать упавший тест?
если упал валидно - заводите ошибку
если неправильный тест - перепишите, добейтесь того, чтобы его не надо было ретраить

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

public class Retry implements TestRule {
	private int retryCount;

	public Retry(int retryCount) {
		this.retryCount = retryCount;
	}

	public Statement apply(Statement base, Description description) {
		return statement(base, description);
	}

	private Statement statement(final Statement base, final Description description) {
		return new Statement() {
			@Override
			public void evaluate() throws Throwable {
				Throwable caughtThrowable = null;

				// implement retry logic here
				for (int i = 0; i < retryCount; i++) {
					try {
						base.evaluate();
						return;
					} catch (Throwable t) {
						caughtThrowable = t;
						System.err.println(description.getDisplayName() + ": run " + (i+1) + " failed");
					}
				}
				System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures");
				throw caughtThrowable;
			}
		};
	}
 }