Annotation Type Togglz


  • @Retention(RUNTIME)
    @Target({TYPE,METHOD})
    @Inherited
    public @interface Togglz
    Creates a TestFeatureManager for the test.

    Allows the user to control the state of a Feature for a test or specification. It can only be used to manage one feature enum at a time, as the TestFeatureManager doesn't support multiple features.

    Parallel Execution Support

    This extension supports Spock's parallel execution capability. Every specification and test annotated with @Togglz will acquire READ_WRITE lock for the key TogglzExtension.TOGGLZ_FEATURE_RESOURCE.

    Where to apply

    Can be applied on individual tests and on the specification.

    When applied on an individual test it will only affect that test.

    When applied on an specification it will behave as if every test was annotated with the same annotation.

    If both test and specification is annotated, then both will be merged, and the feature annotation will override the specification annotation on conflicts.

    Here are some examples:

    Annotation on Specification Annotation on Test Result
    @Togglz(allEnabled = MyFeature) - allEnabled = MyFeature
    - @Togglz(allDisabled = MyFeature) allDisabled = MyFeature
    @Togglz(allEnabled = MyFeature) @Togglz(allDisabled = MyFeature) allDisabled = MyFeature
    @Togglz(allEnabled = MyFeature) @Togglz(disable = {[MyFeature.One]}) allEnabled = MyFeature, disable = {[MyFeature.One]})
    @Togglz(allEnabled = MyFeature) @Togglz(allDisabled = MyFeature, enable = {[MyFeature.One]}) allDisabled = MyFeature, enable = {[MyFeature.One]})

    Enabling/disabling individual features

    You always have to have either allEnabled or allDisabled defined for a test. You can inherit the value from the specification (see the Where to apply chapter).

    If you have used allDisabled then you can enable individual features using the enable setting. The same applies for allEnabled and disabled.

    Note: enable/disabled expect a closure that returns a list, not a list directly.

    Here are some examples:

     @Togglz(allDisabled = MyFeature)
     class MyTest extends Specification {
         def "test allDisabled"() {
             expect:
             !MyFeature.ONE.active
             !MyFeature.TWO.active
         }
    
         @Togglz(enable = {[MyFeature.One]})
         def "enable feature one"() {
             expect:
             MyFeature.ONE.active
             !MyFeature.TWO.active
         }
    
         @Togglz(enable = {[MyFeature.TWO]})
         def "enable feature one"() {
             expect:
             !MyFeature.ONE.active
             MyFeature.TWO.active
         }
     }
     

    Injecting TestFeatureManager into a test

    You can declare TestFeatureManager as a parameter to any test that is either directly annotated with @Togglz or it's Specification is annotated with it.

    Here are some examples:

     @Togglz(allDisabled = MyFeature)
     class MyTest extends Specification {
    
          def "injection in non data-driven feature"(TestFeatureManager testFeatureManager) {
              expect:
              MyFeatures.values().every { !it.active }
    
              when:
              testFeatureManager.enable(MyFeatures.ONE)
    
              then:
              MyFeatures.ONE.active
          }
    
          def "data-driven disabled"(MyFeatures feature, TestFeatureManager testFeatureManager) {
              expect:
              MyFeatures.values().every { !it.active }
    
              when:
              testFeatureManager.enable(feature)
    
              then:
              feature.active
    
              where:
              feature << MyFeatures.values()
          }
     }
     

    Advanced usage

    As enable/disabled use a closure, you can add logic to control which feature is enabled/disabled. The closure gets PreconditionContext as parameter so you can use it to control which feature is returned.

    Use this feature with care!

    Here is an example:

     @Togglz(allDisabled = MyFeatures,
         enable = { PreconditionContext pc -> pc.os.windows ? [MyFeatures.ONE] : [MyFeatures.TWO] })
     def "all disabled with individual enabled using PreconditionContext"() {
         given:
         def os = OperatingSystem.getCurrent()
    
         expect:
         MyFeatures.ONE.active == os.windows
         MyFeatures.TWO.active == !os.windows
         !MyFeatures.THREE.active
     }
     
    • Optional Element Summary

      Optional Elements 
      Modifier and Type Optional Element Description
      Class<? extends org.togglz.core.Feature> allDisabled
      Feature class that should have every feature disabled.
      Class<? extends org.togglz.core.Feature> allEnabled
      Feature class that should have every feature enabled.
      Class<? extends groovy.lang.Closure<List<? extends org.togglz.core.Feature>>> disable
      The inverse of enable() It cannot be combined with allDisabled(). It is mutually exclusive with enable().
      Class<? extends groovy.lang.Closure<List<? extends org.togglz.core.Feature>>> enable
      Can be used in conjunction with allDisabled() to enable individual features again.
    • Element Detail

      • allEnabled

        Class<? extends org.togglz.core.Feature> allEnabled
        Feature class that should have every feature enabled.

        Example Usage:

        @Togglz(allEnable = MyFeature)

        It is mutually exclusive with allDisabled().

        Default:
        org.togglz.spock.Togglz.None.class
      • allDisabled

        Class<? extends org.togglz.core.Feature> allDisabled
        Feature class that should have every feature disabled.

        It is mutually exclusive with allEnabled().

        Default:
        org.togglz.spock.Togglz.None.class
      • enable

        Class<? extends groovy.lang.Closure<List<? extends org.togglz.core.Feature>>> enable
        Can be used in conjunction with allDisabled() to enable individual features again.

        Define a closure that returns a list of features to enable.

        Example Usage:

        @Togglz(allDisable = MyFeature, enable = {[MyFeature.ONE]})

        Default:
        org.togglz.spock.Togglz.None.class
      • disable

        Class<? extends groovy.lang.Closure<List<? extends org.togglz.core.Feature>>> disable
        The inverse of enable()
        Default:
        org.togglz.spock.Togglz.None.class