source

매개 변수화된 테스트 이름 변경

factcode 2022. 8. 19. 20:46
반응형

매개 변수화된 테스트 이름 변경

JUnit4에서 파라미터화된 테스트를 사용할 때 커스텀 테스트 케이스명을 설정할 수 있는 방법이 있습니까?

- 을 [Test class].runTest[n] 있는 으로. - 의미 있는 것으로. - 의미 있는 것으로. - 의미 있는 것으로.

이 기능을 통해 JUnit 4.11이 되었습니다.

매개 변수화된 테스트의 이름 변경을 사용하려면 다음과 같이 입력합니다.

@Parameters(name="namestring")

namestring 는 문자열로, 다음과 같은 특수한 플레이스 홀더를 가질 수 있습니다.

  • {index}- 이 인수 집합의 인덱스입니다.기본값은 입니다.{index}.
  • {0}이의 첫 값. - 이 파라미터 값.
  • {1}두 값 - '두 번째 파라미터 값'
  • 등등

테스트의 최종명은 다음과 같이 테스트 방법의 이름이 되고 그 뒤에 괄호 안의 가 표시됩니다.

를 들어 (「」의)Parameterized★★★★★

@RunWith(Parameterized.class)
static public class FibonacciTest {

    @Parameters( name = "{index}: fib({0})={1}" )
    public static Iterable<Object[]> data() {
        return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
                { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } });
    }

    private final int fInput;
    private final int fExpected;

    public FibonacciTest(int input, int expected) {
        fInput= input;
        fExpected= expected;
    }

    @Test
    public void testFib() {
        assertEquals(fExpected, fib(fInput));
    }

    private int fib(int x) {
        // TODO: actually calculate Fibonacci numbers
        return 0;
    }
}

을 붙이다testFib[1: fib(1)=1] ★★★★★★★★★★★★★★★★★」testFib[4: fib(4)=3] . . . . . . . .testFib이름의 일부는 의 메서드 이름입니다.@Test를 참조해 주세요.

JUnit 4.5를 보면, 그 논리는 Parameterized 클래스 내의 프라이빗 클래스 내에 묻혀 있기 때문에 JUnit 4.5의 주자는 그것을 지원하지 않는 것이 분명합니다.JUnit 매개 변수화된 런너를 사용할 수 없으며, 대신 이름의 개념을 이해할 수 있는 고유한 런너를 만들 수 없습니다(이것에 의해, 이름을 어떻게 설정할지에 대한 질문으로 이어집니다).

JUnit의 관점에서 볼 때 단순히 증분만 전달하는 것이 아니라 쉼표로 구분된 인수를 전달하는 것이 좋습니다.TestNG는 이렇게 합니다.이 기능이 중요한 경우 www.junit.org에서 참조하는 야후 메일링 리스트에 코멘트를 붙일 수 있습니다.

최근 JUnit 4.3.1을 사용할 때도 같은 문제가 발생하였습니다.Labeled Parameterized라고 하는 파라미터화된 클래스를 확장한 새로운 클래스를 구현했습니다.JUnit 4.3.1, 4.4 및 4.5를 사용하여 테스트되었습니다.@Parameters 메서드에서 각 파라미터 배열의 첫 번째 인수의 String 표현을 사용하여 Description 인스턴스를 재구성합니다.이 코드는 다음 사이트에서 확인할 수 있습니다.

http://code.google.com/p/migen/source/browse/trunk/java/src/.../Labelled Parameterized.java?r=3789

및 그 사용 예를 다음에 나타냅니다.

http://code.google.com/p/migen/source/browse/trunk/java/src/.../ServerBuilderTest.java?r=3789

Eclipse에서는 테스트 설명 형식이 훌륭합니다.이것이 불합격 테스트를 찾기 쉽게 하기 때문에 제가 원하던 것입니다.앞으로 며칠 또는 몇 주 동안 수업을 더 다듬고 문서화할 것입니다.블리딩 엣지를 원하는 경우 URL의 ? 부분을 드롭합니다. :- )

이를 사용하려면 해당 클래스(GPL v3)를 복사하고 파라미터 목록의 첫 번째 요소가 센스 있는 라벨이라고 가정하여 @RunWith(Parameterized.class)를 @RunWith(Labelled Parameterized.class)로 변경하기만 하면 됩니다.

