-
Notifications
You must be signed in to change notification settings - Fork 80
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
Run JS API unit tests and integration tests in the Gradle build #4988
Changes from all commits
b048f9c
c05823a
30d1df4
47a68cd
ea53236
e8ddd50
5f8cb54
a855985
06a17a5
354fd48
d8ad542
9df4859
d9da1ca
6e6326d
92e6f3a
37639a0
03939d9
0d15ac3
49b9b95
0d02ff3
dd54ea8
e16cbb7
4af1341
43a102f
2bab42b
d61c783
a11687d
e03f3e7
ab0bb30
4413dcf
a0c4f0d
713007d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
plugins { | ||
id 'io.deephaven.project.register' | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
io.deephaven.project.ProjectType=DOCKER_REGISTRY | ||
deephaven.registry.imageName=selenium/standalone-firefox:4.16.1-20231219 | ||
deephaven.registry.imageId=selenium/standalone-firefox@sha256:a405fe92b3ce5d7eb31a07e1f99be3d628fdc0e5bdc81febd8dc11786edef024 |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,22 @@ | ||
import com.bmuschko.gradle.docker.tasks.container.DockerCreateContainer | ||
import com.bmuschko.gradle.docker.tasks.container.DockerRemoveContainer | ||
import com.bmuschko.gradle.docker.tasks.container.DockerStartContainer | ||
import io.deephaven.tools.docker.WaitForHealthyContainer | ||
|
||
plugins { | ||
id 'io.deephaven.project.register' | ||
id 'io.deephaven.deephaven-in-docker' | ||
} | ||
|
||
evaluationDependsOn(Docker.registryProject('selenium')) | ||
|
||
apply from: "$rootDir/gradle/web-client.gradle" | ||
|
||
configurations { | ||
js | ||
dts | ||
typescriptDoclet | ||
testImplementation.extendsFrom junit | ||
} | ||
|
||
dependencies { | ||
|
@@ -20,6 +29,8 @@ dependencies { | |
implementation 'com.vertispan.nio:gwt-nio:1.0-alpha-1' | ||
|
||
js project(path: ':proto:raw-js-openapi', configuration: 'js') | ||
|
||
testImplementation 'org.seleniumhq.selenium:selenium-remote-driver:4.16.1' | ||
} | ||
Classpaths.inheritElemental(project, 'elemental2-core', 'implementation') | ||
Classpaths.inheritElemental(project, 'elemental2-promise', 'implementation') | ||
|
@@ -57,6 +68,101 @@ artifacts { | |
} | ||
} | ||
|
||
project.tasks.getByName('quick').dependsOn project.tasks.withType(de.esoco.gwt.gradle.task.GwtCompileTask) | ||
def gwtUnitTest = tasks.register('gwtUnitTest', Test) { t -> | ||
t.systemProperties = [ | ||
'gwt.args': ['-runStyle HtmlUnit', | ||
'-ea', | ||
'-style PRETTY', | ||
"-war ${layout.buildDirectory.dir('unitTest-war').get().asFile.absolutePath}" | ||
].join(' '), | ||
'gwt.persistentunitcachedir': layout.buildDirectory.dir('unitTest-unitCache').get().asFile.absolutePath, | ||
] | ||
t.include '**/ClientUnitTestSuite.class' | ||
t.useJUnit() | ||
t.scanForTestClasses = false | ||
} | ||
|
||
// start a grpc-api server | ||
String randomSuffix = UUID.randomUUID().toString(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are we doing this? Is this safe to do? Seems like this would mess up gradle caching? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would yes, but we are doing this all over for naming docker containers, so that you don't accidentally collide in parallel runs, or separate checkouts, etc. Since this is just for tests, we're not concerned with "oh these tests passed last time, so I'm not even going to run them this time" for integration tests. |
||
deephavenDocker { | ||
envVars.set([ | ||
'START_OPTS':'-Xmx512m -DAuthHandlers=io.deephaven.auth.AnonymousAuthenticationHandler' | ||
]) | ||
containerName.set "dh-server-for-js-${randomSuffix}" | ||
networkName.set "js-test-network-${randomSuffix}" | ||
} | ||
|
||
def seleniumContainerId = "selenium-${randomSuffix}" | ||
def seleniumPort | ||
if (!hasProperty('selenium.port')) { | ||
seleniumPort = '4444' | ||
} else { | ||
seleniumPort = project.getProperty('selenium.port') | ||
} | ||
|
||
def createSelenium = tasks.register('createSelenium', DockerCreateContainer) { t -> | ||
t.dependsOn(Docker.registryTask(project, 'selenium'), deephavenDocker.startTask) | ||
t.targetImageId('deephaven/selenium:local-build') | ||
t.containerName.set(seleniumContainerId) | ||
// Advised by the selenium documentation | ||
t.hostConfig.shmSize.set(2L * 1024 * 1024 * 1024) | ||
|
||
apply from: "$rootDir/gradle/web-gwt-test.gradle" | ||
// Add our own healthcheck to confirm the container starts fully | ||
t.healthCheck.cmd.set(['curl http://localhost:4444/wd/hub/status || exit 1']) | ||
|
||
// This provides a hostname that can be referenced from inside the docker container to access the host | ||
// OS, and connect to the test server. | ||
t.hostConfig.extraHosts.add('host.docker.internal:host-gateway') | ||
t.hostConfig.portBindings.set(["$seleniumPort:4444"]) | ||
t.hostConfig.network.set(deephavenDocker.networkName.get()) | ||
} | ||
def startSelenium = tasks.register('startSelenium', DockerStartContainer) {t -> | ||
t.dependsOn(createSelenium) | ||
t.containerId.set(seleniumContainerId) | ||
} | ||
def seleniumHealthy = project.tasks.register('seleniumHealthy', WaitForHealthyContainer) { task -> | ||
task.dependsOn startSelenium | ||
|
||
task.awaitStatusTimeout.set 120 | ||
task.checkInterval.set 100 | ||
Comment on lines
+126
to
+127
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Side note - really confusing that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed... can go back and rewrite those, but I vote not today. This is code taken from the upstream docker-gradle plugin, and we didn't customize it further. |
||
|
||
task.containerId.set(seleniumContainerId) | ||
} | ||
def stopSelenium = project.tasks.register('stopSelenium', DockerRemoveContainer) { task -> | ||
task.dependsOn startSelenium | ||
task.targetContainerId seleniumContainerId | ||
task.force.set true | ||
task.removeVolumes.set true | ||
} | ||
|
||
def gwtIntegrationTest = tasks.register('gwtIntegrationTest', Test) { t -> | ||
t.dependsOn(deephavenDocker.portTask, seleniumHealthy) | ||
t.finalizedBy(deephavenDocker.endTask, stopSelenium) | ||
doFirst { | ||
def webdriverUrl = "http://localhost:${seleniumPort}/" | ||
t.systemProperty('gwt.args', ["-runStyle io.deephaven.web.junit.RunStyleRemoteWebDriver:${webdriverUrl}?firefox", | ||
'-ea', | ||
'-style PRETTY', | ||
"-setProperty dh.server=http://${deephavenDocker.containerName.get()}:10000", | ||
"-war ${layout.buildDirectory.dir('integrationTest-war').get().asFile.absolutePath}" | ||
].join(' ')) | ||
t.classpath += tasks.getByName('gwtCompile').src | ||
} | ||
t.finalizedBy(deephavenDocker.endTask) | ||
t.systemProperties = [ | ||
'gwt.persistentunitcachedir':layout.buildDirectory.dir('integrationTest-unitCache').get().asFile.absolutePath, | ||
'webdriver.test.host':'host.docker.internal', | ||
] | ||
t.include '**/ClientIntegrationTestSuite.class' | ||
t.useJUnit() | ||
t.scanForTestClasses = false | ||
} | ||
|
||
tasks.named('check').configure { | ||
dependsOn(gwtUnitTest, gwtIntegrationTest) | ||
} | ||
|
||
test { | ||
// Configure jvm-only tests to not run any GWT-only tests | ||
exclude '**/*TestGwt.class', '**/*TestSuite.class' | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package io.deephaven.web; | ||
|
||
import com.google.gwt.junit.tools.GWTTestSuite; | ||
import io.deephaven.web.client.api.NullValueTestGwt; | ||
import io.deephaven.web.client.api.subscription.ConcurrentTableTestGwt; | ||
import io.deephaven.web.client.api.TableManipulationTestGwt; | ||
import io.deephaven.web.client.api.subscription.ViewportTestGwt; | ||
import junit.framework.Test; | ||
import junit.framework.TestSuite; | ||
|
||
public class ClientIntegrationTestSuite extends GWTTestSuite { | ||
public static Test suite() { | ||
TestSuite suite = new TestSuite("Deephaven JS API Integration Test Suite"); | ||
|
||
// This test doesn't actually talk to the server, but it requires the dh-internal library be available. | ||
// Disabled for now, we don't have good toString on the FilterCondition/FilterValue types. | ||
// suite.addTestSuite(FilterConditionTestGwt.class); | ||
|
||
// Actual integration tests | ||
suite.addTestSuite(ViewportTestGwt.class); | ||
suite.addTestSuite(TableManipulationTestGwt.class); | ||
suite.addTestSuite(ConcurrentTableTestGwt.class); | ||
suite.addTestSuite(NullValueTestGwt.class); | ||
|
||
// Unfinished: | ||
// suite.addTestSuite(TotalsTableTestGwt.class); | ||
|
||
return suite; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<module> | ||
<inherits name="io.deephaven.web.DeephavenApi" /> | ||
|
||
<!-- restore the default linker that the test tooling expects --> | ||
<add-linker name="xsiframe" /> | ||
|
||
<!-- define url to load dh-internal from, grpc server to connect to --> | ||
<define-configuration-property name="dh.server" is-multi-valued="false"/> | ||
</module> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<module> | ||
<inherits name="io.deephaven.web.DeephavenApi" /> | ||
|
||
<!-- restore the default linker that the test tooling expects --> | ||
<add-linker name="xsiframe" /> | ||
|
||
|
||
<!-- define url to load dh-internal from, grpc server to connect to --> | ||
<define-configuration-property name="dh.server" is-multi-valued="false"/> | ||
<!-- set a value so that the app can compile at all --> | ||
<set-configuration-property name="dh.server" value="notset" /> | ||
</module> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of the other imageName are more open-ended so that the imageId can be bumped w/
bumpImage
task. Is there a reason this tag was chosen?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Selenium client has historically been firmly tied to a single release of the browser+driver version, so it rarely will work to update this to "latest" without finding out what version that happens to be, and then update the test dependencies to match that specific version. This way, the version number is clear in both places.