|
| 1 | +[Home](../README.md) |
| 2 | + |
| 3 | +# Getting Started with WebTester |
| 4 | + |
| 5 | +## What you'll create |
| 6 | +You'll write a simple GUI test for [Twitter](https://twitter.com/) using WebTester that tests basic login |
| 7 | +as well as tweeting a simple message. The end result will be similar to this: |
| 8 | + |
| 9 | + |
| 10 | + |
| 11 | +## What you'll need |
| 12 | + |
| 13 | +- About 30 Minutes |
| 14 | +- Eclipse (You can use any IDE, but the guide is using Eclipse) |
| 15 | +- Java 1.7 or newer |
| 16 | + |
| 17 | +## Create the project |
| 18 | +Open Eclipse and create a new Maven project. Leave the default values until the group and artifact Id need be to specified. |
| 19 | +Set the group Id to "info.novatec.testit" and the artifact Id to "webtester-example-twitter". |
| 20 | +Set up the project and create the files as depicted below. |
| 21 | + |
| 22 | + |
| 23 | + |
| 24 | +Configure the Maven project to look like this and replace `${webtester-version}` with the version you want to use: |
| 25 | + |
| 26 | +```xml |
| 27 | +<project |
| 28 | + xmlns="http://maven.apache.org/POM/4.0.0" |
| 29 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| 30 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| 31 | + <modelVersion>4.0.0</modelVersion> |
| 32 | + |
| 33 | + <groupId>info.novatec.testit</groupId> |
| 34 | + <artifactId>webtester-example-twitter</artifactId> |
| 35 | + <version>0.0.1-SNAPSHOT</version> |
| 36 | + <packaging>jar</packaging> |
| 37 | + |
| 38 | + <name>webtester-example-twitter</name> |
| 39 | + <url>https://documentation.novatec-gmbh.de/display/TESTIT</url> |
| 40 | + |
| 41 | + <dependencies> |
| 42 | + <dependency> |
| 43 | + <groupId>info.novatec.testit</groupId> |
| 44 | + <artifactId>webtester-support-firefox</artifactId> |
| 45 | + <version>${webtester-version}</version> |
| 46 | + </dependency> |
| 47 | + <dependency> |
| 48 | + <groupId>info.novatec.testit</groupId> |
| 49 | + <artifactId>webtester-support-junit</artifactId> |
| 50 | + <version>${webtester-version}</version> |
| 51 | + </dependency> |
| 52 | + <dependency> |
| 53 | + <groupId>junit</groupId> |
| 54 | + <artifactId>junit</artifactId> |
| 55 | + <version>4.12</version> |
| 56 | + </dependency> |
| 57 | + <dependency> |
| 58 | + <groupId>ch.qos.logback</groupId> |
| 59 | + <artifactId>logback-classic</artifactId> |
| 60 | + <version>1.1.3</version> |
| 61 | + </dependency> |
| 62 | + </dependencies> |
| 63 | + |
| 64 | + <repositories> |
| 65 | + <repository> |
| 66 | + <id>novatec</id> |
| 67 | + <name>NovaTec Public Repository</name> |
| 68 | + <url>http://repository.novatec-gmbh.de/content/repositories/novatec/</url> |
| 69 | + </repository> |
| 70 | + </repositories> |
| 71 | + |
| 72 | + <build> |
| 73 | + <plugins> |
| 74 | + <plugin> |
| 75 | + <groupId>org.apache.maven.plugins</groupId> |
| 76 | + <artifactId>maven-compiler-plugin</artifactId> |
| 77 | + <version>3.1</version> |
| 78 | + <configuration> |
| 79 | + <source>1.7</source> |
| 80 | + <target>1.7</target> |
| 81 | + <compilerVersion>1.7</compilerVersion> |
| 82 | + <encoding>UTF8</encoding> |
| 83 | + <showWarnings>true</showWarnings> |
| 84 | + <showDeprecation>true</showDeprecation> |
| 85 | + </configuration> |
| 86 | + </plugin> |
| 87 | + </plugins> |
| 88 | + </build> |
| 89 | + |
| 90 | +</project> |
| 91 | +``` |
| 92 | + |
| 93 | +Create a new file: `testit-webtester.properties` and set your twitter credentials: |
| 94 | +```properties |
| 95 | +twitter.username=INSERT_TWITTER_USERNAME |
| 96 | +twitter.password=INSERT_TWITTER_PASSWORD |
| 97 | +``` |
| 98 | + |
| 99 | +## Create PageObject for Login Page |
| 100 | +After you've set up the project it's time to start writing some code. |
| 101 | + |
| 102 | +To login into your Twitter account we need to setup a PageObject for the Login Page. Open the TwitterLogin |
| 103 | +class and have it extend the PageObject class. Now we need to find the respective HTML elements to interact |
| 104 | +with on the Twitter page. WebTester can identify Objects by id, class, xpath or css using Selenium. After inspecting |
| 105 | +the HTML source of the Twitter Login Page you'll need to find the Objects you can interact with. In this case the login |
| 106 | +button, the username field and the password field. We'll identify these two fields by id, while we'll use the class to |
| 107 | +get the login button. |
| 108 | + |
| 109 | +We need to make sure that we are on the correct page @PostConstruct of the PageObject. To achieve this the page title |
| 110 | +is matched with the title we expect. In our case the title should be the following. |
| 111 | + |
| 112 | +> Welcome to Twitter - Login or Sign up |
| 113 | +
|
| 114 | +For all the gory details, please view the source code below at line 23. |
| 115 | + |
| 116 | +For the login process we need the following methods: setUsername, setPassword, clickLogin, and login. Note that these |
| 117 | +methods return type must extend PageObject. It is a representation of the state of the page opened after the methods |
| 118 | +execution. |
| 119 | + |
| 120 | +The methods setUsername and setPassword return instances of TwitterLogin while clickLogin and login return instances |
| 121 | +of TwitterHome. |
| 122 | + |
| 123 | +```java |
| 124 | +package pageobjects; |
| 125 | + |
| 126 | +import static org.junit.Assert.assertEquals; |
| 127 | + |
| 128 | +import info.novatec.testit.webtester.api.annotations.AfterInitialization; |
| 129 | +import info.novatec.testit.webtester.api.annotations.IdentifyUsing; |
| 130 | +import info.novatec.testit.webtester.api.enumerations.Method; |
| 131 | +import info.novatec.testit.webtester.pageobjects.Button; |
| 132 | +import info.novatec.testit.webtester.pageobjects.PageObject; |
| 133 | +import info.novatec.testit.webtester.pageobjects.PasswordField; |
| 134 | +import info.novatec.testit.webtester.pageobjects.TextField; |
| 135 | + |
| 136 | + |
| 137 | +public class TwitterLogin extends PageObject { |
| 138 | + |
| 139 | + @IdentifyUsing ( method = Method.CLASS, value = "primary-btn" ) |
| 140 | + private Button loginButton; |
| 141 | + @IdentifyUsing ( "signin-email" ) |
| 142 | + private TextField usernameField; |
| 143 | + @IdentifyUsing ( "signin-password" ) |
| 144 | + private PasswordField passwordField; |
| 145 | + |
| 146 | + @PostConstruct |
| 147 | + private void assertThatCorrectPageIsDisplayed () { |
| 148 | + assertEquals("Welcome to Twitter - Login or Sign up", getBrowser().getPageTitle()); |
| 149 | + } |
| 150 | + |
| 151 | + public TwitterHome login (String username, String password) { |
| 152 | + return setUsername(username).setPassword(password).clickLogin(); |
| 153 | + } |
| 154 | + |
| 155 | + public TwitterLogin setUsername (String username) { |
| 156 | + usernameField.setText(username); |
| 157 | + return this; |
| 158 | + } |
| 159 | + |
| 160 | + public TwitterLogin setPassword (String password) { |
| 161 | + passwordField.setText(password); |
| 162 | + return this; |
| 163 | + } |
| 164 | + |
| 165 | + public TwitterHome clickLogin () { |
| 166 | + loginButton.click(); |
| 167 | + return create(TwitterHome.class); |
| 168 | + } |
| 169 | + |
| 170 | +} |
| 171 | +``` |
| 172 | + |
| 173 | +**Note:** When using `@IdentifyUsing` with an Id, it's not necessary to explicitly define the method used as Id is the default. |
| 174 | + |
| 175 | +## Create PageObject for Home Page |
| 176 | + |
| 177 | +Similar to the Login Page we create a PageObject representation for the Twitter Home Page. |
| 178 | + |
| 179 | +```java |
| 180 | +package pageobjects; |
| 181 | + |
| 182 | +import static org.junit.Assert.assertEquals; |
| 183 | + |
| 184 | +import info.novatec.testit.webtester.api.annotations.AfterInitialization; |
| 185 | +import info.novatec.testit.webtester.api.annotations.IdentifyUsing; |
| 186 | +import info.novatec.testit.webtester.api.enumerations.Method; |
| 187 | +import info.novatec.testit.webtester.pageobjects.Button; |
| 188 | +import info.novatec.testit.webtester.pageobjects.PageObject; |
| 189 | +import pageobjects.widgets.TweetBox; |
| 190 | + |
| 191 | + |
| 192 | +public class TwitterHome extends PageObject { |
| 193 | + |
| 194 | + @IdentifyUsing ( "tweet-box-home-timeline" ) |
| 195 | + private TweetBox tweetBox; |
| 196 | + @IdentifyUsing ( method = Method.CSS, value = |
| 197 | + ".btn.primary-btn.tweet-action.tweet-btn.js-tweet-btn" ) |
| 198 | + private Button sendTweetButton; |
| 199 | + @IdentifyUsing ( method = Method.XPATH, value = |
| 200 | + ".//ol[@id='stream-items-id']/li[1]//p[contains(@class, 'tweet-text')]" ) |
| 201 | + private PageObject latestTweet; |
| 202 | + |
| 203 | + @PostConstruct |
| 204 | + private void assertThatCorrectPageIsDisplayed () { |
| 205 | + assertEquals("Twitter", getBrowser().getPageTitle()); |
| 206 | + } |
| 207 | + |
| 208 | + public TwitterHome tweet (String message) { |
| 209 | + setTweetMessage(message).sendTweet(); |
| 210 | + return this; |
| 211 | + } |
| 212 | + |
| 213 | + public TwitterHome setTweetMessage (String message) { |
| 214 | + tweetBox.setMessage(message); |
| 215 | + return this; |
| 216 | + } |
| 217 | + |
| 218 | + public TwitterHome sendTweet () { |
| 219 | + sendTweetButton.click(); |
| 220 | + return create(TwitterHome.class); |
| 221 | + } |
| 222 | + |
| 223 | + public String getMessageOfLatesTweet () { |
| 224 | + return latestTweet.getVisibleText(); |
| 225 | + } |
| 226 | + |
| 227 | +} |
| 228 | +``` |
| 229 | + |
| 230 | +As PageObjects can represent either entire pages or just a certain part of it, we use the TweetBox class as a |
| 231 | +representation of Twitter´s TweetBox. |
| 232 | + |
| 233 | +```java |
| 234 | +package pageobjects.widgets; |
| 235 | + |
| 236 | +import info.novatec.testit.webtester.pageobjects.PageObject; |
| 237 | + |
| 238 | + |
| 239 | +public class TweetBox extends PageObject { |
| 240 | + |
| 241 | + public TweetBox setMessage (String message) { |
| 242 | + click(); |
| 243 | + getWebElement().sendKeys(message); |
| 244 | + return this; |
| 245 | + } |
| 246 | + |
| 247 | +} |
| 248 | +``` |
| 249 | + |
| 250 | +## Create the Test |
| 251 | + |
| 252 | +The `TwitterTest` must `@RunWith` the `WebTesterJUnitRunner` class for JUnit support. |
| 253 | + |
| 254 | +In this example the `@CreateUsing` annotation specifies the `Browser` to be an instance of Firefox. |
| 255 | + |
| 256 | +The `@EntryPoint` is the initial page used by WebTester. It´s the first page the configured browser navigates to. |
| 257 | + |
| 258 | +The Twitter password and username are taken from the `testit-webtester.properties` file using the `@ConfigurationValue` |
| 259 | +annotation. |
| 260 | + |
| 261 | +`@Before` test execution a representational instance of the Twitter Login page (twitter.com) is returned by the |
| 262 | +`Browser` as a `TwitterLogin` (created above) object. |
| 263 | + |
| 264 | +During the `@Test` WebTester will use twitterLogin to log in with the username and password specified in the |
| 265 | +properties file. After a successful login a tweet containing the current system time is tweeted and the test then |
| 266 | +asserts that the tweet has been tweeted. |
| 267 | + |
| 268 | +```java |
| 269 | +package test; |
| 270 | + |
| 271 | +import static org.junit.Assert.assertEquals; |
| 272 | + |
| 273 | +import java.util.Date; |
| 274 | + |
| 275 | +import javax.annotation.Resource; |
| 276 | + |
| 277 | +import org.junit.Before; |
| 278 | +import org.junit.Test; |
| 279 | +import org.junit.runner.RunWith; |
| 280 | + |
| 281 | +import info.novatec.testit.webtester.utils.Waits; |
| 282 | +import info.novatec.testit.webtester.api.browser.Browser; |
| 283 | +import info.novatec.testit.webtester.browser.factories.FirefoxFactory; |
| 284 | +import info.novatec.testit.webtester.junit.annotations.ConfigurationValue; |
| 285 | +import info.novatec.testit.webtester.junit.annotations.CreateUsing; |
| 286 | +import info.novatec.testit.webtester.junit.annotations.EntryPoint; |
| 287 | +import info.novatec.testit.webtester.junit.runner.WebTesterJUnitRunner; |
| 288 | +import pageobjects.TwitterHome; |
| 289 | +import pageobjects.TwitterLogin; |
| 290 | + |
| 291 | + |
| 292 | +@RunWith ( WebTesterJUnitRunner.class ) |
| 293 | +public class TwitterTest { |
| 294 | + |
| 295 | + @Resource |
| 296 | + @CreateUsing ( FirefoxFactory.class ) |
| 297 | + @EntryPoint ( "https://twitter.com/" ) |
| 298 | + private Browser browser; |
| 299 | + |
| 300 | + @ConfigurationValue ( "twitter.username" ) |
| 301 | + private String username; |
| 302 | + @ConfigurationValue ( "twitter.password" ) |
| 303 | + private String password; |
| 304 | + |
| 305 | + private TwitterLogin twitterLogin; |
| 306 | + |
| 307 | + @Before |
| 308 | + public void initStartPage () { |
| 309 | + twitterLogin = browser.create(TwitterLogin.class); |
| 310 | + } |
| 311 | + |
| 312 | + @Test |
| 313 | + public void testThatMessageCanBeTweeted () throws InterruptedException { |
| 314 | + |
| 315 | + String tweetMessage = "It is " + new Date(); |
| 316 | + TwitterHome home = twitterLogin.login(username, password).tweet(tweetMessage); |
| 317 | + |
| 318 | + Waits.waitSeconds(1); // AJAX actions take some time to be performed |
| 319 | + assertEquals(tweetMessage, home.getMessageOfLatesTweet()); |
| 320 | + |
| 321 | + } |
| 322 | + |
| 323 | +} |
| 324 | +``` |
| 325 | + |
| 326 | +## Summary |
| 327 | +Congratulations! You´ve just developed a simple Twitter login and tweet test with WebTester. |
0 commit comments