I'd like to execute some action when Spock test fails. Specifically, take a screenshot. Is it possible? How to do it?
Create a listener class
class ExampleListener extends AbstractRunListener {
def void error(ErrorInfo error) {
println "Actual on error logic"
}
}
then add it to each specification using implementation of IGlobalExtension
that is executed for each Spec
class GlobalSpecExtension implements IGlobalExtension {
@Override
void visitSpec(SpecInfo specInfo) {
specInfo.addListener(new ExampleListener())
}
}
and finally create file named org.spockframework.runtime.extension.IGlobalExtension
in your META-INF/services directory
(typically it will be under src/test/resources
if you are using Maven) with the full name of your IGlobalExtension
implementation e.g.
com.example.tests.GlobalSpecExtension
The best way to achieve this is to write a (global or annotation-driven) Spock extension that implements and registers an AbstractRunListener
. For an example, see OptimizeRunOrderExtension. For how to register a global extension, see the IGlobalExtension descriptor.
There isn't much documentation on extensions because the APIs are still subject to change. If you want to play it safe (and can live with some restrictions), you can implement a JUnit Rule instead.
One problem that you may encounter in both cases is that they don't provide access to the current spec instance. If you need this, you may have to use both an AbstractRunListener
(to be notified of the failure) and an IMethodInterceptor
(to get hold of the spec instance), both registered by the same extension. (Shouldn't be this hard, but that's what's currently there.)
WebDriverException: Session [...] was terminated due to TIMEOUT
I can intercept and log the error in the listener, but do not have access to driver
or a driver factory the cache of which I can invalidate. Any ideas? –
Beshore I've managed to do it this way:
class ExampleTest extends GebSpec{
static boolean success = false
def setup(){
success = false
}
def cleanup(){
assert success == true, someAction()
}
def someAction(){
}
def "TestCase"(){
expect:
/*What you expect here*/
(success = true) != null
}
}
Before each test case "success" is set to false by the setup() method. At the end of each test case you add the "(success = true) != null" statement. Therefore "success" will only be true if the test case has passed. After each test case the cleanup() method will verify if "success" is true. If it isn't the method someAction() will be called.
I can't upvote or comment on user3074543's answer, but it's simpler than creating an extension. I want easy. So I shortened user*'s a little (I don't mean the 1-line methods). You can make the logic simpler by recording failure instead of success, and reduce typing with a done() helper.
class Test extends spock.lang.Specification {
def fail
def setup(){ fail = true }
def done(){ !(fail = false) }
def cleanup(){ fail && doStuffWhenFail() }
def 'test things'(){
expect:
stuff
done()
}
}
© 2022 - 2024 — McMap. All rights reserved.