que - test en java
Aplique ''@Rule'' después de cada ''@Test'' y antes de cada ''@After'' en JUnit (3)
Tengo un paquete de prueba donde me desconecto del sistema en @After
y cierro el navegador en @AfterClass
. Estoy tratando de usar @Rule
para tomar una captura de pantalla de prueba fallida usando Selenium para cada método de prueba. Verifiqué manualmente que @Rule
solo se ejecuta antes de cada @Before
pero quiero configurarlo después de @Test
y antes de @After
. No pude encontrar una solución simple. Cualquier ayuda será apreciada.
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;
}
}
La salida que estoy obteniendo es
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
¿Qué pasa con el uso de la regla ExternalResource ?
Parece que usted puede darle suficiente flexibilidad para lo que necesita.
Y si esto no es exactamente lo que necesita, eche un vistazo al código fuente del recurso externo.
Es bastante comprensible cómo implementar una regla, por ejemplo, que funcionará solo después de la invocación de la prueba.
Debido a la forma en que se configuran las reglas, no puede tener una regla que venga después de @before o antes de @after. Puedes pensar en reglas como shells que pones en el método de prueba. El primer shell que debe seguir es @ before / @ after. A partir de entonces se aplican las reglas.
Una forma rápida de hacer lo que quiere hacer es evitar @After por completo. Se puede crear una regla para que tome una captura de pantalla si falla un método y luego ejecute la suya después del código. No es tan bonito como @After, pero funciona. (También implementé TestRule porque MethodRule se ha depreciado).
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);
}
}
}
Todo el trabajo de la regla se hace en una declaración. Un org.junit.runners.model.Statement es una clase que representa un paquete de código. Así que aquí el método de aplicación recibe el paquete de código sobre el que está colocando un shell. Apply devuelve su declaración que ejecuta el paquete de código que le dio y la rodea con una declaración try / catch para detectar las fallas del método.
La salida para este método es:
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
¡Espero que esto ayude!
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
}
}
};
}
}