매개 변수화 된 테스트 이름 변경
JUnit4에서 매개 변수화 된 테스트를 사용할 때 고유 한 사용자 정의 테스트 케이스 이름을 설정하는 방법이 있습니까?
기본값 [Test class].runTest[n]
을 의미있는 것으로 변경하고 싶습니다 .
이 기능은 JUnit 4.11 로 만들어졌습니다 .
매개 변수가 지정된 테스트의 이름을 변경하려면 다음과 같이 말합니다.
@Parameters(name="namestring")
namestring
문자열은 다음과 같은 특수 자리 표시자를 가질 수 있습니다.
{index}
-이 인수 세트의 인덱스 기본값namestring
은{index}
입니다.{0}
-이 테스트 호출의 첫 번째 매개 변수 값{1}
-두 번째 매개 변수 값- 등등
테스트의 최종 이름은 namestring
아래에 표시된대로 테스트 방법의 이름이며 뒤에 괄호 가 붙습니다 .
예를 들어 ( 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 Parameterized 러너를 사용할 수 없었고 대신 이름 개념을 이해하는 이름을 직접 작성하십시오 (이름을 설정하는 방법에 대한 질문으로 이어짐).
JUnit 관점에서 증분을 전달하는 대신 (또는 추가로) 쉼표로 구분 된 인수를 전달하면 좋을 것입니다. TestNG가이를 수행합니다. 이 기능이 중요한 경우 www.junit.org에서 참조하는 yahoo 메일 링리스트에 의견을 남길 수 있습니다.
JUnit 4.3.1을 사용할 때 최근에 동일한 문제가 발생했습니다. LabelledParameterized라는 Parameterized를 확장하는 새로운 클래스를 구현했습니다. JUnit 4.3.1, 4.4 및 4.5를 사용하여 테스트되었습니다. @Parameters 메서드에서 각 매개 변수 배열의 첫 번째 인수에 대한 String 표현을 사용하여 Description 인스턴스를 재구성합니다. 이 코드는 다음에서 확인할 수 있습니다.
http://code.google.com/p/migen/source/browse/trunk/java/src/.../LabelledParameterized.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 (LabelledParameterized.class)로 변경하면됩니다.
JUnit의 이후 릴리스 에서이 문제를 해결하는지 알 수는 없지만, 공동 개발자가 모두 업데이트해야하고 재 툴링보다 우선 순위가 높기 때문에 JUnit을 업데이트 할 수 없습니다. 따라서 클래스의 작업은 여러 버전의 JUnit에서 컴파일 할 수 있습니다.
참고 : 위에 나열된 것과 같이 다른 JUnit 버전에서 실행되도록 일부 리플렉션 jiggery-pokery가 있습니다. 구체적의 JUnit 4.3.1 버전이 발견 될 수있다 여기서 , JUnit을 4.4 및 4.5 그리고 여기 .
와 Parameterized
모델로, 나는 내 자신의 사용자 정의 테스트 러너 / 제품군을 썼다 - 절반 밖에 시간 정도 걸렸다. 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);
}
}
junit4.8.2부터는 단순히 Parameterized 클래스를 복사하여 MyParameterized 클래스를 작성할 수 있습니다. TestClassRunnerForParameters에서 getName () 및 testName () 메소드를 변경하십시오.
JUnitParams를 시도 할 수도 있습니다 : http://code.google.com/p/junitparams/
당신은 같은 방법을 만들 수 있습니다
@Test
public void name() {
Assert.assertEquals("", inboundFileName);
}
항상 사용하지는 않지만 정확히 143의 테스트 번호를 알아내는 것이 유용합니다.
Assert 및 친구들에게 정적 가져 오기를 광범위하게 사용하므로 어설 션을 재정의하기가 쉽습니다.
private <T> void assertThat(final T actual, final Matcher<T> expected) {
Assert.assertThat(editThisToDisplaySomethingForYourDatum, actual, expected);
}
예를 들어, 테스트 클래스에 "name"필드를 추가하고 생성자에서 초기화하여 테스트 실패시이를 표시 할 수 있습니다. 각 테스트마다 매개 변수 배열의 첫 번째 요소로 전달하십시오. 또한 데이터 레이블을 지정하는 데 도움이됩니다.
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}
});
}
그 중 어느 것도 나를 위해 일하지 않았으므로 Parameterized의 소스를 얻었고 수정하여 새로운 테스트 러너를 만들었습니다. 많이 바꿀 필요는 없었지만 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;
}
}
A workaround would be to catch and nest all Throwables into a new Throwable with a custom message that contains all information about the parameters. The message would appear in the stack trace. This works whenever a test fails for all assertions, errors and exceptions as they are all subclasses of Throwable.
My code looks like this:
@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);
}
}
}
The stack trace of the failed test is:
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
Check out JUnitParams as dsaff mentioned, works using ant to build parameterized test method descriptions in the html report.
This was after trying LabelledParameterized and finding that it although it works with eclipse it does not work with ant as far as the html report is concerned.
Cheers,
Since the parameter accessed (e.g. with "{0}"
always returns the toString()
representation, one workaround would be to make an anonymous implementation and override toString()
in each case. For example:
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...
);
}
참고URL : https://stackoverflow.com/questions/650894/changing-names-of-parameterized-tests
'Programing' 카테고리의 다른 글
원 안에 임의의 점을 생성합니다 (균일하게) (0) | 2020.05.12 |
---|---|
Git 저장소의 처음 두 커밋을 결합 하시겠습니까? (0) | 2020.05.12 |
클래스 내의 파이썬 호출 함수 (0) | 2020.05.12 |
.htm VS .html (0) | 2020.05.12 |
이클립스 선폭 마커가 있습니까? (0) | 2020.05.12 |