тестирование повторных вызовов по периоду времени - PullRequest
0 голосов
/ 01 марта 2020

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

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

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

Я ищу что-то вроде invocationCount, но со вкусом времени. Когда указано, оно должно повторяться, как invocationCount, пока остается оставшееся время. Кто-нибудь делал что-то подобное?

1 Ответ

0 голосов
/ 20 апреля 2020

На высоком уровне вот что вам нужно сделать, чтобы добиться этого:

  1. Создайте пользовательскую аннотацию, которая может использоваться для указания, сколько итераций нужно выполнить и для какой продолжительности.
  2. Теперь для всех методов тестирования, которым требуется эта возможность, аннотируйте их пользовательской аннотацией, определенной в (1).
  3. Определите базовый класс, который реализует интерфейс TestNG org.testng.IHookable.
  4. В методе run() проанализируйте аннотацию, а затем используйте службу исполнителя для управления продолжительностью и итерациями.

Пользовательская аннотация

import static java.lang.annotation.ElementType.METHOD;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({METHOD})
public @interface Repeatable {

  int forSeconds() default 0;

  int iterations() default 1;
}

База class (Это необходимо, только если у вас есть несколько таких тестовых классов с одинаковой потребностью)

import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.testng.IHookCallBack;
import org.testng.IHookable;
import org.testng.ITestResult;

public class AbstractTestCase implements IHookable {

  @Override
  public void run(IHookCallBack callBack, ITestResult testResult) {
    Repeatable repeatable =
        testResult.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Repeatable.class);
    if (repeatable == null) {
      callBack.runTestMethod(testResult);
      return;
    }
    Callable<Void> task =
        () -> {
          for (int i = 1; i <= repeatable.iterations(); i++) {
            System.err.println("Running iteration : " + i);
            callBack.runTestMethod(testResult);
          }
          return null;
        };
    ExecutorService service = Executors.newFixedThreadPool(1);
    try {
      List<Future<Void>> result =
          service.invokeAll(
              Collections.singletonList(task), repeatable.forSeconds(), TimeUnit.SECONDS);
      service.shutdown();
      result.forEach(
          r -> {
            try {
              r.get();
            } catch (InterruptedException | ExecutionException e) {
              throw new RuntimeException(e);
            }
          });
    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    }
  }
}

Тестовый класс

import java.util.concurrent.TimeUnit;
import org.testng.annotations.Test;

public class TestClassSample extends AbstractTestCase {

  @Test
  @Repeatable(forSeconds = 5, iterations = 10)
  public void runTask() throws InterruptedException {
    TimeUnit.SECONDS.sleep(1);
    System.err.println("Woke up after sleeping for 1 second");
  }
}

Выход выполнения

Running iteration : 1
Woke up after sleeping for 1 second
Running iteration : 2
Woke up after sleeping for 1 second
Running iteration : 3
Woke up after sleeping for 1 second
Running iteration : 4
Woke up after sleeping for 1 second
Running iteration : 5
Running iteration : 6



java.util.concurrent.CancellationException
    at java.util.concurrent.FutureTask.report(FutureTask.java:121)
    at java.util.concurrent.FutureTask.get(FutureTask.java:192)
    at com.rationaleemotions.AbstractTestCase.lambda$run$1(AbstractTestCase.java:42)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at com.rationaleemotions.AbstractTestCase.run(AbstractTestCase.java:39)
    at org.testng.internal.MethodInvocationHelper.invokeHookable(MethodInvocationHelper.java:255)
    at org.testng.internal.TestInvoker.invokeMethod(TestInvoker.java:594)
    at org.testng.internal.TestInvoker.invokeTestMethod(TestInvoker.java:174)
    at org.testng.internal.MethodRunner.runInSequence(MethodRunner.java:46)
    at org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:821)
    at org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:147)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:588)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:384)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:378)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:337)
    at org.testng.SuiteRunner.run(SuiteRunner.java:286)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1214)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1136)
    at org.testng.TestNG.runSuites(TestNG.java:1066)
    at org.testng.TestNG.run(TestNG.java:1034)
    at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66)
    at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:110)


===============================================
Default Suite
Total tests run: 1, Passes: 0, Failures: 1, Skips: 0
===============================================


Process finished with exit code 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...