之后的每个“@测试”和JUnit的每个“@After”之前应用“@rule”(Apply '

2019-06-27 06:41发布

我有一个测试套件,在那里我退出系统中的@After和关闭浏览器@AfterClass 。 我试图用@Rule使用Selenium对每个测试方法把失败的测试截图。 我手动检查了@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

Answer 1:

由于方式,规则设置,你不能有@Before后或@After之前出现的规则。 你能想到的一样,你把测试方法炮弹规则。 第一个壳去是@前/后@。 此后@rules被应用。

一个快速的方法做你想要做的是避免@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);

        }


    }
}

该规则的所有的工作都在一份声明中完成的。 甲org.junit.runners.model.Statement是表示代码束的类。 所以这里的适用方法接收的,你是把一个壳周围的代码包。 应用的回报您的语句执行的,你给它,并用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

希望这可以帮助!



Answer 2:

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
                }
            }
        };
    }
}


Answer 3:

怎么样使用ExternalResource规则?
看起来你也可以给你足够的灵活性,以你所需要的。
如果这不正是你所需要的,看看在源代码外部的资源。
这是相当understandble如何实现例如一个规则,只有测试调用之后的工作。



文章来源: Apply '@Rule' after each '@Test' and before each '@After' in JUnit