Выполнить код до и после спецификации

У меня есть простая спецификация с несколькими случаями в ней:

class MySpec extends Specification {

  "Something" should {

    "case 1" in {
      ...
    }

    "case 2" in {
      ...
    }
  }
}

Теперь мне нужно запустить приложение, запустить все случаи и завершить работу приложения. Запуск/остановка приложения занимает много времени, и я не хочу, чтобы это происходило в каждом случае.

Как запустить код перед запуском и после завершения всех случаев?

Ответ 1

Я придумал следующее решение, основанное на ответе cmbaxter.

import org.specs2.specification.Step

trait BeforeAllAfterAll extends Specification {
  // see http://bit.ly/11I9kFM (specs2 User Guide)
  override def map(fragments: =>Fragments) = 
    Step(beforeAll) ^ fragments ^ Step(afterAll)

  protected def beforeAll()
  protected def afterAll()
}

Затем смешайте BeforeAllAfterAll в Specification и реализуйте методы beforeAll и afterAll:

class MySpec extends Specification with BeforeAllAfterAll {

  def beforeAll() {
    println("Doing setup work...")
  }

  def afterAll() {
    println("Doing shutdown work...")
  }

  "Something" should {

    "case 1" in {
      ...
    }

    "case 2" in {
      ...
    }
  }
}

Наконец, извлеките инициализацию, чтобы поделиться им между спецификациями:

trait InApplication extends BeforeAllAfterAll {
  def beforeAll() {
    println("Doing setup work...")
  }

  def afterAll() {
    println("Doing shutdown work...")
  }
}

class MySpec extends Specification with InApplication {

  "Something" should {

    "case 1" in {
      ...
    }

    "case 2" in {
      ...
    }
  }
}

Ответ 2

Хорошо, как упоминалось в моем комментарии, у меня на самом деле была такая же проблема. Мне нужно было проверить Unfiltered конечные точки, и наилучшим способом для каждой спецификации было запустить Unfiltered сервер с одной конечной точкой, запустить спецификацию и затем выключить сервер. Для этого я сначала определил базовую спецификацию, подобную этой:

import org.specs2.mutable.Specification

abstract class SpecificationBase extends Specification{
  //Do setup work here
  step{
    println("Doing setup work...")
    success
  }

  //Include the real spec from the derived class
  include(spec)

  //Do shutdown work here
  step{
    println("Doing shutdown work...")
    success
  }  

  /**
   * To be implemented in the derived class.  Returns the real specification
   * @return Specification
   */
  def spec:Specification
}

В основном, этот базовый класс собирает полную спецификацию в качестве шага настройки и шаг отрыва с реальной спецификацией (определенной в конкретном классе спецификации), зажатой посередине. Таким образом, тест с использованием этого базового класса будет выглядеть следующим образом:

class MySpec extends SpecificationBase{ def spec = 
  new Specification{
    "A request to do something" should{
      "be successful in case 1" in {
        println("Testing case 1")
        success
      }
      "be successful in case 2" in {
        println("Testing case 2")
        success
      }      
    }
  }
}

Когда вы запустите это, вы увидите:

Doing setup work...
Testing case 1
Testing case 2
Doing shutdown work...

Это не идеально, но он работает. Есть ли другой способ (и, возможно, более чистый/лучший)? Возможно, но это одно из решений, которое вы могли бы изучить.

Ответ 3

Хорошо, это старый вопрос, но он может помочь кому-то.

Я использую Play Framework. В моих тестах я использовал org.scalatest.BeforeAndAfterAll

Пример:

import org.scalatest.BeforeAndAfterAll

class MySpec extends PlaySpec with BeforeAndAfterAll {

  "Some test" must {
    "print a text" in {

      println("Some test")
      2 mustBe 2
    }
  }

  override def beforeAll(): Unit = {
    println("Before")
  }

  override def afterAll(): Unit = {
    println("After")
  }
}