2011-12-19 44 views
10

我使用JUnit 4.8.2开发了一套Selenium测试(实际上是WebDriver支持的Selenium)。一旦测试失败,我希望测试能够自动截取浏览器的截图。所有的测试都是从SeleniumBaseTestCase继承而来,然后大多数从SeleniumBastTestCaseWithCompany(它使用@Before@After方法创建并通过Selenium清理常用测试数据)进一步继承。如何在测试失败之后但在任何@After方法之前让JUnit 4.8运行代码?

我试着在SeleniumBaseTestCase加入TestWatchman一个子类作为@Rule,覆盖TestWatchmanfailed方法采取截图。问题在于,在调用TestWatchmanfailed方法之前,正在运行清理测试数据的@After方法,因此屏幕截图都是清理的最后一步,而不是失败的测试。

寻找到它一点点,似乎TestWatchmanapply方法只是调用传递Statement的评估方法(只露法),它调用@After方法,留下TestWatchman(或任何其他Rule)没有机会据我所知,在执行测试和@After方法之间插入任何代码。

我也看到,创建一个自定义Runner改变创造了Statement S左右,与定制@AfterFailure注解的方法之前@After方法(这样的截图可以采取这样的方法@AfterFailure)运行的方法,但是这依赖于重写BlockJUnit4ClassRunnerwithAfters方法,根据建议使用规则的documentation,该方法已被弃用并且变为私有方法。

我在SO上发现了另一个关于@Rule lifecycle的回答,它使得它听起来像这样在JUnit 4.8中可能是不可能的,但在JUnit 4.10中可能是可能的。如果这是正确的,那么就足够公平了,我只想先确认一下。

任何想法,在一个优雅的和面向未来的方式,我可以实现我想要的东西将不胜感激!

回答

7

你的分析是正确的,在任何规则之前,@Befores和@Afters被添加到语句列表中。在@Rule@After@Rule之前被执行之后,@Before被执行。你如何解决这个问题取决于你如何灵活使用SeleniumBaseTestCaseWithCompany

最简单的方法是删除@Before/@After方法并将其替换为ExternalResource。这可能看起来像:

public class BeforeAfterTest { 
    @Rule public TestRule rule = new ExternalResource() { 
     protected void before() throws Throwable { System.out.println("externalResource before"); } 
     protected void after() { System.out.println("externalResource after"); } 
    }; 

    @Test public void testHere() { System.out.println("testHere"); } 
} 

这给:

externalResource before 
testHere 
externalResource after 

此字段可以放入你的基类,所以它被继承/重写。您在@After和您的规则之间订购时遇到的问题随即消失,因为您可以使用@RuleChain(4.10,而不是4.8)来订购您的规则。

如果您不能更改SeleniumBaseTestCaseWithCompany,则可以扩展BlockJUnit4ClassRunner,但不要覆盖withAfters,而是覆盖BlockJUnit4ClassRunner#methodBlock()。然后你可以打电话给超级。methodBlock,并根据需要重新排列语句[*]。

[*]您可以复制代码并重新排序行,但规则是私有的,因此不能从子类调用。

+0

是的,我认为升级JUnit是要走的路 - 在4.8.2中我看不到特别令人满意的解决方案。 我在SeleniumBaseTestCase上有一个受保护的TestWatcher来截取屏幕截图,而RuleChain以此为唯一规则。然后在'SeleniumBaseTestCaseWithCompany'中我有一个ExternalResource来创建/删除公司,并且我将超类的RuleChain映射到屏幕截图和创建/删除规则中。似乎很好地工作,谢谢。 – Rowan 2011-12-21 16:15:16

+0

只是一个笔记。在4.11中,你可以在一个方法上指定@Rule,这样你就可以覆盖该方法而不是对一个字段进行遮蔽。但4.11还没有发布。 – 2011-12-21 16:23:53

+0

啊,很高兴知道 - 映射变量是我唯一感到不安的唯一... – Rowan 2011-12-21 16:28:30

相关问题