Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Geb login spec by example

I am trying to get familiar with Geb. I’m trying to run it from inside Grails, but that shouldn’t matter at all since my question here is specific to Geb.

I have the following test directory structure:

myapp/
    <lots of stuff here>
    test/
        functional/
            GebConfig.groovy
            LogInLogOutSpec.groovy
            pages/
                LogInPage.groovy
                DashboardPage.groovy

Where LoginPage.groovy is (obviously) the login page, and where DashboardPage is where you should be redirected to after logging in successfully. In reality I have security filters in place that will check to see if the URL you are trying to access requires authentication. If so, they redirect you to the login page, and after successful login, redirect you again to the URL you were trying to access.

For good measure, here’s the HTML that comprises my login page (again, this is Grails, so a GSP file is dynamically converted into HTML at runtime):

<!DOCTYPE html>
<html>
    <head>
        <title>Login</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    </head>
    <body>  
        <form action=“/myapp/auth/signIn" method="post">
            <input type="hidden" name="targetUri" value="/dashboard" />
            <table>
                <tbody>
                    <tr>
                        <td>Username:</td>
                        <td><input type="text" name="username" value="" /></td>
                    </tr>
                    <tr>
                        <td>Password:</td>
                        <td><input type="password" name="password" value="" /></td>
                    </tr>
                    <tr>
                        <td />
                            <td><input type="submit" value="Sign in" /></td>
                    </tr>
                </tbody>
            </table>
        </form>
    </body>
</html>

So I need a Geb test that:

  1. Attempts to go to the Dashboard Page (unauthorized)
  2. Verifies we have instead been redirected to the Login Page
  3. Logs in with good credentials
  4. Verifies we are not at the Dashboard Page

Furthermore:

  • I’d like to choose between: (a) either browser-based (Firefox or Chrome) or (b) a headless browser (which I believe is the HtmlUnitDriver, but correct me if I’m wrong)
  • I’d like the login credentials used by Geb to be injectable from either the GebConfig file or some external parameter (perhaps as env vars or runtime args supplied to the Grails command line). Essentially I don’t want to store username/password in test code.

My best attempt so far:

GebConfig.groovy:

driver = {
    // Again, or Firefox
    ChromeProfile profile = new ChromeProfile()
    Driver driverInstance = new ChromeDriver(profile)
    driverInstace.manage().window().maximize()

    driverInstance
}

baseNavigatorWaiting = true
atCheckWaiting = true

// Need to inject from some external process somehow, but make these
// available to test specs somehow.
username = System.env("USERNAME")
password = System.env("PASSWORD")

LogInLogOutSpec.groovy:

import geb.spock.GerbReportingSpec
import spock.lang.*
import pages.*

@Stepwise
class LogInLogOutSpec extends GebReportingSpec {
    String username
    String password

    /*
     * Attempt to go to user dashboard, and confirm you are instead
     * redirected to the login page. Login with good credentials,
     * and verify you are now logged in and at the dashboard.
     */
    def "successful login redirects to dashboard page"() {
        when:
        to DashboardPage

        then:
        "Login".equals($(".page-header").text())

        when:
        $("#login-form input[name=username]").value(username)
        $("#login-form input[name=password]").value(password)

        then:
        "Dashboard".equals($(".page-header").text())
    }
}

I think I'm close, but this is obviously wrong. Any ideas where I’m going awry? Thanks!

like image 368
smeeb Avatar asked Oct 09 '15 17:10

smeeb


1 Answers

You should modularize your test code. You should use

  • modules for UI widgets which can occur on different pages
  • pages (1, 2) to model a certain HTML page
  • specs for the actual test logic

In your code example you have a dashboard page, but no login page object. You should also think about a login modul if all your pages have the possibility to login or at least provide the possibility to detect the login state. See this SO answer for a modul definition. What is missing here is a function to determine the login state.For another implementation look at the AuthModule and the login test spec of the Geb examples.

To the login credentials: I think you did a good job having the credentials in the environment. This works fine on a developer machine and also on the build server.

For testing with different browsers: geb-example-gradle is a gradle sample project with a GebConfig and a build.gradle. This allows you to switch browser as argument to gradle:

./gradlew chromeTest
./gradlew firefoxTest
./gradlew phantomJsTest

This also answers your last question: a good headless browser I like to use is phantomJs.

like image 77
ChrLipp Avatar answered Oct 24 '22 04:10

ChrLipp