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 theEnvironment
in theApplicationContext
.
In light of the above, I am closing this issue.