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

Бег

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» для объекта до того, как первый поток завершил свое построение.

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

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


person Andrea Bisello    schedule 11.03.2019    source источник


Ответы (2)


Команда 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).

person Andrey Tyukin    schedule 11.03.2019
comment
Истинный. моя проблема была с идеей Intellij, которая не будет выполнять тест параллельно. поэтому я заставляю ide искать параллелизм, который sbt делает по умолчанию. Спасибо. - person Andrea Bisello; 11.03.2019

Как упомянул @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")
      }
    }
  }
}
person KZapagol    schedule 11.03.2019