Search code examples
scalaseleniumjunitselenium-webdriverspecs2

How to use JUnit's @Rule annotation with Scala Specs2 tests?


In our project we use Scala Specs2 together with Selenium. I'm trying to implement screenshot-on-failure mechanism "in a classic way (link)" for my tests, using JUnit annotations, but, the rule doesn't called on test failure at all.

The structure of the test is as follows:

class Tests extends SpecificationWithJUnit{

      trait Context extends LotsOfStuff {
        @Rule
        val screenshotOnFailRule = new ScreenshotOnFailRule(driver)
      }

      "test to verify stuff that will fail" should {
        "this test FAILS" in new Context {
         ...
      }
}

The ScreenshotOnFailRule looks like this:

class ScreenshotOnFailRule (webDriver: WebDriver) extends TestWatcher {

  override def failed(er:Throwable, des:Description) {
    val scrFile = webDriver.asInstanceOf[TakesScreenshot].getScreenshotAs(OutputType.FILE)
    FileUtils.copyFile(scrFile, new File(s"/tmp/automation_screenshot${Platform.currentTime}.png"))
  }
}

I understand that probably it doesn't work now because the tests aren't annotated with @Test annotation. Is it possible to annotate the Specs2 tests with JUnit @Rule annotation?


Solution

  • According to this question it seems as if JUnit Rules aren't supported. But you could try to make use of the AroundExample trait:

    import org.specs2.execute.{AsResult, Result}
    import org.specs2.mutable._
    import org.specs2.specification.AroundExample
    
    class ExampleSpec extends Specification with AroundExample {
    
      // execute tests in sequential order
      sequential
    
      "The 'Hello world' string" should {
        "contain 11 characters" in  {
          "Hello world" must have size (10)
        }
    
       // more tests..
      }
    
      override protected def around[T](t: => T)(implicit ev: AsResult[T]): Result = {
        try {
          AsResult.effectively(t)
        } catch {
          case e: Throwable => {
            // take screenshot here
            throw e
          }
        }
      }
    }