Подтвердить что ты не робот

Параллельное выполнение тестов

Я заметил, что SBT работает параллельно с моими спецификациями2. Это кажется хорошим, за исключением того, что один из моих тестов включает в себя чтение и запись из файла и, следовательно, непредсказуемость, например. см. ниже.

Есть ли лучшие варианты, чем

  • настройка всех тестов для запуска в последовательном режиме,
  • с использованием отдельных имен файлов и разрывов для каждого теста?
class WriteAndReadSpec extends Specification{
  val file = new File("testFiles/tmp.txt")

  "WriteAndRead" should {
    "work once" in {
      new FileWriter(file, false).append("Foo").close
      Source.fromFile(file).getLines().toList(0) must_== "Foo"
    }
    "work twice" in {
      new FileWriter(file, false).append("Bar").close
      Source.fromFile(file).getLines().toList(0) must_== "Bar"
    }
  }

  trait TearDown extends After {
    def after = if(file.exists) file.delete
  }
}
4b9b3361

Ответ 1

В дополнение к тому, что написано о sbt выше, вы должны знать, что specs2 запускает все примеры ваших спецификаций одновременно по умолчанию.

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

class WriteAndReadSpec extends Specification{
  val file = new File("testFiles/tmp.txt")

  sequential

  "WriteAndRead" should {
   ...
  }
}

Ответ 2

Фиксированная последовательность тестов для наборов может привести к взаимозависимости тестовых случаев и нагрузке на обслуживание.

Я бы предпочел протестировать, не касаясь файловой системы (независимо от того, является ли это бизнес-логикой или кодом сериализации), или если это неизбежно (как для тестирования интеграции с файловыми каналами), тогда будет использоваться создание временных файлов:

// Create temp file.
File temp = File.createTempFile("pattern", ".suffix");
// Delete temp file when program exits.
temp.deleteOnExit();

Ответ 3

Кажется, есть третий вариант, который группирует серийные тесты в конфигурации и запускает их отдельно, одновременно управляя остальными.

Отметьте эту вики, найдите "Приложение для параллельного выполнения" .

Ответ 4

ссылка wiki Пабло Фернандес дал в его ответ довольно хорош, хотя в примере есть небольшая ошибка, которая может отбросить ее (хотя, будучи вики, я могу ее исправить). Здесь project/Build.scala, который на самом деле компилирует и производит ожидаемые фильтры, хотя на самом деле я не тестировал его с помощью тестов.

import sbt._
import Keys._

object B extends Build
{
  lazy val root =
    Project("root", file("."))
      .configs( Serial )
      .settings( inConfig(Serial)(Defaults.testTasks) : _*)
      .settings(
         libraryDependencies ++= specs,
         testOptions in Test := Seq(Tests.Filter(parFilter)),
         testOptions in Serial := Seq(Tests.Filter(serialFilter))
       )
      .settings( parallelExecution in Serial := false : _*)

  def parFilter(name: String): Boolean = !(name startsWith "WriteAndReadSpec")
  def serialFilter(name: String): Boolean = (name startsWith "WriteAndReadSpec")

  lazy val Serial = config("serial") extend(Test)

  lazy val specs = Seq(
        "org.specs2" %% "specs2" % "1.6.1",
        "org.specs2" %% "specs2-scalaz-core" % "6.0.1" % "test"
      )
}

Ответ 5

Другие ответы объяснили, как использовать make, чтобы они выполнялись последовательно.

Пока они действительные ответы, по моему мнению, лучше изменить свои тесты, чтобы они запускались параллельно. (если возможно)

В вашем примере - используйте разные файлы для каждого теста. Если у вас задействован БД - используйте разных (или случайных) пользователей (или независимо от их изоляции) и т.д.