Dave Syer opened SPR-7754 and commented

Now that @Profile (and "profile" generally) has a meaning in the framework, the old test support for detecting system properties looks like it has an awkward name. In Spring 3.1 terms, what @IfProfileValue does is detect key-value pairs in the Environment (not profiles).

One simple thing we should definitely do is add a ProfileValueSource that can pull values from the Environment.

More radically, maybe we could rename @IfProfileValue(name=,value=) to @Environment(key=,value=).

Another suggestion is that we could provide a way to activate profiles declaratively for tests or test classes. Something I've been playing with is this (new components ProfileSuite and @ActiveProfile):

@RunWith(Suite.class)
@SuiteClasses({ HsqlTest.class, DerbyTest.class })
public class JdbcDaoIntegrationTests {

    @RunWith(ProfileSuite.class)
    @SuiteClasses({ JdbcSearchableJobInstanceDaoTests.class, JdbcSearchableJobExecutionDaoTests.class,
            JdbcSearchableStepExecutionDaoTests.class })
    public static abstract class BaseTest {
    }

    @ActiveProfile("hsql")
    public static class HsqlTest extends BaseTest {
    }

    @ActiveProfile("derby")
    public static class DerbyTest extends BaseTest {
    }

}

It says: run these three test classes twice each, once with profile "hsql" and once with profile "derby". This has the nice feature that @EnvironmentValue can still be honoured inside the individual tests (per method).


Issue Links: - #13625 SystemProfileValueSource is not very compatible with the new 3.1 default system property profiles - #12615 TestContext framework should support declarative configuration of bean definition profiles - #13622 Allow overriding @ActiveProfiles in test classes with system property - #16300 Introduce annotation to skip test based on active Spring profile

6 votes, 7 watchers

Comment From: spring-projects-issues

Chris Beams commented

Assigning to Sam for comments (and possibly implementation of course).

Sam, if you haven't gotten familiar with the Environment/Profiles support, this is probably a great time to do so.

Dave, with regard to the @Environment annotation, it might be more accurate to think of @Property or @EnvironmentProperty or something to that effect. What's really being evaluated in this situation is properties as accessed through the environment.

It should be noted that @Profile and @IfProfileValue have pretty close semantics already. In the case of @Profile, it indicates a @Component/@Configuration class should loaded only if the profile(s) specified in the value attribute are currently active. In the case of @IfProfileValue, it indicates, that a @Test method should be executed only if the key/value (property) is present and matching.

I'm not sure how widely used @IfProfileValue is right now. It would be nice to consider some kind of unification of semantics in any case.

Comment From: spring-projects-issues

Dave Syer commented

A more radical idea would be to remove @IfProfileValue and replace it with @Profile. This means re-thinking Environment a little so we can avoid the "special" key name ("springProfiles" is a key name in the Environment which is special because it switches on profiles). We can do that by sticking to the old @IfProfileValue style definition of a profile value (it has to be explicit about its key name), so you would just have Environment with key-value pairs, and none of them would have any special status. @Profile (and similar feature in XML) would need to name the key as well as the value(s), just like @IfProfileValue does now, and then the latter could be simply removed in favour of the former.

Comment From: spring-projects-issues

Helena Edelson commented

I like the move to @Profile idea and have been starting to play around with an environment module that in part leverages the Sigar jar to detect environment data, explicitly filtered via Spring.

Comment From: spring-projects-issues

Dave Syer commented

Another suggestion: an environment matcher utility so that you can use imperative instead of declarative approach to skipping tests by profile. E.g. somethng like this

@Test
public void shouldOnlyWorkWithOracle() {
    assumeTrue(TestEnvironmentUtils.activeProfiles().contains("oracle"));
    ...
}

I guess TestEnvironmentUtils would need to access the ApplicationContext and extract the environment (so maybe it would have to be a field in the test case). With this approach a user has access to all the profile and property information (name=value pairs) in the Environment.

The inverse

Comment From: spring-projects-issues

Neale Upstone commented

A thought to feed in here...

Just working with a number of Spring 3 based tests at the moment, and we have un-DRY things like:

@IfProfileValue(name = "test_category", values = { "all", "integration-test" })
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/integration-test.xml" })
public class SomeIntegrationTest {
    ...
}

What's missing is the Stereotype support that we have for components.

I'd like all Spring annotations to be able to be targetted to an annotation type so that I can just have:

@RunWith(SpringJUnit4ClassRunner.class)
@IntegrationTest
public class SomeIntegrationTest {
    ...
}

with the @ContextConfiguration and @IfProfileValue on our @IntegrationTest annotation definition.

Comment From: spring-projects-issues

Sam Brannen commented

@Neale: I've captured your comments in a new JIRA issue: #12483

Cheers,

Sam

Comment From: spring-projects-issues

Caleb Cushing commented

deprecate the original annotation. I would like something either based on PropertySourceMerger which I believe can merge properties, the environment etc, and/or support SpEL for disabling tests. As it stands I've realized that @IfProfileValue isn't actually valuable to me.

Comment From: sbrannen

Since @IfProfileValue is specific to our JUnit 4 support and since JUnit 4 does not provide an extension mechanism for enabling/disabling tests, we have decided to leave the @IfProfileValue in place as-is as long as we continue to support JUnit 4.

Regarding other topics discussed in this issue, many of the requested features and/or proposals are already possible with JUnit Jupiter (in JUnit 5) and Spring's support for JUnit Jupiter.

  • JUnit Jupiter provides numerous built-in annotations for Conditional Test Execution such as @DisabledIfSystemProperty, @EnabledIfEnvironmentVariable, etc.
  • Users can also implement their own custom ExecutionCondition.
  • Spring provides @EnabledIf and @DisabledIf annotations that are based on SpEL expressions -- which can optionally access beans and the Environment in the ApplicationContext.

In light of the above, I am closing this issue.