在每个’@Test’之后和JUnit中的每个’@After’之前应用’@Rule’

我有一个测试套件,我在@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 

由于规则的设置方式,您不能拥有@after之前或@after之前的规则。 你可以考虑像测试方法那样的shell之类的规则。 继续进行的第一个shell是@ 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是一个表示代码包的类。 所以这里apply方法接收你放置shell的代码包。 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规则怎么样?
看起来你可以为你提供足够的灵活性来满足你的需求。
如果这不是您所需要的,请查看外部资源的源代码 。
如何实现例如仅在测试调用之后才能工作的规则是非常容易理解的。