Применяйте "@ Rule "после каждого" @Test "и перед каждым" @After " в JUnit
у меня есть набор тестов, где я выхожу из системы в @After
и закрытие браузера в @AfterClass
. Я пытаюсь использовать @Rule
принять неудачный скриншот теста с использованием Селена для каждого метода тестирования. Я проверил вручную, что @Rule
работает только перед каждым @Before
но я хочу настроить его после @Test
и перед @After
. Я не мог найти простого решения. Любая помощь будет оценена.
public class MorgatgeCalculatorTest {
@Before
public void before(){
System.out.println("I am before");
}
@BeforeClass
public static void beforeclass(){
System.out.println("I am beforeclass");
}
@Test
public void test(){
System.out.println("I am Test");
}
@Test
public void test2(){
System.out.println("I am Test2");
}
@After
public void after(){
System.out.println("I am after");
}
@AfterClass
public static void afterclass(){
System.out.println("I am afterclass");
}
@Rule
ExpensiveExternalResource ExpensiveExternalResource = new ExpensiveExternalResource();
static class ExpensiveExternalResource implements MethodRule {
public ExpensiveExternalResource(){
System.out.println("I am rule");
}
@Override
public Statement apply(Statement arg0, FrameworkMethod arg1, Object arg2) {
// TODO Auto-generated method stub
return null;
}
}
выход, который я получаю, это
I am beforeclass
I am rule
I am before
I am Test
I am after
I am rule
I am before
I am Test2
I am after
I am afterclass
3 ответов
из-за способа настройки правил вы не можете иметь правило, которое приходит после @before или до @after. Вы можете думать о правилах, таких как оболочки, которые вы ставите на метод тестирования. Первая оболочка для продолжения - @before / @after. После этого применяются правила @.
быстрый способ сделать то, что вы хотите сделать, - это избежать @After. Правило может быть создано так, что оно будет делать снимок экрана, если метод терпит неудачу, а затем выполнить Ваш после кода. Это не так красиво, как @После, но это работает. (также я реализовал TestRule, потому что MethodRule был амортизирован).
public class MortgageCalculatorTest {
@Before
public void before(){
System.out.println("I am before");
}
@BeforeClass
public static void beforeclass(){
System.out.println("I am beforeclass");
}
@Test
public void test(){
System.out.println("I am a Test");
}
@Test
public void test2(){
System.out.println("I am a Failed Test");
fail();
}
@AfterClass
public static void afterclass(){
System.out.println("I am afterclass");
}
@Rule
public ExpensiveExternalResource ExpensiveExternalResource = new ExpensiveExternalResource();
public static class ExpensiveExternalResource implements TestRule {
// public ExpensiveExternalResource(){}
public class ExpansiveExternalResourceStatement extends Statement{
private Statement baseStatement;
public ExpansiveExternalResourceStatement(Statement b){
baseStatement = b;
}
@Override
public void evaluate() throws Throwable {
try{
baseStatement.evaluate();
}catch(Error e){
System.out.println("I take a Screenshot");
throw e;
}finally{
after();
}
}
//Put your after code in this method!
public void after(){
System.out.println("I am after");
}
}
public Statement apply(Statement base, Description description) {
return new ExpansiveExternalResourceStatement(base);
}
}
}
вся работа правила выполняется в инструкции. Орг.тесты JUnit.бегуны.модель.Оператор-это класс, представляющий собой пакет кода. Так вот применить метод получает пакет кода,который вы помещаете в оболочку. Apply возвращает ваш оператор, который выполняет пакет кода, который вы ему дали, и окружает его инструкцией try / catch, чтобы поймать ошибки метода.
выход для этого метода:
I am beforeclass
I am before
I am a Test
I am after
I am before
I am a Failed Test
I take a Screenshot
I am after
I am afterclass
надеюсь, что это помогает!
public class ScreenshotTestRule implements MethodRule {
public Statement apply(final Statement statement, final FrameworkMethod frameworkMethod, final Object o) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
try {
statement.evaluate();
} catch (Throwable t) {
captureScreenshot(frameworkMethod.getName());
throw t; // rethrow to allow the failure to be reported to JUnit
} finally {
tearDown();
}
}
public void tearDown() {
//logout to the system;
}
public void captureScreenshot(String fileName) {
try {
new File("target/surefire-reports/screenshot").mkdirs(); // Insure directory is there
FileOutputStream out = new FileOutputStream("target/surefire-reports/screenshot/screenshot-" + fileName + ".png");
out.write(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES));
out.close();
} catch (Exception e) {
// No need to crash the tests if the screenshot fails
}
}
};
}
}
Как насчет использования ExternalResource правило ?
Похоже, вы можете дать вам достаточно гибкости для того, что вам нужно.
И если это не совсем то, что вам нужно, взглянем на исходный код внешних ресурсов.
вполне понятно, как реализовать правило, например, которое будет работать только после вызова теста.