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

[question] using ContainerGebSpec in CI while staying with GebSpec otherwhise #134

Open
JonasPammer opened this issue Feb 9, 2025 · 2 comments

Comments

@JonasPammer
Copy link
Contributor

JonasPammer commented Feb 9, 2025

motivation for switching to ContainerGebSpec: Private GitLab CI with gradle base image

motiviation for not using it unless direly necessary:

  • 20+ minutes compared to 2 minutes run time
GebSpec ContainerGebSpec
Image Image
  • not being able to see whats going on
  • not being able to breakpoint manually and interactively intervene/inspect in browser
  • Weird ElementClickInterceptedException's when clicking something at bottom of page that i had to solve with
    scrollIntoViewAndClick
        /**
         * Fix for
         * org.openqa.selenium.ElementClickInterceptedException: element click intercepted: Element is not clickable at point (90, 920)
         */
        void scrollIntoViewAndClick(final Navigator object) {
            try {
                try {
                    browser.interact {
                        actions.moveToElement(object.singleElement()).build().perform()
                    }
                    object.click()
                } catch (final ElementClickInterceptedException | MoveTargetOutOfBoundsException ex) {
                    System.err.println("moveToElement->click threw a " + ex.message + ". Trying js.scrollIntoView->click")
                    try {
                        browser.js.exec(object.singleElement(), 'arguments[0].scrollIntoView({ behavior: "instant" });')
                        object.click()
                    } catch (final ElementClickInterceptedException | MoveTargetOutOfBoundsException ey) {
                        System.err.println("js.scrollIntoView->click threw a " + ey.message + ". Trying window.maximize->click")
    
                        // possibly?    browser.driver.manage().window().fullscreen()
                        browser.driver.manage().window().maximize()
                        browser.js.exec(object.singleElement(), 'arguments[0].scrollIntoView({ behavior: "instant" });')
                        object.click()
                    }
                }
            } catch (final WebDriverException ea) {
                System.err.println("Nothing worked. Falling back to js.click. " + ea.message)
                System.err.println(ey.message)
                browser.js.exec("arguments[0].click();")
            }
        }
  • Yesterday I came up with this hack. If someone knows of a better way while still utilizing the Integration brought by this Project would be cool:

    task switchToContainerGebSpec {
        doLast {
            if (System.getenv('CI')) {
                print("Not in CI; Skip altering to ContainerGebSpec")
                return
            }
    
            file('src/integration-test/groovy').eachFileRecurse { final file ->
                if (file.name.endsWith('.groovy')) {
                    if (file.text.contains('extends GebSpec')) {
                        // Note: transformation happens during the Gradle build process and modifies the files in Gradle's build/compilation context, not your source files
                        file.text = file.text.replace('extends GebSpec', 'extends com.demo.utils.MyContainerGebSpec')
                    }
                }
            }
        }
    }
    
    tasks.integrationTest {
        dependsOn switchToContainerGebSpec
    }

    Also, in my Utility trait:

        File createTestDataInputSource(final String filename) {
            final File file = loadTestFile(filename) /*own function*/
            if(this instanceof grails.plugin.geb.ContainerGebSpec){
                final String containerPath = "/tmp/${filename}"
                ((grails.plugin.geb.ContainerGebSpec)this).container.copyFileToContainer(Transferable.of(file.bytes), containerPath)
                return new ContainerGebFileInputSource(containerPath)
            } else {
                return file
            }
        }
    @jdaugherty
    Copy link
    Contributor

    We switched to containers for easier maintenance, stability, consistency, & to facilitate parallel testing:

    1. stability - web browsers change quickly and the https://github.com/erdi/webdriver-binaries-gradle-plugin is basically abandoned. See add gradle 8.7 compatibility via org.ysb33r.gradle:grolifant-herd:4.0.0 erdi/webdriver-binaries-gradle-plugin#44 - seleniumManager is being adopted upstream as a replacement, but it's not ready yet.

    2. consistency - containers have the same environment setup every time, so any local configuration that may vary by machine is always the same in the container regardless of where it runs. This includes being able to the pin the browser version since the container determines what browser runs the tests. Want to test code that's 4 years old the same way you tested 4 year ago? You can't really do that with GebSpec because of your local browser version. You can with a container since the image contains the same tools.

    3. easier maintenance - there was a lot of properties/ configuration required to setup the web driver binaries correctly. Also, keeping the version of Geb in sync with the version of selenium proved challenging.

    4. parallel testing - if you wanted to run Gebspec locally, it's going to use your current browser, this means you can't continue to develop while those tests are running. ContainerGebSpec backgrounds this by the nature of it running in a container.

    @matrei
    Copy link
    Contributor

    matrei commented Feb 9, 2025

    20+ minutes compared to 2 minutes run time

    This, might have to do with clicking Geb radio button modules or some other similar action.
    We set a wait duration according to the test-containers examples:

    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30))

    This has proven problematic for Geb and we need to find what the right way to handle this is.

    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

    No branches or pull requests

    3 participants