JUnit의 새로운 릴리스가 이 문제를 해결할지는 모르겠지만, JUnit을 업데이트해도 모든 공동 개발자도 업데이트해야 하고 재툴링보다 우선 순위가 더 높기 때문에 업데이트할 수 없습니다.따라서 클래스 내의 작업은 여러 버전의 JUnit에서 컴파일할 수 있습니다.


주의: 위에 나열된 다양한 JUnit 버전에서 실행할 수 있도록 반사 조작 포커리가 있습니다.JUnit 4.3.1 전용 버전은 여기에, JUnit 4.4 및 4.5 전용 버전은 여기에 있습니다.

와 함께Parameterized모델로서 커스텀 테스트 러너/스위트를 작성했습니다.약 30분밖에 걸리지 않았습니다.Darrenp의 것과는 조금 다르다.LabelledParameterized첫 번째 파라미터에 의존하지 않고 이름을 명시적으로 지정할 수 있습니다.toString().

어레이를 싫어하기 때문에 어레이도 사용하지 않습니다.:)

public class PolySuite extends Suite {

  // //////////////////////////////
  // Public helper interfaces

  /**
   * Annotation for a method which returns a {@link Configuration}
   * to be injected into the test class constructor
   */
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.METHOD)
  public static @interface Config {
  }

  public static interface Configuration {
    int size();
    Object getTestValue(int index);
    String getTestName(int index);
  }

  // //////////////////////////////
  // Fields

  private final List<Runner> runners;

  // //////////////////////////////
  // Constructor

  /**
   * Only called reflectively. Do not use programmatically.
   * @param c the test class
   * @throws Throwable if something bad happens
   */
  public PolySuite(Class<?> c) throws Throwable {
    super(c, Collections.<Runner>emptyList());
    TestClass testClass = getTestClass();
    Class<?> jTestClass = testClass.getJavaClass();
    Configuration configuration = getConfiguration(testClass);
    List<Runner> runners = new ArrayList<Runner>();
    for (int i = 0, size = configuration.size(); i < size; i++) {
      SingleRunner runner = new SingleRunner(jTestClass, configuration.getTestValue(i), configuration.getTestName(i));
      runners.add(runner);
    }
    this.runners = runners;
  }

  // //////////////////////////////
  // Overrides

  @Override
  protected List<Runner> getChildren() {
    return runners;
  }

  // //////////////////////////////
  // Private

  private Configuration getConfiguration(TestClass testClass) throws Throwable {
    return (Configuration) getConfigMethod(testClass).invokeExplosively(null);
  }

  private FrameworkMethod getConfigMethod(TestClass testClass) {
    List<FrameworkMethod> methods = testClass.getAnnotatedMethods(Config.class);
    if (methods.isEmpty()) {
      throw new IllegalStateException("@" + Config.class.getSimpleName() + " method not found");
    }
    if (methods.size() > 1) {
      throw new IllegalStateException("Too many @" + Config.class.getSimpleName() + " methods");
    }
    FrameworkMethod method = methods.get(0);
    int modifiers = method.getMethod().getModifiers();
    if (!(Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
      throw new IllegalStateException("@" + Config.class.getSimpleName() + " method \"" + method.getName() + "\" must be public static");
    }
    return method;
  }

  // //////////////////////////////
  // Helper classes

  private static class SingleRunner extends BlockJUnit4ClassRunner {

    private final Object testVal;
    private final String testName;

    SingleRunner(Class<?> testClass, Object testVal, String testName) throws InitializationError {
      super(testClass);
      this.testVal = testVal;
      this.testName = testName;
    }

    @Override
    protected Object createTest() throws Exception {
      return getTestClass().getOnlyConstructor().newInstance(testVal);
    }

    @Override
    protected String getName() {
      return testName;
    }

    @Override
    protected String testName(FrameworkMethod method) {
      return testName + ": " + method.getName();
    }

    @Override
    protected void validateConstructor(List<Throwable> errors) {
      validateOnlyOneConstructor(errors);
    }

    @Override
    protected Statement classBlock(RunNotifier notifier) {
      return childrenInvoker(notifier);
    }
  }
}

예를 들어 다음과 같습니다.

@RunWith(PolySuite.class)
public class PolySuiteExample {

  // //////////////////////////////
  // Fixture

  @Config
  public static Configuration getConfig() {
    return new Configuration() {
      @Override
      public int size() {
        return 10;
      }

      @Override
      public Integer getTestValue(int index) {
        return index * 2;
      }

      @Override
      public String getTestName(int index) {
        return "test" + index;
      }
    };
  }

