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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: VNC recording with BrowserWebdriverContainer in Spock-Extension #726

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion modules/spock/build.gradle
Expand Up @@ -10,8 +10,9 @@ dependencies {

testCompile project(':mysql')
testCompile project(':postgresql')
compile project(':selenium')
testCompile 'com.zaxxer:HikariCP:2.6.1'

testRuntime 'org.postgresql:postgresql:42.0.0'
testRuntime 'mysql:mysql-connector-java:6.0.6'
}
}
@@ -1,17 +1,32 @@
package org.testcontainers.spock

import org.spockframework.runtime.AbstractRunListener
import org.spockframework.runtime.extension.AbstractAnnotationDrivenExtension
import org.spockframework.runtime.model.ErrorInfo
import org.spockframework.runtime.model.SpecInfo

class TestcontainersExtension extends AbstractAnnotationDrivenExtension<Testcontainers> {

@Override
void visitSpecAnnotation(Testcontainers annotation, SpecInfo spec) {
def interceptor = new TestcontainersMethodInterceptor(spec)
def listener = new ErrorListener()
def interceptor = new TestcontainersMethodInterceptor(spec, listener)
spec.addSetupSpecInterceptor(interceptor)
spec.addCleanupSpecInterceptor(interceptor)
spec.addSetupInterceptor(interceptor)
spec.addCleanupInterceptor(interceptor)

spec.addListener(listener)

}

class ErrorListener extends AbstractRunListener {
List<ErrorInfo> errors = []

@Override
void error(ErrorInfo error) {
errors.add(error)
}
}

}
@@ -1,18 +1,23 @@
package org.testcontainers.spock

import org.junit.runner.Description
import org.spockframework.runtime.extension.AbstractMethodInterceptor
import org.spockframework.runtime.extension.IMethodInvocation
import org.spockframework.runtime.model.FieldInfo
import org.spockframework.runtime.model.SpecInfo
import org.testcontainers.containers.BrowserWebDriverContainer
import org.testcontainers.containers.DockerComposeContainer
import org.testcontainers.containers.GenericContainer
import org.testcontainers.spock.TestcontainersExtension.ErrorListener

class TestcontainersMethodInterceptor extends AbstractMethodInterceptor {

private final SpecInfo spec
private final ErrorListener errorListener

TestcontainersMethodInterceptor(SpecInfo spec) {
TestcontainersMethodInterceptor(SpecInfo spec, ErrorListener errorListener) {
this.spec = spec
this.errorListener = errorListener
}

@Override
Expand Down Expand Up @@ -50,6 +55,15 @@ class TestcontainersMethodInterceptor extends AbstractMethodInterceptor {

@Override
void interceptCleanupMethod(IMethodInvocation invocation) throws Throwable {
findAllBrowserWebDriverContainers(invocation).each {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about this and it seems that it will result in exporting the video after each failed test..
does it mean we have to restart the container after each test(failed or not)?
or it will just stop the execution?

maybe we want to do this at cleanupSpec time, not sure

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we actually have to add it to both methods but have a conditional findAllBrowserWebDriverContainers() method, so we get the non-shared containers in interceptCleanupMethod and only the @Shared ones in interceptCleanupSpecMethod.

if (errorListener.errors.isEmpty()) {
it.succeeded(Description.createTestDescription(this.class, "foobar"))
} else {
it.failed(errorListener.errors.first().getException(), Description.createTestDescription(this.class, "foobar"))
}

}

def containers = findAllContainers(false)
stopContainers(containers, invocation)

Expand All @@ -65,6 +79,14 @@ class TestcontainersMethodInterceptor extends AbstractMethodInterceptor {
}
}

private List<BrowserWebDriverContainer> findAllBrowserWebDriverContainers(IMethodInvocation invocation) {
spec.allFields.findAll { FieldInfo f ->
BrowserWebDriverContainer.isAssignableFrom(f.type)
}.collect {
readContainerFromField(it, invocation) as BrowserWebDriverContainer
}
}

private List<FieldInfo> findAllComposeContainers(boolean shared) {
spec.allFields.findAll { FieldInfo f ->
DockerComposeContainer.isAssignableFrom(f.type) && f.shared == shared
Expand Down
@@ -0,0 +1,190 @@
package org.testcontainers.spock

import org.intellij.lang.annotations.Language
import spock.lang.Specification
import spock.util.EmbeddedSpecRunner

class BrowserVncRecordingIT extends Specification {

def cleanup() {
new File("dummy.flv").delete()
}

def "retains all recordings"() {
given:

@Language("groovy")
String myTest = """
package org.testcontainers.spock

import org.junit.runner.Description
import org.openqa.selenium.remote.DesiredCapabilities
import org.openqa.selenium.remote.RemoteWebDriver
import org.testcontainers.containers.BrowserWebDriverContainer
import org.testcontainers.containers.RecordingFileFactory
import spock.lang.Specification

import java.util.concurrent.TimeUnit

import static org.testcontainers.containers.BrowserWebDriverContainer.VncRecordingMode.RECORD_ALL

@Testcontainers
class BrowserWebdriverContainerIT extends Specification {

BrowserWebDriverContainer browserContainer = new BrowserWebDriverContainer()
.withDesiredCapabilities(DesiredCapabilities.chrome())
.withRecordingMode(RECORD_ALL, new File("./build/"))
.withRecordingFileFactory(new RecordingFileFactory() {
@Override
File recordingFileForTest(File vncRecordingDirectory, Description description, boolean succeeded) {
return new File("dummy.flv")
}
});

RemoteWebDriver driver

def setup() {
driver = browserContainer.getWebDriver()
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS)
}

def "should record"() {
when:
driver.get("http://en.wikipedia.org/wiki/Randomness")

then:
driver.findElementByPartialLinkText("pattern").isDisplayed()
}

}


"""

when:
EmbeddedSpecRunner runner = new EmbeddedSpecRunner(throwFailure: false)
def result = runner.run(myTest)

then:
new File("dummy.flv").exists()
}

def "records nothing if RECORD_FAILING and not failing"() {
given:

@Language("groovy")
String myTest = """
package org.testcontainers.spock

import org.junit.runner.Description
import org.openqa.selenium.remote.DesiredCapabilities
import org.openqa.selenium.remote.RemoteWebDriver
import org.testcontainers.containers.BrowserWebDriverContainer
import org.testcontainers.containers.RecordingFileFactory
import spock.lang.Specification

import java.util.concurrent.TimeUnit

import static org.testcontainers.containers.BrowserWebDriverContainer.VncRecordingMode.RECORD_FAILING

@Testcontainers
class BrowserWebdriverContainerIT extends Specification {

BrowserWebDriverContainer browserContainer = new BrowserWebDriverContainer()
.withDesiredCapabilities(DesiredCapabilities.chrome())
.withRecordingMode(RECORD_FAILING, new File("./build/"))
.withRecordingFileFactory(new RecordingFileFactory() {
@Override
File recordingFileForTest(File vncRecordingDirectory, Description description, boolean succeeded) {
return new File("dummy.flv")
}
});

RemoteWebDriver driver

def setup() {
driver = browserContainer.getWebDriver()
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS)
}

def "should record"() {
when:
driver.get("http://en.wikipedia.org/wiki/Randomness")

then:
driver.findElementByPartialLinkText("pattern").isDisplayed()
}

}


"""

when:
EmbeddedSpecRunner runner = new EmbeddedSpecRunner(throwFailure: false)
def result = runner.run(myTest)

then:
!new File("dummy.flv").exists()
}

def "records file if RECORD_FAILING and failing"() {
given:

@Language("groovy")
String myTest = """
package org.testcontainers.spock

import org.junit.runner.Description
import org.openqa.selenium.remote.DesiredCapabilities
import org.openqa.selenium.remote.RemoteWebDriver
import org.testcontainers.containers.BrowserWebDriverContainer
import org.testcontainers.containers.RecordingFileFactory
import spock.lang.Specification

import java.util.concurrent.TimeUnit

import static org.testcontainers.containers.BrowserWebDriverContainer.VncRecordingMode.RECORD_FAILING

@Testcontainers
class BrowserWebdriverContainerIT extends Specification {

BrowserWebDriverContainer browserContainer = new BrowserWebDriverContainer()
.withDesiredCapabilities(DesiredCapabilities.chrome())
.withRecordingMode(RECORD_FAILING, new File("./build/"))
.withRecordingFileFactory(new RecordingFileFactory() {
@Override
File recordingFileForTest(File vncRecordingDirectory, Description description, boolean succeeded) {
return new File("dummy.flv")
}
});

RemoteWebDriver driver

def setup() {
driver = browserContainer.getWebDriver()
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS)
}

def "should record"() {
when:
driver.get("http://en.wikipedia.org/wiki/Randomness")

then:
!driver.findElementByPartialLinkText("pattern").isDisplayed()
}

}


"""

when:
EmbeddedSpecRunner runner = new EmbeddedSpecRunner(throwFailure: false)
def result = runner.run(myTest)

then:
new File("dummy.flv").exists()
}

}