Исключение безпараметрического теста в параметризованном тестовом classе

Есть ли какая-либо аннотация в JUnit для исключения непараметрического теста в параметризованном тестовом classе?

    JUnit 5

    Начиная с версии Junit 5.0.0 вы можете теперь аннотировать свои методы тестирования с помощью @ParameterizedTest . Поэтому нет необходимости во внутренних classах. Существует множество способов предоставить аргументы параметризованному тесту помимо ValueSource, как показано ниже. Подробнее см. В официальном руководстве пользователя junit :

     import org.junit.jupiter.api.Test; import org.junit.jupiter.api.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; public class ComponentTest { @ParameterizedTest @ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba" }) public void testCaseUsingParams(String candidate) throws Exception { } @Test public void testCaseWithoutParams() throws Exception { } } 

    JUnit 4

    Если вы все еще используете Junit 4 (я тестировал с помощью v4.8.2), вы можете использовать бегун Enclosed в сочетании с внутренними classами и параметризированным бегуном:

     import org.junit.Test; import org.junit.experimental.runners.Enclosed; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @RunWith(Enclosed.class) public class ComponentTest { @RunWith(Parameterized.class) public static class ComponentParamTests { @Parameters ... @Test public void testCaseUsingParams() throws Exception { } } public static class ComponentSingleTests { @Test public void testCaseWithoutParams() throws Exception { } } } 

    Я только что узнал, что можно использовать JUnitParams . Я использовал один из моих тестов, чтобы использовать его, и он работает красиво.

    Нет. Лучше всего переместить те непараметрированные тесты в другой class (.java-файл)

    Zohhak test runner – это более простой способ параметризации конкретных тестов. Спасибо, Петр!

    Я смог сделать что-то очень похожее на ответ Мэтью Мэдсона и счел полезным создать базовый class для инкапсуляции настроек и общих вспомогательных функций между одиночными и параметрическими тестами. Это работает без использования Enclosed.class .

      @RunWith(Suite.class) @SuiteClasses({ComponentTest.ComponentParamTests.class, ComponentTest.ComponentSingleTests.class}) public class ComponentTest { public static class TestBase { @Spy ... @Before ... } @RunWith(Parameterized.class) public static class ComponentParamTests extends TestBase{ @Parameter ... @Parameters ... @Test ... } public static class ComponentSingleTests extends TestBase{ @Test ... } } 

    Похоже, что TestNG не страдает от этой проблемы . Я не отчаянный, поэтому я модифицировал встроенный class Parameterized для поддержки этой функции. Просто аннотируйте применимые тесты как @NonParameterized. Обратите внимание, что этот class работает только с аннотациями, то есть проверяет ваш импорт.

     import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.junit.Test; import org.junit.runner.Runner; import org.junit.runner.notification.RunNotifier; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.Suite; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; import org.junit.runners.model.Statement; import org.junit.runners.model.TestClass; /** * 

    * The custom runner Parameterized implements parameterized tests. * When running a parameterized test class, instances are created for the * cross-product of the test methods and the test data elements. *

    * For example, to test a Fibonacci function, write: * *
     * @RunWith(Parameterized.class) * public class FibonacciTest { * @Parameters * public static List<Object[]> data() { * return Arrays.asList(new Object[][] { * Fibonacci, * { {0, 0}, {1, 1}, {2, 1}, {3, 2}, {4, 3}, {5, 5}, * {6, 8}}}); * } * * private int fInput; * * private int fExpected; * * public FibonacciTest(int input, int expected) { * fInput = input; * fExpected = expected; * } * * @Test * public void test() { * assertEquals(fExpected, Fibonacci.compute(fInput)); * } * } * 

    *

    * Each instance of FibonacciTest will be constructed using the * two-argument constructor and the data values in the * @Parameters method. *

    */ public class Parameterized extends Suite { /** * Annotation for a method which provides parameters to be injected into the * test class constructor by Parameterized */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public static @interface Parameters { } /** * Annotation for a methods which should not be parameterized */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public static @interface NonParameterized { } private class TestClassRunnerForParameters extends BlockJUnit4ClassRunner { private final int fParameterSetNumber; private final List fParameterList; TestClassRunnerForParameters(Class type, List parameterList, int i) throws InitializationError { super(type); fParameterList = parameterList; fParameterSetNumber = i; } @Override public Object createTest() throws Exception { return getTestClass().getOnlyConstructor().newInstance( computeParams()); } private Object[] computeParams() throws Exception { try { return fParameterList.get(fParameterSetNumber); } catch (ClassCastException e) { throw new Exception(String.format( "%s.%s() must return a Collection of arrays.", getTestClass().getName(), getParametersMethod( getTestClass()).getName())); } } @Override protected String getName() { return String.format("[%s]", fParameterSetNumber); } @Override protected String testName(final FrameworkMethod method) { return String.format("%s[%s]", method.getName(), fParameterSetNumber); } @Override protected void validateConstructor(List errors) { validateOnlyOneConstructor(errors); } @Override protected Statement classBlock(RunNotifier notifier) { return childrenInvoker(notifier); } @Override protected List computeTestMethods() { List ret = super.computeTestMethods(); for (Iterator i = ret.iterator(); i.hasNext();) { FrameworkMethod frameworkMethod = (FrameworkMethod) i.next(); if (isParameterized() ^ !frameworkMethod.getMethod().isAnnotationPresent( NonParameterized.class)) { i.remove(); } } return ret; } protected boolean isParameterized() { return true; } } private class TestClassRunnerForNonParameterized extends TestClassRunnerForParameters { TestClassRunnerForNonParameterized(Class type, List parameterList, int i) throws InitializationError { super(type, parameterList, i); } protected boolean isParameterized() { return false; } } private final ArrayList runners = new ArrayList(); /** * Only called reflectively. Do not use programmatically. */ public Parameterized(Class klass) throws Throwable { super(klass, Collections. emptyList()); List parametersList = getParametersList(getTestClass()); if (parametersList.size() > 0) { try { runners.add(new TestClassRunnerForNonParameterized( getTestClass() .getJavaClass(), parametersList, 0)); } catch (Exception e) { System.out.println("No non-parameterized tests."); } } try { for (int i = 0; i < parametersList.size(); i++) { runners.add(new TestClassRunnerForParameters(getTestClass() .getJavaClass(), parametersList, i)); } } catch (Exception e) { System.out.println("No parameterized tests."); } } @Override protected List getChildren() { return runners; } @SuppressWarnings("unchecked") private List getParametersList(TestClass klass) throws Throwable { return (List) getParametersMethod(klass).invokeExplosively( null); } private FrameworkMethod getParametersMethod(TestClass testClass) throws Exception { List methods = testClass .getAnnotatedMethods(Parameters.class); for (FrameworkMethod each : methods) { int modifiers = each.getMethod().getModifiers(); if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)) return each; } throw new Exception("No public static parameters method on class " + testClass.getName()); } }

    Обновление: я пытаюсь добавить в junit такую ​​штуку.

    Предполагая, что вы используете Parametrized.class для запуска вашего тестового classа – отметьте все непараметризированные тесты как @Ignored. В противном случае вы можете сделать статический внутренний class для группировки всех ваших параметризованных тестов, а другой – для непараметризированного.

    Я сделал что-то похожее на решение Мэтью. Однако я создал два новых java-файла, которые расширяют текущий файл, так что ComponentSingleTests не запускаются дважды. Таким образом, они могут совместно использовать общие переменные-члены и вспомогательные методы из родительского classа. Проблема, с которой я столкнулась с решением Мэтью, заключалась в том, что мой единственный тест выполнялся дважды, а не один раз, поскольку Enclosed.class (который расширяет class Suite.class) заставит ваш тестовый запуск дважды, как описано в этой ссылке. Запретить запуск тестов junit

    ComponentTest.java

     public class ComponentTest { public int sharedMemberVariables; ... } 

    ComponentParamTests.java

     import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @RunWith(Parameterized.class) public class ComponentParamTests extends ComponentTest { @Parameters ... @Test public void testCaseUsingParams() throws Exception { } } 

    ComponentSingleTests.java

     import org.junit.Test; public class ComponentSingleTests { @Test public void testCaseWithoutParams() throws Exception { ... } }