--
You received this message because you are subscribed to the Google Groups "Geb User Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to geb-user+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/geb-user/bc7bbb02-6f6c-46f0-bd0f-45985f9eae15n%40googlegroups.com.
Okay, here is a slightly improved version of what Marcin suggested. It only attaches run listener + method interceptor to Spock specs which are actual Geb specs, reducing runtime overhead. It also contains a sample method for taking a screenshot, just to be able to run my sample test.
package de.scrum_master.testing.extension
import geb.spock.GebSpec
import org.openqa.selenium.OutputType
import org.openqa.selenium.TakesScreenshot
import org.openqa.selenium.WebDriver
import org.spockframework.runtime.AbstractRunListener
import org.spockframework.runtime.extension.AbstractGlobalExtension
import org.spockframework.runtime.extension.IMethodInterceptor
import org.spockframework.runtime.extension.IMethodInvocation
import org.spockframework.runtime.model.ErrorInfo
import org.spockframework.runtime.model.SpecInfo
import java.nio.file.Files
/**
* See https://groups.google.com/g/geb-user/c/vrNZFaRyDQQ
*/
class TestFailureScreenshotExtension extends AbstractGlobalExtension {
@Override
void visitSpec(SpecInfo spec) {
if (GebSpec.isAssignableFrom(spec.reflection)) {
def reporter = new ScreenshotOnErrorReporter()
spec.addListener(reporter)
spec.allFeatures*.addIterationInterceptor(reporter)
}
}
static class ScreenshotOnErrorReporter extends AbstractRunListener implements IMethodInterceptor {
GebSpec gebSpec
@Override
void intercept(IMethodInvocation invocation) throws Throwable {
gebSpec = invocation.instance
try {
invocation.proceed()
} finally {
gebSpec = null
}
}
@Override
void error(ErrorInfo error) {
def driver = gebSpec.driver
driver.manage().window().maximize()
takeScreenshot(driver)
}
void takeScreenshot(WebDriver driver) {
// Not all WebDrivers can take screenshots, e.g. HtmlUnitDriver
if (!(driver instanceof TakesScreenshot)) {
println "Driver $driver is incapable of taking screenshots"
return
}
def screenshotTempFile = (driver as TakesScreenshot).getScreenshotAs(OutputType.FILE)
def targetDir = new File(gebSpec.browser.reportGroupDir, gebSpec.class.name.replaceAll("[.]", "/"))
// TODO: generate nicer name for screenshot file, this is just an example
def screenshotFile = new File(targetDir, System.nanoTime() + ".png")
targetDir.mkdirs()
Files.copy(screenshotTempFile.toPath(), screenshotFile.toPath())
println "Screenshot saved as $screenshotFile"
}
}
}
package de.scrum_master.testing.extension
import geb.spock.GebSpec
import spock.lang.Ignore
import spock.lang.Unroll
//@Ignore("test fails on purpose; activate if you want to see screenshots taken via global extension")
class TestFailureGebReportingTest extends GebSpec {
static url = this.getResource("/simple-form-page.html").toString()
def "failing normal feature"() {
given:
go url
expect:
0 == 1
}
def "passing normal feature"() {
given:
go url
expect:
0 == 0
}
def "parametrised feature"() {
given:
go url
expect:
a == b
where:
a << [2, 4, 6]
b << [3, 5, 6]
}
@Unroll
def "unrolled feature with #a/#b"() {
given:
go url
expect:
a == b
where:
a << [6, 8, 0]
b << [7, 9, 0]
}
}
For normal Spock specs there would be no extra log output. For Geb specs you would see something like:
Screenshot saved as target\geb-reports\de\scrum_master\testing\extension\TestFailureGebReportingTest\70413528792100.png
When running Geb specs using a driver not implementing TakesScreenshot (e.g. HtmlUnitDriver), you would rather see:
Driver org.openqa.selenium.htmlunit.HtmlUnitDriver@4893b344 is incapable of taking screenshots
--
Alexander Kriegisch
https://scrum-master.de
Alexander Kriegisch schrieb am 05.01.2021 09:28 (GMT +07:00):
> I forgot to mention: A SpecInfo is just meta information, the best you
> can get from there is the spec class in order wo rewrite the 'if' as
>
> if (GebSpec.isAssignableFrom(iteration.feature.spec.reflection))
>
> But then you are at a dead end if you need the actual specification
> instance because you cannot get it, so there is no way to access its
> fields or methods like 'getDriver()' from there either. This is why
> Marcin's approach to use an IMethodInterceptor is exactly right. From
> the 'IMethodInvocation invocation' parameter you can easily get the
> instance, while from an 'IterationInfo iteration' you cannot. So you
> see, my quick & dirty hack without running the code is fundamentally
> wrong on several levels.
>
>
To view this discussion on the web visit https://groups.google.com/d/msgid/geb-user/20210105051006.3FB8133804E6%40dd39516.kasserver.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/geb-user/8ddd334b-8cdc-4e6c-8992-8f62785b10cdn%40googlegroups.com.
Just a remark because Marcin already answered the actual question: We are talking Spock now, this question is no longer connected to Geb. I do not mind, but I am not so sure about other readers here.
To view this discussion on the web visit https://groups.google.com/d/msgid/geb-user/CA%2B52dQT2bbaFw%3D2L-U3fOcVg45KzNwxm92tvy90-WcYdk4%2Bzig%40mail.gmail.com.