Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow access to the currently executing block object #538

Closed
ddimtirov opened this issue Oct 28, 2015 · 12 comments · Fixed by #1575
Closed

Allow access to the currently executing block object #538

ddimtirov opened this issue Oct 28, 2015 · 12 comments · Fixed by #1575

Comments

@ddimtirov
Copy link

In order to improve the error reporting of our testing utils, we would like to have a ISpecificationContext#getCurrentBlock() method.

If the code is before any block, it should return a block of type SETUP and no text.

Ideally, the text of blocks returned by this method would have resolved #references, similar to the spec titles.

@dpost
Copy link

dpost commented May 5, 2016

@ddimtirov have you found any way to get the current block? I can access the list of blocks but I haven't found a way to determine which block is currently being executed

@kriegaex
Copy link
Contributor

kriegaex commented Feb 10, 2017

@pniederw, are there any options we have overlooked? It would be really helpful to have a block-level interception point for Spock extensions so as to enable power users or toolsmiths to help themselves. See also #645 and StackOverflow questions like this one.

I mean, this is easy to achieve, but it only works before/after feature execution:

package de.scrum_master.app

import org.spockframework.runtime.AbstractRunListener
import org.spockframework.runtime.extension.AbstractGlobalExtension
import org.spockframework.runtime.model.FeatureInfo
import org.spockframework.runtime.model.SpecInfo

class LabelPrintExtension extends AbstractGlobalExtension {
  @Override
  void visitSpec(SpecInfo spec) {
    spec.addListener(new LabelPrintListener())
  }

  static class LabelPrintListener extends AbstractRunListener {
    @Override
    void beforeFeature(FeatureInfo feature) {
      feature.blocks.each {
        println "$it.kind: ${it.texts[0]}"
      }
    }
  }
}

META-INF/services/org.spockframework.runtime.extension.IGlobalExtension:

de.scrum_master.app.LabelPrintExtension

Update: There also seems to be a related (maybe half-baked, I have not tried) PR #111. But that one may just be an improvement concerning report generation, I have not actually inspected the code and would have a hard time fully understanding it.

@kriegaex
Copy link
Contributor

kriegaex commented Mar 12, 2017

FYI, if you need a workaround until PR #111 is available as a feature, see my StackOverflow answer which I am quoting here. By using src/test/resources/SpockConfig.groovy and declaring a printing method named _ therein as a mixin to Specification we can achieve that the method is also available in subclasses such as GebSpec, GebReportingSpec or your own (base) classes derived from either of them.

import spock.lang.Specification

class LabelPrinter {
  def _(def message) {
    println message
    true
  }
}

Specification.mixin LabelPrinter

Now if we have a spec like this (please note the unobtrusive underscores, e.g. given:_ "blah"):

package de.scrum_master.testing

import spock.lang.Specification

class MySpockTest extends Specification {
  def "interaction"() {
    given:_ "My given comment"
    def foo = 11
    def bar = foo + 4
    println "blah"

    expect:_ "My expect comment"
    interaction {
      foo = 2
      bar = 5
      true
    }
    println "foo"
    foo * bar == 10
    foo + bar == 7

    and:_ "My and comment"
    true
  }
}

We get a console log like this:

My given comment
blah
My expect comment
foo
My and comment

@leonard84
Copy link
Member

Let me just says that we plan to enhance reporting in post 1.1 so this feature won't be added in 1.1.
One part is iteration-reporting #705 and the release of spock-reporting and spock-gradle plugin, another would be a block-listener support.

@kriegaex
Copy link
Contributor

Me personally, I am not so much interested in reporting because I do not use it. Block listeners is what I am waiting for because I rather look into build logs, not into build reports.

My little workaround has the advantage to also work for and: labels which would probably require some changes (such as not removing and: from the AST as mere syntactic sugar) in Spock. It can also utilise variable/expression expansion inside "labels" (in reality GroovyString method parameters) in simple or unrolled specs, e.g. then:_ "hello $my_var".

BTW, it cannot be used with where:, but the same probably also applies to a future block listener because of the special semantics of where:.

@leonard84
Copy link
Member

Yes where blocks are special and won't be part of the block listeners. There is also the hidden mechanic, that interactions from the then blocks, are configured just before the preceding when block and I'm not so sure if and how we would address this with the block listeners.

@ngyukman
Copy link

ngyukman commented May 9, 2018

Is there any chance to have this move forward?
It will be very useful in reporting to know which is the failing step

@adrian-baker
Copy link

adrian-baker commented Jun 25, 2018

I've just been experimenting moving our integration tests from Cucumber over to Spock, which we run from a standalone distribution built using gradle application plugin. Unfortunately it looks like a bit of a non starter if Spock can't print tests as they're run.

@kriegaex
Copy link
Contributor

kriegaex commented Jun 25, 2018

@adrian-baker, is "non-starter" not a bit exaggerated? I would not want to be without Spock + Geb for any other set of tools. I also like to see this little shortcoming improved, abut this is very far from a non-starter. But of course you are free to opt out and just not use Spock.

Meanwhile you can use my workaround from above - quite easy and effective. And once this ticket is implemented, it shall be very easy to globally search and replace all the _ prefixes in your codebase later.

@kriegaex
Copy link
Contributor

Like several times before, I have just answered another StackOverflow question concerning block listener support. Spock 2.0-M2 is already out and if there has not been a feature freeze yet, I would be very pleased if this would make it into the next milestone and then into the stable release.

@thokari
Copy link

thokari commented May 29, 2020

@kriegaex You are spot on!

@thokari
Copy link

thokari commented May 29, 2020

I am trying to make this workaround work right now.

The use case:

  • We want to have logs from the tests, that are similar to the generated spock-reports.

  • We are using Zalenium to run our tests against, which records videos, and allows to set cookies with messages, which will pop up during those recordings. These pop ups should be synchronised with the aforementioned logs.

Unfortunately, this workaround is breaking the spock-reports, as the property featureInfo.blocks.texts will be an empty array, if the text is not of type String.

I also noticed, that the _ method is actually (potentially) clashing with / shadowing public static final Object _ = Wildcard.INSTANCE; in Specification, so I used __ but this did not make any difference.

leonard84 added a commit that referenced this issue Dec 27, 2024
This feature allows extension authors to register an `IBlockListener` for
a feature to observe the execution of a feature in more detail.
This surfaces some of Spock's idiosyncrasies, for example interaction
assertions are actually setup right before entering the preceding
`when`-block as well as being evaluated on leaving the `when`-block
before actually entering the `then`-block.

The only valid block description is a constant `String`, although some
users mistakenly try to use a dynamic `GString`. Using anything other
than a `String`, will be treated as a separate statement and thus ignored.

Expose `IErrorContext` in `ErrorInfo` to provide more information in
`IRunListener.error(ErrorInfo)` about where the error happened.

fixes #538
fixes #111
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants