Tutorial - Writing integration tests for Confluence using PageObjects
Plugin Source
We encourage you to work through this tutorial. If you want to skip ahead or check your work when you are done, you can find the plugin source code on Bitbucket. Bitbucket serves a public Git repository containing the tutorial's code. To clone the repository, issue the following command:
$ git clone git@bitbucket.org:seuqra/confluence-pageobjects-integration-tests-tutorial.git
Alternatively, you can download the source using the Downloads page here: https://bitbucket.org/seuqra/confluence-pageobjects-integration-tests-tutorial
Step 1. Creating the plugin project
Use the atlas-create-
confluence
-plugin
command to create your plugin.
When you create the plugin using the above SDK, you will be prompted for some information to identify your plugin. Enter the following information:
groupId: :
com.seuqra.confluence.tutorial
artifactId: :
confluence-pageobjects-integration-tests-tutorial
- version:
1.0-SNAPSHOT
package:
com.seuqra.confluence.tutorial
Step 2. Adding PageObjects dependencies to the POM
<dependency> <groupId>com.atlassian.confluence</groupId> <artifactId>confluence-webdriver-pageobjects</artifactId> <version>${confluence-webdriver-pageobjects.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>${guava.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId> <version>${hamcrest.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-library</artifactId> <version>${hamcrest.version}</version> <scope>test</scope> </dependency>
And set following versions:
<hamcrest.version>1.3</hamcrest.version> <guava.version>13.0.1</guava.version> <confluence-webdriver-pageobjects.version>2.0.10</confluence-webdriver-pageobjects.version>
Step 3. Writing a PageObject for the Confluence Welcome Page
package it.com.seuqra.confluence.tutorial; import com.atlassian.confluence.webdriver.pageobjects.page.ConfluenceAbstractPage; import com.atlassian.pageobjects.elements.ElementBy; import com.atlassian.pageobjects.elements.PageElement; import com.atlassian.pageobjects.elements.query.TimedQuery; public class WelcomeToConfluencePage extends ConfluenceAbstractPage { private static final String PREFIX = "/display/ds/"; private static final String PAGE = "Welcome+to+Confluence"; @ElementBy(id = "WelcometoConfluence-WithConfluenceitiseasytocreate,editandsharecontentwithyourteam.Chooseatopicbelowtostartlearninghow.") protected PageElement welcomeTitle; @Override public String getUrl() { return PREFIX+PAGE; } public TimedQuery<String> getWelcomeTitle() { return welcomeTitle.timed().getText(); } }
PageElement
is a DOM element that you want to interact with (modify, click, read or write to)- The
@ElementBy
annotation defines how to search for the element; you can search by things like id, cssSelector, name, and tag - The
getUrl
method defined inConfluenceAbstractPage
indicates where to go to open the expected page - To avoid race conditions, your Page Object should always return a
TimedQuery
orTimedCondition
.
You can type or click on elements. You can also get their attributes, search for page elements inside of page elements, and so on. What's great is that Page Objects are run in the real browser so you really imitate the user and their experience.
Step 4. Using PageObjects in your tests
package it.com.seuqra.confluence.tutorial; import static com.atlassian.pageobjects.elements.query.Poller.*; import static org.hamcrest.Matchers.*; import org.hamcrest.Matcher; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import com.atlassian.confluence.webdriver.pageobjects.ConfluenceTestedProduct; import com.atlassian.confluence.webdriver.pageobjects.page.ConfluenceAbstractPage; import com.atlassian.confluence.webdriver.pageobjects.page.ConfluenceLoginPage; import com.atlassian.pageobjects.Page; import com.atlassian.pageobjects.TestedProductFactory; public class TestWelcomeToConfluencePage { private static ConfluenceTestedProduct confluenceTestedProduct = TestedProductFactory.create(ConfluenceTestedProduct.class); @BeforeClass public static void login() { // WORKAROUND: Method ConfluenceAbstractPage.doWait() raises always an exception because the condition "return typeof window.ajsScriptsFinishedLoading != 'undefined'" is never true // If setupComplete variable is false, this condition is never checked :) ConfluenceAbstractPage.setSetupComplete(false); ConfluenceLoginPage confluenceLoginPage = confluenceTestedProduct.gotoLoginPage(); confluenceLoginPage.login("admin", "admin", true); } @AfterClass public static void logout() { confluenceTestedProduct.logOut(); } @Test public void testWelcomePageTitle() { Page page = confluenceTestedProduct.getPageBinder().navigateToAndBind(WelcomeToConfluencePage.class); WelcomeToConfluencePage welcomeToConfluencePage = (WelcomeToConfluencePage) page; waitUntil(welcomeToConfluencePage.getWelcomeTitle(), (Matcher<String>) containsString("With Confluence it is easy to create, edit and share content with your team.")); } }
- The
pageBinder
object is responsible for binding the Page Object to the DOM. - Use
Poller.waitUntil
to check the assertion. This will poll the Page Object until the assumption is met or the timeout has passed. This is great if you have elements that are dynamically created, or you use AJAX to retrieve data. It will make sure that there are no race conditions in your code. - Use
org.hamcrest.Matchers.*
andorg.hamcrest.CoreMatchers.*
predefined matchers as parameter ofwaitUntil
method.
Step 5. Running your tests
- Go to a command line.
- Make sure you are in at the top level
PLUGIN_HOME
directory for you plugin. Enter the
atlas-integration-test
command:
$ atlas-integration-tests
Notice in command's output, the system runs the unit tests, starts the host application, and then runs your integration tests. The command output should succeed with test output similar to the following:
------------------------------------------------------- T E S T S ------------------------------------------------------- Running it.com.seuqra.confluence.tutorial.TestWelcomeToConfluencePage Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 51.976 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
Step 6. Adjusting PageObjects timeouts
By default, Pageobjects for Confluence use the default timeout values defined in class com.atlassian.pageobjects.elements.timeout.DefaultTimeouts:
# All but EVALUATION_INTERVAL are timeouts. EVALUATION_INTERVAL is the polling interval. com.atlassian.timeout.EVALUATION_INTERVAL=100 # setting timeouts below 1000ms is not recommended! # The following values are the one defined in com.atlassian.pageobjects.elements.timeout.DefaultTimeouts com.atlassian.timeout.DEFAULT=5000 com.atlassian.timeout.UI_ACTION=1000 com.atlassian.timeout.PAGE_LOAD=20000 com.atlassian.timeout.SLOW_PAGE_LOAD=20000 com.atlassian.timeout.DIALOG_LOAD=5000 com.atlassian.timeout.COMPONENT_LOAD=3000 com.atlassian.timeout.AJAX_ACTION=5000
If you need to increase the timeout of Poller.waitUntil
method, create a properties file named com/atlassian/timeout/pageobjects-timeouts.properties,
put all the above properties and increase the value of com.atlassian.timeout.DEFAULT
to 10000:
com.atlassian.timeout.EVALUATION_INTERVAL=100 com.atlassian.timeout.DEFAULT=10000 com.atlassian.timeout.UI_ACTION=1000 com.atlassian.timeout.PAGE_LOAD=20000 com.atlassian.timeout.SLOW_PAGE_LOAD=20000 com.atlassian.timeout.DIALOG_LOAD=5000 com.atlassian.timeout.COMPONENT_LOAD=3000 com.atlassian.timeout.AJAX_ACTION=5000