Galen Test Suite Syntax

To give more flexibility and maintainability to user Galen came up with another simple format for defining test suites. Test suites are just a set of pages that needs to be checked with the appropriate test specs. But there is something more in there which gives a lot of power in testing.

Basic Format

Same way as in specs language the indentation is done with 1 to 8 spaces. A test starts with a name and then you define the page and page actions

Home page on a small mobile device http://example.com/home 320x600 check homepage.gspec --include "mobile,all" --exclude "nomobile"

In the example above we have defined the simplest test named "Home page on a small mobile device". For this test we also specified that we want to run it against http://example.com/home with browser resized to 320x600. Then we defined the so called Page Action in which it is specified to use homepage.gspec file and also it says which tags to use and which ones to exclude.

This is how the two tests in a same suite would look like:

Home page on a small mobile device http://example.com/home 320x600 check homepage.gspec --include "mobile,all" --exclude "nomobile" Login page on a small mobile device http://example.com/login 320x600 check login.gspec --include "mobile,all" --exclude "nomobile"

You can also filter some sections with --section argument:

Home page on a small mobile device http://example.com/home 320x600 check homepage.gspec --section "Login for * device"

Passing JavaScript variables to spec file

You can pass some data from your tests into your spec file so that they are accessible from JavaScript statements. To do this you need to pass it via --VvariableName variableValue argument. For example:

Home page test http://example.com 1024x768 check homepage.gspec --include desktop --Vusername John

Variables

It is always nice to put commonly used data in variables. e.g. we can put domain name in the variable. This can be done with special instruction: set

@@ set domain example.com Home page on a small mobile device http://${domain}/home 320x600 check homepage.gspec --include "mobile,all" --exclude "nomobile"

You can also define multiple variables within same instruction like this:

@@ set domain example.com mobile_size 320x600 Home page on a small mobile device http://${domain}/home ${mobile_size} check homepage.gspec --include "mobile,all" --exclude "nomobile"

Or you can also use variable reference when defining another variable:

@@ set domain example.com base_url http://${domain}/ Home page on a small mobile device ${base_url} 320x600 check homepage.gspec --include "mobile,all" --exclude "nomobile"

Import Test Suites

If you want to reuse objects and tables from other test suites, you can import them like this:

@@ import base.test # ....

Browser Factory

There few ways you could run Galen. You can run tests in a specific browser (Firefox, Chrome, IE) or you can run tests against Selenium Grid.

Defining a local browser

Homepage in local Firefox browser selenium firefox http://example.com/ 640x480 check homepage.gspec Homepage in local Chrome browser selenium chrome http://example.com/ 640x480 check homepage.gspec Homepage in local Internet Explorer browser selenium ie http://example.com/ 640x480 check homepage.gspec Homepage in PhantomJS browser selenium phantomjs http://example.com/ 640x480 check homepage.gspec

Actually if you skip the browser name before url Galen will pick Firefox by default.

Running in Selenium Grid

If you want to run Galen tests in parallel or if you want to maintain cross-browser testing then it is a good idea to configure a Selenium Grid (follow this tutorial for setting up a Selenium Grid). In your Galen tests you can use it like this

Homepage in Selenium Grid in Chrome selenium grid http://your.selenium.grid.hostname:4444/wd/hub --page http://example.com --size 640x480 --browser Chrome --version "21.0" --platform "XP" check homepage.gspec

The following are the arguments that you can use for selenium grid config:

  • browser - name of a browser which you can set in your Selenium Grid
  • version -version a browser
  • platform -name of operating system
  • page - the url to your test website
  • size - the size of the browser window to which it should be resized
  • dc. - the desired capability prefix. Every argument that starts with dc. will be taken as desired capability for grid node

Actually the browser, version and platform are optional arguments so you can use it like this:

Homepage in Selenium Grid selenium grid http://your.selenium.grid.hostname:4444/wd/hub --page http://example.com --size 640x480 check homepage.gspec

Or it would be even better to put selenium grid in the variable:

@@ Set run_in_grid selenium grid http://your.selenium.grid.hostname:4444/wd/hub Homepage in Selenium Grid ${run_in_grid} --page http://example.com --size 640x480 check homepage.gspec

And here is an example of using desired capabilities

Homepage in Selenium Grid selenium grid http://localhost:4444/wd/hub --dc.browser android --dc.device-orientation landscape

JavaScript Browser Factory

In case you would like to take full control over instantiating the WebDriver you can use the so called jsfactory. It delegates the creation of browser to a user-defined script. This might be very handy in case you need to provide some additional settings in a profile. Lets image you need to open browser with specific language settings. Here is an example of a script mydriver.js that does that:

importClass(org.openqa.selenium.firefox.FirefoxDriver); importClass(org.openqa.selenium.firefox.FirefoxProfile); importClass(com.galenframework.utils.GalenUtils); importClass(com.galenframework.browser.SeleniumBrowser); var pageUrl = args[0]; var size = GalenUtils.readSize(args[1]); var profile = new FirefoxProfile(); profile.setPreference("intl.accept_languages", "no,en-us,en"); var browser = new SeleniumBrowser(new FirefoxDriver(profile)); browser.load(pageUrl); browser.changeWindowSize(size); browser;

And here is an example how to use this script mydriver.js in the test suite:

Home page on a mobile device jsfactory mydriver.js http://samples.galenframework.com/tutorial1/tutorial1.html 400x480 check homepage.gspec --include "mobile"

You should always provide a script for jsfactory. All other arguments will be copied to the args array in the script. As you see from example above the argument http://samples.galenframework.com/tutorial1/tutorial1.html is stored at 0 position in args array and argument 640x480 is at 1 position

IMPORTANT! If you use jsfactory you also have to handle opening of a url and resizing browser window. In this browser factory Galen is not doing anything so you have to manage this by yourself. Just take a look how it is implemented in the example above

In case you don’t want to implement browser window resize and loading of page url you can use page actions open and resize for jsfactory based tests.

Home page test jsfactory firefox.js open http://example.com resize 640x480 check homepage.gspec

Replacing page url in reports

Once the test is done Galen will generate HTML report and in it it will use the browser factory that you defined in your spec. If you would like to change the way it appears there you can use ‘|’ symbol like in the following example

Login page test Login page url /login | http://example.com/login 640x480 check login.gspec

In the end galen will use everything before ‘|’ in HTML report. So only the Login page url /login part will be shown.

Page Actions

Page Actions: Cookies Handling

Sometimes you need to work with functionality that is hidden behind Feature switch (or Feature Toggle). That is now possible with Galen Framework. Lets imagine that for your website you use the cookie MyFeature1=allowed; path=/ to set a feature switch. Now you need to test that functionality behind the feature switch. You could do it like this.

Homepage on mobile device http://example.com/ 400x600 cookie "MyFeature1=allowed; path=/" check homepage.gspec --include "all,mobile"

What will happen is that Galen will generate a javascript for setting a new cookie and will inject it in browser. After that it will refresh the browser window so that you can test your page properly.

Page Actions: JavaScript Injection

Sometimes you need to test things that are not easy accessible. For example user profile page. Normally you need to authorize first. Or another example: there could be a hidden menu that pops up only in case you interact with something on a page. For both problems there two different solutions: javascript injection and selenium interaction

You can inject your own javascript with which you can change your page. For that you need to save a javascript in a separate file e.g. open-popup.js:

$("popup").show();

Then you should trigger this javascript injection from your Galen tests like this:

Popup on Home Page http://example.com/ 640x480 inject open-popup.js check homepage-popup.gspec

Page Actions: Selenium Interaction

Another thing that you might need sometimes – is doing something on website before testing with Galen Specs. Lets say you need to login to get to your profile. Galen allows you to run javascript in which you can take over the browser using WebDriver.

IMPORTANT! Even though this page action also uses javascript please note its not getting injected in your web page. It is actually being executed separately and in it you can operate with your browser: click the elements, type text to text fields and even change the size of a window.

The content of some login flow in file login.js

// These two values are passed from Galen test var userLogin = arg.login; var userPassword = arg.password // Here we type user login and password on our login page driver.findElement(By.cssSelector("#login-form .login")).sendKeys(userLogin); driver.findElement(By.cssSelector("#login-form .password")).sendKeys(userPassword); // Submitting the login page driver.findElement(By.cssSelector("#login-form .submit")).click(); // Waiting till user profile page is shown function pageIsLoaded() { return driver.findElement(By.id("user-profile")) != null; } waitFor(pageIsLoaded); function waitFor(func) { var timeout = 10; while(timeout > 0 && !func()) { timeout = timeout - 1; Thread.sleep(1000); } if (!func()) { throw new Error("Wait timeout"); } }

Once we are finished with the login.js lets call it before we can test user profile page with userprofile.gspec file

User profile page http://example.com/login 640x480 run login.js '{login: "[email protected]", password: "qwerty"}' check userprofile.gspec

Page Actions: Open and Resize

In case you use your own factory for creating a browser and you don’t want to handle url opening in there you can use open page action

Home page test jsfactory firefox.js open http://example.com check homepage.gspec

You can also use resize page action for changing browser window size

Home page test jsfactory firefox.js open http://example.com resize 640x480 check homepage.gspec

Parameterization

Once you start thinking on testing the responsive design for your web application you might need to look into parameterization. For instance you want to run tests against different devices or different browsers. This can be done by writing a data table and marking the test with "parameterized" special instruction

@@ parameterized | deviceName | tags | size | | Mobile | mobile | 320x600 | | Tablet | tablet | 640x480 | | Desktop | desktop | 1024x800 | Home page on ${deviceName} device http://example.com/ ${size} check homepage.gspec --include "${tags}"

As you see we defined a data table where the first row is used as a header with names of parameters. Using the example above Galen will run test 3 times with all listed parameters. In the report you will see the tests runs like this:

  • Home page on Mobile device
  • Home page on Tablet device
  • Home page on Desktop device

But what if we want to parameterize the parameterized? What could that mean? Lets say you would like to run tests in all browsers and with all different sizes. This can also be done in the following way:

@@ parameterized | browser | | firefox | | chrome | | ie | @@ parameterized | deviceName | tags | size | | Mobile | mobile | 320x600 | | Tablet | tablet | 640x480 | | Desktop | desktop | 1024x800 | Home page on ${deviceName} device in ${browser} browser ${browser} http://example.com/ ${size} check homepage.gspec --include "${tags}"

The example above would give us 9 runs for the same test. The resulting report would give these test runs:

  • Home page on Mobile device in firefox browser
  • Home page on Tablet device in firefox browser
  • Home page on Desktop device in firefox browser
  • Home page on Mobile device in chrome browser
  • Home page on Tablet device in chrome browser
  • Home page on Desktop device in chrome browser
  • Home page on Mobile device in ie browser
  • Home page on Tablet device in ie browser
  • Home page on Desktop device in ie browser

Tables

Of course the parameterizations are nice but what if we are using 30 tests and we want to parameterize all of them? In this case we can share the data tables and reuse them in our parameterized tests. Take a look at the example below

@@ table devices | deviceName | tags | size | | Mobile | mobile | 320x600 | | Tablet | tablet | 640x480 | | Desktop | desktop | 1024x800 | @@ parameterized using devices Home page on ${deviceName} device http://example.com/ ${size} check homepage.gspec --include "${tags}" @@ parameterized using devices Login page on ${deviceName} device http://example.com/login ${size} check login.gspec --include "${tags}"

You can also merge tables inside parameterization block like this

@@ table deviceList_A | deviceName | tags | size | | Mobile | mobile | 320x600 | | Tablet | tablet | 640x480 | | Desktop | desktop | 1024x800 | @@ table deviceList_B | deviceName | tags | size | | Mobile 2 | mobile | 360x600 | | Mobile 3 | mobile | 400x600 | | Mobile 4 | mobile | 500x600 | @@ parameterized using deviceList_A, deviceList_B Login page on ${deviceName} device http://example.com/login ${size} check login.gspec --include "${tags}"

Loading Properties

Sometimes you might want to define some specific values in a property file and share its contents across multiple spec files. Here is how you can do it. For example we can create a custom.properties file and put the following content in it:

header.desktop.height= 80 to 90px header.mobile.height= ~ 45px

In the test suite we can load the properties right before the check command:

Home page test on desktop http://example.com 1024x768 properties custom.properties check homepage.gspec --include desktop

Here are the contents of homepage.gspec

@objects header #header = Header = header: @on desktop height ${header.desktop.height} @on mobile height ${header.mobile.height}

Disabling Tests

In case you want to temporarily disable a test just put the disabled special instruction before it.

@@ disabled Home page http://example.com 640x480 check homepage.gspec Login page http://example.com/login 640x480 check homepage.gspec

Test Groups

Since version 1.6 you can tag your tests with groups. That will allow you to group your tests in HTML report and choose which group to run in command line. To mark a specific test as a group just use groups keyword:

@@ groups mobile, homepage, temp Home page test http://example.com 1024x768 check homepage.gspec

Waiting for dynamic content

Sometimes you need to test a page that is generated dynamically and you have to wait until it is properly rendered before checking its layout. Since version 0.10.0 Galen offers a wait action. It can be used in two ways:

  • Strict timeout
  • Condition based timeout

Strict timeout

You can define timeout in milliseconds (ms), seconds (s) or minutes (m)

Home page test http://example.com 640x480 wait 10s check homepage.gspec

Condition based timeout

For this way of waiting you need to provide a locator (css, xpath or id) for an element and a condition for it. There 4 conditions that could be used in wait action:

  • element appears in DOM
  • element is removed from DOM
  • element becomes visible
  • element gets hidden

In case the condition fails Galen will throw an exception and interrupt the test.

Example of waiting for element to appear in DOM:

Home page test http://example.com 640x480 wait 1m until exist "css: div.list a" check homepage.gspec

Example of waiting for element to be removed from DOM:

Home page test http://example.com 640x480 wait 1m until gone "xpath: //div[@class='list']//a" check homepage.gspec

Example of waiting for element to become visible:

Home page test http://example.com 640x480 wait 1m until visible "id: login-box" check homepage.gspec

Example of waiting for element to become hidden:

Home page test http://example.com 640x480 wait 1m until hidden "id: login-box" check homepage.gspec

You can also mix multiple conditions with multiple elements like this:

Home page test http://example.com 640x480 wait 1m until exist "id: login-box" "css: div.list" gone "css: #logout" visible "css: a.signup" check homepage.gspec

Page Dump

Since version 1.3 Galen has a feature of creating a page dump. With a page dump you can store information about all your test objects on the page together with image samples.

Home page test http://example.com 640x480 dump homepage.gspec --name "Home page" --export dumps/homepage --max-width 200 --max-height 200

Mutation Testing

Since version 2.4 galen lets you perform the so called mutation testing of your galen specs. It lets you check whether your galen specs are good enough by running “mutations” for each object and checking if it was catched by the spec. It works like the check command and uses same arguments. All you need is a working galen spec (it should always pass, otherwise mutation test will not succeed). In the galen test suite you can invoke with the following command:

Home page test http://example.com 640x480 mutate homepage.gspec --offset 5

Where the --offset 5 is an offset for each individual mutation.

Comments

We have moved all the discussions to Google Groups. From this moment, if you have problems with your test code or some issues with installation, please ask your questions in https://groups.google.com/forum/#!forum/galen-framework.