Excluding a non param test in parameterized test class

前端 未结 10 813
粉色の甜心
粉色の甜心 2020-12-02 19:32

Is there any annotation in JUnit to exclude a non param test in parameterized test class?

相关标签:
10条回答
  • 2020-12-02 20:28

    No. The best practice is to move those non-parameterized tests to a different class (.java file)

    0 讨论(0)
  • 2020-12-02 20:33

    For those who wants the parameters come from java function instead of annotations:

    @ParameterizedTest
    @MethodSource("provideStringsForIsBlank")
    void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input, boolean expected) {
        assertEquals(expected, Strings.isBlank(input));
    }
    
    private static Stream<Arguments> provideStringsForIsBlank() {
        return Stream.of(
          Arguments.of(null, true),
          Arguments.of("", true),
          Arguments.of("  ", true),
          Arguments.of("not blank", false)
        );
    }
    

    source: https://www.baeldung.com/parameterized-tests-junit-5

    0 讨论(0)
  • 2020-12-02 20:35

    Assuming you use Parametrized.class to run your test class - mark all non-parametrized tests as @Ignored. Otherwise you can make a static inner class to group all your parametrized tests and another - for non-parametrized.

    0 讨论(0)
  • 2020-12-02 20:36

    It appears that TestNG does not suffer from this problem. I'm not that desperate so I modified the builtin Parameterized class to support this feature. Just annotate applicable tests as @NonParameterized. Note that this class only works with its on annotations, i.e. check your imports.

    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;
    
    /**
     * <p>
     * The custom runner <code>Parameterized</code> 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.
     * </p>
     * For example, to test a Fibonacci function, write:
     *
     * <pre>
     * &#064;RunWith(Parameterized.class)
     * public class FibonacciTest {
     *     &#064;Parameters
     *     public static List&lt;Object[]&gt; 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;
     *     }
     *
     *     &#064;Test
     *     public void test() {
     *         assertEquals(fExpected, Fibonacci.compute(fInput));
     *     }
     * }
     * </pre>
     * <p>
     * Each instance of <code>FibonacciTest</code> will be constructed using the
     * two-argument constructor and the data values in the
     * <code>&#064;Parameters</code> method.
     * </p>
     */
    public class Parameterized extends Suite {
    
        /**
         * Annotation for a method which provides parameters to be injected into the
         * test class constructor by <code>Parameterized</code>
         */
        @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<Object[]> fParameterList;
    
            TestClassRunnerForParameters(Class<?> type,
                    List<Object[]> 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<Throwable> errors) {
                validateOnlyOneConstructor(errors);
            }
    
            @Override
            protected Statement classBlock(RunNotifier notifier) {
                return childrenInvoker(notifier);
            }
    
            @Override
            protected List<FrameworkMethod> computeTestMethods() {
                List<FrameworkMethod> ret = super.computeTestMethods();
                for (Iterator<FrameworkMethod> 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<Object[]> parameterList, int i)
                throws InitializationError {
                super(type, parameterList, i);
            }
    
            protected boolean isParameterized() {
                return false;
            }
        }
    
        private final ArrayList<Runner> runners = new ArrayList<Runner>();
    
        /**
         * Only called reflectively. Do not use programmatically.
         */
        public Parameterized(Class<?> klass) throws Throwable {
            super(klass, Collections.<Runner> emptyList());
            List<Object[]> 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<Runner> getChildren() {
            return runners;
        }
    
        @SuppressWarnings("unchecked")
        private List<Object[]> getParametersList(TestClass klass)
                throws Throwable {
            return (List<Object[]>) getParametersMethod(klass).invokeExplosively(
                    null);
        }
    
        private FrameworkMethod getParametersMethod(TestClass testClass)
                throws Exception {
            List<FrameworkMethod> 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());
        }
    
    }
    

    Update: I'm trying to get this sort of thing added to junit.

    0 讨论(0)
提交回复
热议问题