001/*
002 * Copyright 2002-2019 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.test.context.junit.jupiter;
018
019import java.lang.annotation.Documented;
020import java.lang.annotation.ElementType;
021import java.lang.annotation.Retention;
022import java.lang.annotation.RetentionPolicy;
023import java.lang.annotation.Target;
024
025import org.junit.jupiter.api.extension.ExtendWith;
026
027import org.springframework.core.annotation.AliasFor;
028
029/**
030 * {@code @EnabledIf} is used to signal that the annotated test class or test
031 * method is <em>enabled</em> and should be executed if the supplied
032 * {@link #expression} evaluates to {@code true}.
033 *
034 * <p>When applied at the class level, all test methods within that class
035 * are automatically enabled by default as well.
036 *
037 * <p>For basic examples, see the Javadoc for {@link #expression}.
038 *
039 * <p>This annotation may be used as a <em>meta-annotation</em> to create
040 * custom <em>composed annotations</em>. For example, a custom
041 * {@code @EnabledOnMac} annotation can be created as follows.
042 *
043 * <pre style="code">
044 * {@literal @}Target({ElementType.TYPE, ElementType.METHOD})
045 * {@literal @}Retention(RetentionPolicy.RUNTIME)
046 * {@literal @}EnabledIf(
047 *     expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}",
048 *     reason = "Enabled on Mac OS"
049 * )
050 * public {@literal @}interface EnabledOnMac {}
051 * </pre>
052 *
053 * @author Sam Brannen
054 * @since 5.0
055 * @see SpringExtension
056 * @see DisabledIf
057 * @see org.junit.jupiter.api.Disabled
058 */
059@Target({ElementType.TYPE, ElementType.METHOD})
060@Retention(RetentionPolicy.RUNTIME)
061@Documented
062@ExtendWith(EnabledIfCondition.class)
063public @interface EnabledIf {
064
065        /**
066         * Alias for {@link #expression}; only intended to be used if {@link #reason}
067         * and {@link #loadContext} are not specified.
068         *
069         * @see #expression
070         */
071        @AliasFor("expression")
072        String value() default "";
073
074        /**
075         * The expression that will be evaluated to determine if the annotated test
076         * class or test method is <em>enabled</em>.
077         *
078         * <p>If the expression evaluates to {@link Boolean#TRUE} or a {@link String}
079         * equal to {@code "true"} (ignoring case), the test will be enabled.
080         *
081         * <p>Expressions can be any of the following.
082         *
083         * <ul>
084         * <li>Spring Expression Language (SpEL) expression &mdash; for example:
085         * <pre style="code">@EnabledIf("#{systemProperties['os.name'].toLowerCase().contains('mac')}")</pre>
086         * <li>Placeholder for a property available in the Spring
087         * {@link org.springframework.core.env.Environment Environment} &mdash; for example:
088         * <pre style="code">@EnabledIf("${smoke.tests.enabled}")</pre>
089         * <li>Text literal &mdash; for example:
090         * <pre style="code">@EnabledIf("true")</pre>
091         * </ul>
092         *
093         * <p>Note, however, that a <em>text literal</em> which is not the result of
094         * dynamic resolution of a property placeholder is of zero practical value
095         * since {@code @EnabledIf("false")} is equivalent to {@code @Disabled}
096         * and {@code @EnabledIf("true")} is logically meaningless.
097         *
098         * @see #reason
099         * @see #loadContext
100         * @see #value
101         */
102        @AliasFor("value")
103        String expression() default "";
104
105        /**
106         * The reason this test is enabled.
107         *
108         * @see #expression
109         */
110        String reason() default "";
111
112        /**
113         * Whether the {@code ApplicationContext} associated with the current test
114         * should be eagerly loaded in order to evaluate the {@link #expression}.
115         *
116         * <p>Defaults to {@code false} so that test application contexts are not
117         * eagerly loaded unnecessarily. If an expression is based solely on system
118         * properties or environment variables or does not interact with beans in
119         * the test's application context, there is no need to load the context
120         * prematurely since doing so would be a waste of time if the test ends up
121         * being disabled.
122         *
123         * @see #expression
124         */
125        boolean loadContext() default false;
126
127}