Skip to content

Commit 509cc80

Browse files
authored
Make @PendingFeatureIf repeatable (#1030) (#1191)
1 parent 6bb1e76 commit 509cc80

5 files changed

Lines changed: 139 additions & 9 deletions

File tree

docs/extensions.adoc

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -218,15 +218,20 @@ and only if all iterations become successful will be marked as failing. But if t
218218
does reference valid data variables, the individual iterations where the condition holds are
219219
deemed pending and each will individually fail as soon as it would be successful without this annotation.
220220

221-
[source,groovy]
221+
[source,groovy,indent=0]
222222
----
223-
@PendingFeatureIf({ os.windows })
224-
def "I'm not yet implemented on windows, but I am on other operating systems"() { ... }
223+
include::{sourcedir}/extension/PendingFeatureIfDocSpec.groovy[tag=example-a]
225224
226-
@PendingFeatureIf({ sys.targetEnvironment == "prod" })
227-
def "This feature isn't deployed out to production yet, and isn't expected to pass"() { ... }
225+
include::{sourcedir}/extension/PendingFeatureIfDocSpec.groovy[tag=example-b]
228226
----
229227

228+
It is also supported to have multiple `@PendingFeatureIf` annotations or a mixture of `@PendingFeatureIf` and
229+
`@PendingFeature`, for example to ignore certain exceptions only under certain conditions.
230+
231+
[source,groovy,indent=0]
232+
----
233+
include::{sourcedir}/extension/PendingFeatureIfDocSpec.groovy[tag=example-c]
234+
----
230235

231236
=== Stepwise
232237

docs/release_notes.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ include::include.adoc[]
1818

1919
- `@IgnoreIf` is now repeatable
2020

21+
- `@PendingFeatureIf` is now repeatable
22+
2123
- `@Requires` is now repeatable
2224

2325
- `@See` is now repeatable

spock-core/src/main/java/spock/lang/PendingFeatureIf.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@
66
import org.spockframework.runtime.extension.builtin.PreconditionContext;
77
import org.spockframework.util.Beta;
88

9-
import java.lang.annotation.ElementType;
10-
import java.lang.annotation.Retention;
11-
import java.lang.annotation.RetentionPolicy;
12-
import java.lang.annotation.Target;
9+
import java.lang.annotation.*;
1310

1411
/**
1512
* Marks the annotated feature or selected iterations as {@link PendingFeature} if the
@@ -31,6 +28,7 @@
3128
@Retention(RetentionPolicy.RUNTIME)
3229
@Target({ElementType.METHOD})
3330
@ExtensionAnnotation(PendingFeatureIfExtension.class)
31+
@Repeatable(PendingFeatureIf.Container.class)
3432
public @interface PendingFeatureIf {
3533

3634
/**
@@ -58,4 +56,14 @@
5856
* @return reason why this feature is pending
5957
*/
6058
String reason() default "";
59+
60+
/**
61+
* @since 2.0
62+
*/
63+
@Beta
64+
@Retention(RetentionPolicy.RUNTIME)
65+
@Target({ElementType.METHOD})
66+
@interface Container {
67+
PendingFeatureIf[] value();
68+
}
6169
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package org.spockframework.docs.extension
2+
3+
import org.opentest4j.TestAbortedException
4+
import spock.lang.PendingFeature
5+
import spock.lang.PendingFeatureIf
6+
import spock.lang.Specification
7+
8+
class PendingFeatureIfDocSpec extends Specification {
9+
// tag::example-a[]
10+
@PendingFeatureIf({ os.windows })
11+
def "I'm not yet implemented on windows, but I am on other operating systems"() {
12+
// end::example-a[]
13+
expect:
14+
throw new TestAbortedException()
15+
}
16+
17+
// tag::example-b[]
18+
@PendingFeatureIf({ sys.targetEnvironment == "prod" })
19+
def "This feature isn't deployed out to production yet, and isn't expected to pass"() {
20+
// end::example-b[]
21+
expect:
22+
true
23+
}
24+
25+
// tag::example-c[]
26+
@PendingFeature(exceptions = UnsupportedOperationException)
27+
@PendingFeatureIf(
28+
exceptions = IllegalArgumentException,
29+
value = { os.windows },
30+
reason = 'Does not yet work on Windows')
31+
@PendingFeatureIf(
32+
exceptions = IllegalAccessException,
33+
value = { jvm.java8 },
34+
reason = 'Does not yet work on Java 8')
35+
def "I have various problems in certain situations"() {
36+
// end::example-c[]
37+
expect:
38+
throw new TestAbortedException()
39+
}
40+
}

spock-specs/src/test/groovy/org/spockframework/smoke/extension/PendingFeatureIfExtensionSpec.groovy

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,27 @@ def bar() {
2323
result.testsSucceededCount == 0
2424
}
2525

26+
def "@PendingFeatureIf marks failing feature as skipped if the condition passes and the test fails even if applied twice"() {
27+
when:
28+
def result = runner.runWithImports("""import spock.lang.PendingFeature
29+
import spock.lang.PendingFeatureIf
30+
31+
class Foo extends Specification {
32+
@PendingFeatureIf({true})
33+
@PendingFeatureIf({true})
34+
def bar() {
35+
expect: false
36+
}
37+
}
38+
""")
39+
40+
then:
41+
notThrown(AssertionError)
42+
result.runCount == 1
43+
result.failureCount == 0
44+
result.ignoreCount == 0
45+
}
46+
2647
def "@PendingFeatureIf marks passing feature as failed if the conditional expression returns true"() {
2748
when:
2849
runner.runSpecBody """
@@ -37,6 +58,24 @@ def bar() {
3758
e.message == "Feature is marked with @PendingFeatureIf but passes unexpectedly"
3859
}
3960

61+
def "@PendingFeatureIf marks passing feature as failed if the conditional expression returns true even if applied twice"() {
62+
when:
63+
def result = runner.runWithImports("""import spock.lang.PendingFeature
64+
import spock.lang.PendingFeatureIf
65+
66+
class Foo extends Specification {
67+
@PendingFeatureIf({true})
68+
@PendingFeatureIf({true})
69+
def bar() {
70+
expect: true
71+
}
72+
}
73+
""")
74+
then:
75+
AssertionError e = thrown(AssertionError)
76+
e.message == "Feature is marked with @PendingFeatureIf but passes unexpectedly"
77+
}
78+
4079
def "@PendingFeatureIf marks passing feature as failed if the conditional expression returns true even if @PendingFeature is applied first"() {
4180
when:
4281
runner.runSpecBody """
@@ -182,6 +221,26 @@ def bar() {
182221
result.testsSucceededCount == 1
183222
}
184223

224+
def "@PendingFeatureIf marks failing feature as skipped if the data variable accessing condition passes and the test fails even if applied twice"() {
225+
when:
226+
def result = runner.runSpecBody """
227+
@PendingFeatureIf({ a == 1 })
228+
@PendingFeatureIf({ a == 1 })
229+
def bar() {
230+
expect: a == 2
231+
where: a = 1
232+
}
233+
"""
234+
235+
then:
236+
notThrown(AssertionError)
237+
result.testsStartedCount == 2
238+
result.testsFailedCount == 0
239+
result.testsSkippedCount == 0
240+
result.testsAbortedCount == 1
241+
result.testsSucceededCount == 1
242+
}
243+
185244
def "@PendingFeatureIf marks passing feature as failed if the data variable accessing conditional expression returns true"() {
186245
when:
187246
runner.runSpecBody """
@@ -197,6 +256,22 @@ def bar() {
197256
e.message == "Feature is marked with @PendingFeatureIf but passes unexpectedly"
198257
}
199258

259+
def "@PendingFeatureIf marks passing feature as failed if the data variable accessing conditional expression returns true even if applied twice"() {
260+
when:
261+
runner.runSpecBody """
262+
@PendingFeatureIf({ a == 2 })
263+
@PendingFeatureIf({ a == 2 })
264+
def bar() {
265+
expect: a == 2
266+
where: a = 2
267+
}
268+
"""
269+
270+
then:
271+
AssertionError e = thrown()
272+
e.message == "Feature is marked with @PendingFeatureIf but passes unexpectedly"
273+
}
274+
200275
def "@PendingFeatureIf marks failing feature as failed if the data variable accessing conditional expression returns false"() {
201276
when:
202277
runner.runSpecBody """

0 commit comments

Comments
 (0)