  // //////////////////////////////
  // Fields

  private final int testVal;

  // //////////////////////////////
  // Constructor

  public PolySuiteExample(int testVal) {
    this.testVal = testVal;
  }

  // //////////////////////////////
  // Test

  @Ignore
  @Test
  public void odd() {
    assertFalse(testVal % 2 == 0);
  }

  @Test
  public void even() {
    assertTrue(testVal % 2 == 0);
  }

}

JUnitParams를 시험해 보는 것도 좋습니다.http://code.google.com/p/junitparams/

junit4.8.2부터는 파라미터화 클래스를 복사하는 것만으로 나만의 My Parameterized 클래스를 만들 수 있습니다.TestClassRunnerForParameters에서 getName() 메서드와 testName() 메서드를 변경합니다.

다음과 같은 방법을 만들 수 있습니다.

@Test
public void name() {
    Assert.assertEquals("", inboundFileName);
}

항상 사용하는 것은 아니지만, 143번이 어떤 시험인지 정확하게 알아내는 것이 도움이 될 것입니다.

Assert 및 친구를 위해 스태틱 Import를 광범위하게 사용하고 있기 때문에 Assertion을 재정의하는 것은 간단합니다.

private <T> void assertThat(final T actual, final Matcher<T> expected) {
    Assert.assertThat(editThisToDisplaySomethingForYourDatum, actual, expected);
}

예를 들어, 생성자에서 초기화된 "이름" 필드를 테스트 클래스에 추가하고 테스트 실패 시 표시할 수 있습니다.각 테스트에 사용할 파라미터 배열의 첫 번째 요소로 전달합니다.또한 데이터에 라벨을 붙이는 데도 도움이 됩니다.

public ExampleTest(final String testLabel, final int one, final int two) {
    this.testLabel = testLabel;
    // ...
}

@Parameters
public static Collection<Object[]> data() {
    return asList(new Object[][]{
        {"first test", 3, 4},
        {"second test", 5, 6}
    });
}

어느 것도 나에게 효과가 없었기 때문에 나는 파라미터화된 소스를 입수하여 그것을 수정하여 새로운 테스트 러너를 작성했다.크게 바꿀 필요는 없었지만, IT는 기능하고 있습니다!!!

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.internal.runners.ClassRoadie;
import org.junit.internal.runners.CompositeRunner;
import org.junit.internal.runners.InitializationError;
import org.junit.internal.runners.JUnit4ClassRunner;
import org.junit.internal.runners.MethodValidator;
import org.junit.internal.runners.TestClass;
import org.junit.runner.notification.RunNotifier;

public class LabelledParameterized extends CompositeRunner {
static class TestClassRunnerForParameters extends JUnit4ClassRunner {
    private final Object[] fParameters;

    private final String fParameterFirstValue;

    private final Constructor<?> fConstructor;

    TestClassRunnerForParameters(TestClass testClass, Object[] parameters, int i) throws InitializationError {
        super(testClass.getJavaClass()); // todo
        fParameters = parameters;
        if (parameters != null) {
            fParameterFirstValue = Arrays.asList(parameters).toString();
        } else {
            fParameterFirstValue = String.valueOf(i);
        }
        fConstructor = getOnlyConstructor();
    }

    @Override
    protected Object createTest() throws Exception {
        return fConstructor.newInstance(fParameters);
    }

    @Override
    protected String getName() {
        return String.format("%s", fParameterFirstValue);
    }

    @Override
    protected String testName(final Method method) {
        return String.format("%s%s", method.getName(), fParameterFirstValue);
    }

    private Constructor<?> getOnlyConstructor() {
        Constructor<?>[] constructors = getTestClass().getJavaClass().getConstructors();
        Assert.assertEquals(1, constructors.length);
        return constructors[0];
    }

    @Override
    protected void validate() throws InitializationError {
        // do nothing: validated before.
    }

