Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Scalatest - как создать параллельный тест во время выполнения

Автор вопроса: Andrea BiselloОтветов: 2

Бег

package com.thron.qa.tests

import org.scalatest.{FunSuite, ParallelTestExecution}
import org.scalatest.concurrent.Eventually

class ParallelRuntimeTest extends FunSuite with Eventually with ParallelTestExecution{

  Vector.range(0,10).foreach(iteration => {
    test ("test number  n " + iteration.toString) {
      succeed
    }
  })

}

я получаю создание теста во время выполнения: итерация по вектору строится на тестах, и каждый отдельный тест имеет статус успеха, как вы можете видеть в Идее

введите здесь описание изображения

Теперь я хочу распараллелить эти тесты

обычно я использую .par для распараллеливания операций, поэтому код становится

Vector.range(0,10).par.foreach(iteration => {
    test ("test number  n " + iteration.toString) {
      succeed
    }
  })

но в этом случае я получаю эту ошибку:

Исключение или ошибка привели к прерыванию выполнения: два потока попытались изменить внутренние данные FunSuite, которые должны быть изменены только потоком, создающим объект. Вероятно, это означает, что подкласс позволил ссылке this уйти во время построения, и какой-то другой поток попытался вызвать методы "testsFor" или "test" для объекта до того, как первый поток завершил свое построение. java.util.ConcurrentModificationException: два потока попытались изменить внутренние данные FunSuite, которые должны быть изменены только потоком, создающим объект. Вероятно, это означает, что подкласс позволил ссылке this уйти во время построения, и какой-то другой поток попытался вызвать методы "testsFor" или "test" для объекта до того, как первый поток завершил свое построение.

как создать тест во время выполнения и запустить его параллельно?

Благодарность

scalascalatest

Ответы

Ответ 1 · рейтинг 3 · Andrey Tyukin

Команда test не запускает никаких тестов. Он просто регистрирует тестовый пример, прикрепляя к нему строковое имя. Это не требует ресурсов и практически мгновенно. Поэтому нет необходимости регистрировать тестовые случаи параллельно. Как показывает ваше сообщение об ошибке, в любом случае невозможно зарегистрировать их параллельно.

Создавайте тесты последовательно, они будут запускаться параллельно автоматически:

import org.scalatest.{FunSuite, ParallelTestExecution}
import org.scalatest.concurrent.Eventually

class ParallelRuntimeTest
extends FunSuite
   with Eventually
   with ParallelTestExecution {

  for (i <- (0 to 59)) {
    test ("test number  n " + i) {
      Thread.sleep(1000)
      succeed
    }
  }

}

Если вы протестируете его, вы заметите, что это занимает примерно 15 секунд вместо минуты (я думаю, это потому, что количество потоков по умолчанию, используемых для тестов, равно четырем, поэтому 60/4 = 15).

Ответ 2 · рейтинг 2 · KZapagol

Как упомянул @Andrey Tyukin, по умолчанию sbt выполняет все задачи параллельно и в той же JVM, что и сам sbt. Поскольку каждый тест сопоставляется с задачей, по умолчанию тесты также выполняются параллельно.

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

parallelExecution in Test := false,
parallelExecution in IntegrationTest := false

Похоже, есть проблема с использованием ParallelTestExecution и "sbt test" -scalaTest 3.0.x (https://github.com/scalatest/scalest/issues/898). Однако обходной путь для этой проблемы находится в Overriding Distributor.

class Example extends FunSpec with ParallelTestExecution with StressTest {
  describe("Example") {
    for (i <- 1 to poolSize) {
      it(s"test ${i} should run in parallel") {
        info(s"example ${i} start")
        Thread.sleep(5000)
        info(s"example ${i} end")
      }
    }
  }
}

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы