Программно вызвать тесты Spock для создания нагрузочного теста - PullRequest
0 голосов
/ 10 июля 2020

Я написал интеграционные тесты в Spock, которые я хотел бы повторно использовать для нагрузочного тестирования. Мне не повезло с программным выполнением тестов Spock. Мне нужно запустить весь spe c как единое целое, которое будет выполняться одновременно для создания нагрузки.

Предыдущие сообщения о переполнении стека на этом topi c устарели (я пробовал кучу из них с не повезло).

Пример Spe c:

class MySpec extends Specification { 
   def 'test'() {
      expect: 1+1 == 2
   }
}

Я хочу иметь возможность запускать это примерно так (выполнено, успешно и не удалось - это AtomicInteger):

executor.submit(() -> {
    try {
        executed.addAndGet(1);
        Result result = mySpecInstance.run() // <-- what should this be.
        if (result.wasSuccessful()) {
            succeeded.addAndGet(1);
        } else {
            failed.addAndGet(1);
            log.error("Failures encountered: {}", result.getFailures());
        }

    } catch (RuntimeException e) {
        log.error("Exception when running runner!", e);
        failed.addAndGet(1);
    }});
Invalid test class 'my.package.MySpec':
  1. No runnable methods]
  • Я попытался использовать new EmbeddedSpecRunner().run(MySpec.class), который выбрасывает
groovy.lang.MissingMethodException: No signature of method: spock.util.EmbeddedSpecRunner.runClass() is applicable for argument types: (Class) values: [class my.package.MySpec]
Possible solutions: getClass(), metaClass(groovy.lang.Closure)

Я использую JDK8 с Groovy 3.0.4 и spock-2.0-M3- groovy -3.0 (spock-junit4).

Обновить :

Ответ из сообщения работает с Groovy -2.4, Spock-1.3, но не с Groovy -3.0 и Spock-2.0.

Спасибо.

1 Ответ

0 голосов
/ 11 июля 2020

Ваша ошибка возникла не потому, что вы, кстати, использовали неправильную версию Spock. Вы можете использовать модуль spock-junit4, если хотите запустить старый JUnit 4 API. Я только что попробовал, метод работает в Spock 1 и все еще в Spock 2, хотя вам, возможно, следует перейти на что-то, что не полагается на более старый API и уровень совместимости.

Ваше сообщение об ошибке просто вызвано тот факт, что вы скопировали и вставили код из другого ответа, не исправляя его. Парень там написал MySuperSpock.Class, что вызывает ошибку, потому что if должно быть MySuperSpock.class с строчными буквами «C» или под Groovy просто MySuperSpock, потому что .class здесь необязательный.

Сообщение об ошибке даже доказывает, что у вас был JUnit 4 на пути к классам и все было найдено, иначе код, импортирующий классы API JUnit 4, не скомпилировался бы вообще. И сообщение об ошибке также объясняет, что не так, и предлагает решение:

Exception in thread "main" groovy.lang.MissingPropertyException: No such property: Class for class: de.scrum_master.testing.MyTest
Possible solutions: class

Видите? Класс MyTest не имеет свойства с именем Class. И одно из возможных решений (в данном случае даже правильное) - использовать .class. Это дает вам подсказку. Кстати, синтаксис MyTest.Class выглядит как ссылка на внутренний класс или, возможно, ссылка на свойство компилятора (для меня тоже).

Обновление: Я только что присмотрелся и заметил, что решение из другого вопроса, который вы сказали, работает для Spock 1.3, на самом деле компилируется и запускается, но бегун JUnit Core делает на самом деле не запускать тесты. Я пробовал с тестами, которые что-то печатают. Кроме того, результат сообщает, что все тесты не пройдены.

Для простых случаев вы можете использовать EmbeddedSpecRunner Спока, который используется внутри для тестирования самого Спока. В Spock 1.x должно быть достаточно иметь JUnit 4 на пути к тестовым классам, в Spock 2, который основан на платформе JUnit 5, вам также необходимо добавить эти зависимости, потому что встроенный runner использует их:

<properties>
  <version.junit>5.6.2</version.junit>
  <version.junit-platform>1.6.2</version.junit-platform>
  <version.groovy>3.0.4</version.groovy>
  <version.spock>2.0-M3-groovy-3.0</version.spock>
</properties>

<!-- JUnit 5 Jupiter platform launcher for Spock EmbeddedSpecRunner  -->
<dependency>
  <groupId>org.junit.platform</groupId>
  <artifactId>junit-platform-launcher</artifactId>
  <version>${version.junit-platform}</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.junit.platform</groupId>
  <artifactId>junit-platform-testkit</artifactId>
  <version>${version.junit-platform}</version>
  <scope>test</scope>
</dependency>

Затем вы можете запустить такой тест:

def spockRunner = new EmbeddedSpecRunner()
def spockResult = spockRunner.runClass(MyTest)
println "Tests run: " + spockResult.runCount
println "Tests ignored: " + spockResult.ignoreCount
println "Tests failed: " + spockResult.failureCount

Кстати, методы получения *Count устарели в Spock 2, но они все еще работают. Вы можете легко заменить их на более новые, я просто хотел опубликовать код, который работает без изменений в обеих версиях Spock 1.x и 2.x.

Обновление 2: Если вы хотите запустить один и тот же тест, например, 10x одновременно, каждый в своем потоке, в Groovy простой способ сделать это:

(1..10).collect { Thread.start { new EmbeddedSpecRunner().runClass(MyTest) } }*.join()

Или, может быть, немного легче читать с несколькими разрывами строки:

(1..10)
  .collect { 
    Thread.start { new EmbeddedSpecRunner().runClass(MyTest) }
  }
  *.join()

Я предполагаю, что вы знакомы с collect (аналогично map для Java потоков) и оператор звездочка-точка *. (вызов метода для каждого элемента в итерируемом объекте).

...