    @Override
    public void run(RunNotifier notifier) {
        runMethods(notifier);
    }
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public static @interface Parameters {
}

private final TestClass fTestClass;

public LabelledParameterized(Class<?> klass) throws Exception {
    super(klass.getName());
    fTestClass = new TestClass(klass);

    MethodValidator methodValidator = new MethodValidator(fTestClass);
    methodValidator.validateStaticMethods();
    methodValidator.validateInstanceMethods();
    methodValidator.assertValid();

    int i = 0;
    for (final Object each : getParametersList()) {
        if (each instanceof Object[])
            add(new TestClassRunnerForParameters(fTestClass, (Object[]) each, i++));
        else
            throw new Exception(String.format("%s.%s() must return a Collection of arrays.", fTestClass.getName(), getParametersMethod().getName()));
    }
}

@Override
public void run(final RunNotifier notifier) {
    new ClassRoadie(notifier, fTestClass, getDescription(), new Runnable() {
        public void run() {
            runChildren(notifier);
        }
    }).runProtected();
}

private Collection<?> getParametersList() throws IllegalAccessException, InvocationTargetException, Exception {
    return (Collection<?>) getParametersMethod().invoke(null);
}

private Method getParametersMethod() throws Exception {
    List<Method> methods = fTestClass.getAnnotatedMethods(Parameters.class);
    for (Method each : methods) {
        int modifiers = each.getModifiers();
        if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))
            return each;
    }

    throw new Exception("No public static parameters method on class " + getName());
}

public static Collection<Object[]> eachOne(Object... params) {
    List<Object[]> results = new ArrayList<Object[]>();
    for (Object param : params)
        results.add(new Object[] { param });
    return results;
}
}

회피책은 파라미터에 대한 모든 정보를 포함하는 커스텀메시지와 함께 모든 슬로우 가능 파일을 캡처하여 새로운 슬로우 가능에 네스트하는 것입니다.스택 트레이스에 메시지가 표시됩니다.이는 모든 어설션, 오류 및 예외에 대한 테스트가 실패할 때마다 작동합니다. 이는 모두 Throwable의 하위 클래스이기 때문입니다.

코드는 다음과 같습니다.

@RunWith(Parameterized.class)
public class ParameterizedTest {

    int parameter;

    public ParameterizedTest(int parameter) {
        super();
        this.parameter = parameter;
    }

    @Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][] { {1}, {2} });
    }

    @Test
    public void test() throws Throwable {
        try {
            assertTrue(parameter%2==0);
        }
        catch(Throwable thrown) {
            throw new Throwable("parameter="+parameter, thrown);
        }
    }

}

실패한 테스트의 스택트레이스는 다음과 같습니다

java.lang.Throwable: parameter=1
    at sample.ParameterizedTest.test(ParameterizedTest.java:34)
Caused by: java.lang.AssertionError
    at org.junit.Assert.fail(Assert.java:92)
    at org.junit.Assert.assertTrue(Assert.java:43)
    at org.junit.Assert.assertTrue(Assert.java:54)
    at sample.ParameterizedTest.test(ParameterizedTest.java:31)
    ... 31 more

dsaff에서 설명한 바와 같이 JUnitParams를 체크하여 html 보고서에 파라미터화된 테스트 방식의 설명을 작성합니다.

이는 Labeled Parameterized를 시도하여 이클립스에서는 동작하지만 html 리포트에 관한 한 개미에서는 동작하지 않는다는 것을 알게 된 후입니다.

건배.

접근했기 를 들어, 「」를 사용해):"{0}"는 항상 반환됩니다.toString()하여 '어나니머스 실장'을 덮어쓰는 입니다.toString()를 들어 과 같습니다예를 들어 다음과 같습니다.

public static Iterable<? extends Object> data() {
    return Arrays.asList(
        new MyObject(myParams...) {public String toString(){return "my custom test name";}},
        new MyObject(myParams...) {public String toString(){return "my other custom test name";}},
        //etc...
    );
}

가 호출하고 .toString()오브젝트 오버라이드 하는 경우toString() 시험 됩니다

예를 들면, 다른 투고에서 대답했습니다.https://stackoverflow.com/a/67023556/1839360

파라미터 값을 테스트명에 포함할 경우 다음과 같은 작업을 수행할 수 있습니다.

@ParameterizedTest(name="{index} {arguments} then return false" )
@ValueSource(strings = {"false","FALSE","   ","123","abc"})
@DisplayName("When Feature JVM argument is ")
void test_Feature_JVM_Argument_Is_Empty_Or_Blank_Strings_Or_False(String params) {
    System.setProperty("FeatureName", params);
    assertFalse(Boolean.parseBoolean(System.getProperty("FeatureName")));
}

테스트 이름은 다음과 같습니다.

JUnit 테스트 이미지

언급URL : https://stackoverflow.com/questions/650894/changing-names-of-parameterized-tests

반응형