December 31, 2015

Automate Amazon: Writing a Sign In Test

This post is fourth of a series of nine. Need to go back to the beginning?

Drafting a Login Test for Amazon.com won't be as easy as drafting one for Dave Haeffner's mock site, The-Internet. There needs to be a lot more infrastructure put in place besides the CommonUtils library we worked on in the last blog post. Also, Amazon.com use the word "Login". Instead, they use the phrase Sign In.


Sketch the SignIn Steps

Here's how you log into sign into Amazon.com's site:
  1. Go to Amazon.com's home page, http://www.amazon.com/
  2. Hover your cursor over the "Your Account" block, and click the sign in button.
  3. Once you are on the sign in page, enter the username, password into the appropriate text boxes. 
  4. Select the Sign In button. 
I noticed after following this process a few times, that there sometimes was a bit of a lag, so we might want to wait until the username and password actually appear before entering a username and password. 

Review: How to find selectors of Web Elements

Let's say we want to know about what selectors to use for the username, password, and Sign In button on the Sign In page.

You can find the ids and cssSelectors of an object by:
  • Opening the Firefox browser with the Firebug and Firepath plugin. 
  • Going to http://www.amazon.com/ and pressing the "Sign In" button.
  • Right clicking and selecting on the textboxes or the button and selecting "Inspect in Firepath".
  • With the "Firepath" tab, make sure "CSS" is selected. 
We can see that the following web elements have these values:
  • Email textbox: cssSelector #ap_email
  • Password textbox: cssSelector #ap_password
  • Sign In Button: cssSelector #signInSubmit
... Yes, these values are technically IDs and not CSS Selectors. Adding the '#' makes them CSS Selectors. At my workplace, I find that IDs of web elements are constantly changing, since the ID is usually a numbered index. CSS Values seem to change less, so I got in the habit of leaning towards CSS Selectors over IDs. 


Sketch out the Infrastructure Needed

Judging from what we have listed above, we will need the following classes written:
  • A Test Class, PurchaseOrderTest, that stores the tests.
  • A class to store the username and password of test users, and a class to retrieve the data.
  • Methods in CommonUtilites that handle sending keys to textboxes, clicking on buttons, and hovering-and-clicking on sections of the home page.
  • Two classes called Page Objects to store how the HomePage and the LoginPage interacts with the DOM.
  • We can bundle together commonly used methods in an Actions class, and call it OrderActions.

What our Directory Structure Will Look Like


After we store the User Properties, create the Actions classes, and create the test class, our directory structure could look like:

src/test/java

  • actions
    • OrderActions
  • base
    • LoadProperties
  • pages
    • HomePage
    • SignInPage
  • properties
    • user.properties
  • testcases
    • PurchaseOrderTest
  • utils
    • CommonUtils
    • DriverUtils



Store the User Properties


Store the Username and Password in a text file called a Properties file, user.properties. Create a class called LoadProperties in order to handle the reading and the writing of the file. (Code formatting from http://codeformatter.blogspot.com/).

java / properties / user.properties:
1:  tester23.username=amzn.tester23@gmail.com  
2:  tester23.password=amzntester23  

java / base / LoadProperties.java
1:  package base;  
2:  import org.apache.commons.lang3.StringUtils;  
3:  import java.io.FileInputStream;  
4:  import java.io.FileNotFoundException;  
5:  import java.io.IOException;  
6:  import java.util.Properties;  
7:  import java.util.Set;  
8:  /**  
9:   * Created by tmaher on 12/22/2015.  
10:   */  
11:  public class LoadProperties {  
12:    public static Properties user = loadProperties("src/test/java/properties/user.properties");  
13:    private static Properties loadProperties(String filePath) {  
14:      Properties properties = new Properties();  
15:      try {  
16:        FileInputStream f = new FileInputStream(filePath);  
17:        properties.load(f);  
18:      } catch (FileNotFoundException e) {  
19:        e.printStackTrace();  
20:      } catch (IOException e){  
21:        e.printStackTrace();  
22:      }  
23:      return properties;  
24:    }  
25:    public static String getPropertyValue(String path, String key){  
26:      Properties p = loadProperties(path);  
27:      String result = "";  
28:      Set<String> values = p.stringPropertyNames();  
29:      for(String value : values){  
30:        if(StringUtils.equalsIgnoreCase(value, key)){  
31:          result = p.getProperty(value);  
32:          break;  
33:        }  
34:      }  
35:      return result;  
36:    }  
37:  }  
All Source Code can be found in T.J. Maher's Automate-Amazon repository. 

Next, we can work from the bottom level to the top:
  • Adding methods to CommonUtils
  • Abstracting each page into a PageObject such as HomePage and SignInPage
  • Bundling the methods in the PageObjects to create repeatable Actions we can use.
  • Compose the Actions methods into a test we can run. 

1. Add to CommonUtil 

Add to CommonUtils methods the basic building blocks our page objects will call. All Selenium WebDriver calls will be encapsulated in a method on CommonUtils.

  • Navigate to a URL

 public void navigateToURL(String URL) {  
     try {  
       _driver.navigate().to(URL);  
     } catch (Exception e) {  
       System.out.println("FAILURE: URL did not load: " + URL);  
       throw new TestException("URL did not load");  
     }  
   }  

  • SendKeys to a Textbox, given the web element by selector, and the value.

 public void sendKeys(By selector, String value) {  
     WebElement element = getElement(selector);  
     clearField(element);  
     try {  
       element.sendKeys(value);  
     } catch (Exception e) {  
       throw new TestException(String.format("Error in sending [%s] to the following element: [%s]", value, selector.toString()));  
     }  
 }  

  • Click on a button, given the web element by selector

 public void click(By selector) {  
     WebElement element = getElement(selector);  
     waitForElementToBeClickable(selector);  
     try {  
       element.click();  
     } catch (Exception e) {  
       throw new TestException(String.format("The following element is not clickable: [%s]", selector));  
     }  
   }  

  • Hovers a cursor over a web element and click it
 public void scrollToThenClick(By selector) {  
     WebElement element = _driver.findElement(selector);  
     actions = new Actions(_driver);  
     try {  
       ((JavascriptExecutor) _driver).executeScript("arguments[0].scrollIntoView(true);", element);  
       actions.moveToElement(element).perform();  
       actions.click(element).perform();  
     } catch (Exception e) {  
       throw new TestException(String.format("The following element is not clickable: [%s]", element.toString()));  
     }  
   }  


  • Waits Until an Element is Visible
 public void waitForElementToBeVisible(By selector) {  
     try {  
       wait = new WebDriverWait(_driver, timeout);  
       wait.until(ExpectedConditions.presenceOfElementLocated(selector));  
     } catch (Exception e) {  
       throw new NoSuchElementException(String.format("The following element was not visible: %s", selector));  
     }  
   }  

2. Page Objects

Now that the Selenium WebDriver functionality has been encapsulated, we can extend the page objects to use CommonUtils. We are inheriting from CommonUtilites the above methods.

These Page Objects are the only places that should interact with the web elements on the page, evaluating if the web elements are there, checking and setting their values.

On the top of each Page Object, we have the selectors for each web element. They are each declared private because they are only to be accessed in this page object. They are also declared final because they are constant.

By is a reserved word in the Selenium library. Web elements can be found By.id, By.cssSelector, By.name, etc.



HomePage:
1:  package pages;  
2:  import enums.Url;  
3:  import org.openqa.selenium.By;  
4:  import utils.CommonUtils;  
5:  /**  
6:   * Created by tmaher on 12/21/2015.  
7:   */  
8:  public class HomePage extends CommonUtils {  
9:    private final By YOUR_ACCOUNT = By.id("nav-link-yourAccount");  
10:    private final By SHOPPING_CART_ICON = By.cssSelector("#nav-cart");  
11:    private final By SHOPPING_CART_COUNT = By.cssSelector("#nav-cart > #nav-cart-count");  
12:    public HomePage(){  
13:    }  
14:    public void navigateToHomePage() {  
15:      String url = Url.BASEURL.getURL();  
16:      System.out.println("Navigating to Amazon.com: " + url);  
17:      navigateToURL(url);  
18:    }  
19:    public void navigateToSignInPage(){  
20:      System.out.println("HOME_PAGE: Selecting [YOUR_ACCOUNT] in navigation bar.");  
21:      scrollToThenClick(YOUR_ACCOUNT);  
22:      System.out.println("HOME_PAGE: Navigating to the SIGNIN_PAGE.\n");  
23:    }  
24:  }  

SignInPage:
1:  package pages;  
2:  import org.openqa.selenium.By;  
3:  import utils.CommonUtils;  
4:  /**  
5:   * Created by tmaher on 12/21/2015.  
6:   */  
7:  public class SignInPage extends CommonUtils {  
8:    private final By USERNAME = By.cssSelector("#ap_email");  
9:    private final By PASSWORD = By.cssSelector("#ap_password");  
10:    private final By SIGNIN_BUTTON = By.cssSelector("#signInSubmit");  
11:    public void enterUsername(String userName){  
12:      System.out.println("SIGNIN_PAGE: Entering username: " + userName);  
13:      waitForElementToBeVisible(USERNAME);  
14:      sendKeys(USERNAME, userName);  
15:    }  
16:    public void enterPassword(String password){  
17:      System.out.println("SIGNIN_PAGE: Entering password.");  
18:      waitForElementToBeVisible(PASSWORD);  
19:      sendKeys(PASSWORD, password);  
20:    }  
21:    public void clickSignInButton(){  
22:      System.out.println("SIGNIN_PAGE: Clicking the [SIGN_IN] button.\n");  
23:      click(SIGNIN_BUTTON);  
24:    }  
25:  }  

3. Actions Classes

When someone enters a username into the SignIn page, it's a safe bet that they are going to want to enter a password, too, along with clicking on the SignIn button. If someone wants to write a test that explicitly asserts that yes, we can enter text into the username textbox, they can do that by accessing the SignIn page object. But most of the time, those three methods will be grouped together.

Below, we group them together in a method called loginAs(String username, String password). Pass in a username and password, and it will do the rest.

OrderActions.java
1:  package actions;  
2:  import pages.*;  
3:  /**  
4:   * Created by tmaher on 12/21/2015.  
5:   */  
6:  public class OrderActions {  
7:    public void navigateToHomePage(){  
8:      HomePage homePage = new HomePage(); // Instantiate a new HomePage page object 
9:      homePage.navigateToHomePage();  
10:    }  
11:    public void loginAs(String username, String password){  
12:      HomePage homePage = new HomePage();  // Instantiate a new HomePage page object 
13:      SignInPage signIn = new SignInPage();  // Instantiate a new SignInPage page object 
14:      homePage.navigateToSignInPage();  
15:      signIn.enterUsername(username);  // Use the methods on the SignInPage
16:      signIn.enterPassword(password);  
17:      signIn.clickSignInButton();  
18:    }  
19:  }  


4. PurchaseOrderTest: test_Login

Now that we have all the components, we can start assembling the pieces in the Actions class to form a test.

PurchaseOrderTest.java
1:  package testcases;  
2:  import base.LoadProperties;  
3:  import org.openqa.selenium.WebDriver;  
4:  import actions.*;  
5:  import org.testng.annotations.AfterClass;  
6:  import org.testng.annotations.BeforeClass;  
7:  import org.testng.annotations.Test;  
8:  import utils.DriverUtils;  
9:  import static org.testng.Assert.assertEquals;  
10:  /**  
11:   * Created by tmaher on 12/14/2015.  
12:   */  
13:  public class PurchaseOrderTest {  
14:    public WebDriver driver;  
15:    @BeforeClass  
16:    public void setUp(){  
17:      driver = DriverUtils.getDriver();  
18:    }  
19:    @Test()  
20:    public void test_Login(){  
21:      OrderActions orderActions = new OrderActions();  
22:      String username = LoadProperties.user.getProperty("tester23.username");  
23:      String password = LoadProperties.user.getProperty("tester23.password");  
24:      orderActions.navigateToHomePage();  
25:      orderActions.loginAs(username, password);  
26:   
27:    }  
28:    @AfterClass  
29:    public void tearDown(){  
30:      driver.quit();  
31:    }  
32:  }  
All Source Code can be found in T.J. Maher's Automate-Amazon repository. 


5. Run the Test


Now that everything is all set, we can right click on the test method for test_Login and run the test:

 Navigating to Amazon.com: http://www.amazon.com  
 HOME_PAGE: Selecting [YOUR_ACCOUNT] in navigation bar.  
 HOME_PAGE: Navigating to the SIGNIN_PAGE.  
 SIGNIN_PAGE: Entering username: amzn.tester23@gmail.com  
 SIGNIN_PAGE: Entering password.  
 SIGNIN_PAGE: Clicking the [SIGN_IN] button.  
All Source Code can be found in T.J. Maher's Automate-Amazon repository. 

... Normally, we would then assert if we are on the correct page or not. I didn't add that into the test since what I really wanted to do was the next blog entry.

Until then, happy coding!

View the (mostly) Completed Test Code:


NEXT: Setup Objects to Handle Various Products, such as Books! >> 


-T.J. Maher
 Sr. QA Engineer, Fitbit
 Boston, MA

// Automated tester for [ 8 ] month and counting!

Please note: 'Adventures in Automation' is a personal blog about automated testing. It is not an official blog of Fitbit.com



14 comments:

nivedhitha reddy said...

Useful information online software testing course

Sadhana Rathore said...

This is exceedingly helpful information, very good work. Thanks for sharing and let me wait for further updates.
AWS Training in Chennai
AWS course in Chennai
DevOps Training in Chennai
DevOps Certification in Chennai
Cloud Computing Training in Chennai
Cloud Computing Courses in Chennai
AWS Training in Velachery
AWS Training in Tambaram
AWS course in Chennai

sheela rajesh said...

Brilliant ideas that you have share with us.It is really help me lot and i hope it will help others also.
update more different ideas with us.
Selenium Training in Chennai
selenium training in OMR
JAVA Training in Chennai
Python Training in Chennai
Hadoop Training in Chennai
Software testing training in chennai
Selenium Training in Chennai
Selenium Training in Velachery

janakikrishnan said...

Looks great and every freshers want to go through your blog for their growth.
Selenium Training in Bangalore
Selenium Course in Bangalore
Best Selenium Training Institute in Bangalore
Selenium Training in Coimbatore
Selenium Course in Coimbatore
Selenium Classes in Coimbatore

Aruna Ram said...

Nice content! It was very useful for my development. Thank you for your great post and I like more one post from your blog...


Spark Training in Chennai
Spark Training Fees in Chennai
Pega Training in Chennai
Primavera Training in Chennai
Unix Training in Chennai
Linux Training in Chennai
Social Media Marketing Courses in Chennai
Power BI Training in Chennai
Tableau Training in Chennai

Abdul said...

Nice blog. You provide very helpful tips in this blog. We offer AWS Online as well as Classroom Training with 100% job placement. AWS Training

Unknown said...

Grilled Lamb Chops Recipe | Easy Healthy Dinner Recipes At Home

Lamb chops go with frying, barbecuing grilling or roasting and will cook in about ten minutes. It is also best healthy Lamb recipe.Cooked on the grill or in the skillet, lamb chops are stylish but super-fast snacks. From curried to cranberry fixed variations, these easy lamb chop recipes carry big flavor.

janakikrishnan said...

Very nice blog. The contents are valuable. Do well and Keep going.
AWS Training in Bangalore
AWS Course in Bangalore
Best AWS Training in Bangalore
AWS Training Institutes in Bangalore
AWS Certification Training in Bangalore
AWS Training Center in Bangalore

Raju said...

This article really helps me to know more about this technology.Thanks for sharing this information in your blog, keep doing this continuously.
Selenium Training in Chennai
Selenium Course in Chennai
Selenium Training in Velachery
Selenium Training in Tambaram
Selenium Training in Anna Nagar
Software Testing Training in Chennai
Software Testing Course in Chennai
Software Testing Training in Velachery

rudraveni said...

Really very happy to say that your post is very interesting. I never stop myself to say something about it. You did a great job. Keep it up.
We have an excellent IT courses training institute in Hyderabad. We are offering a number of courses that are very trendy in the IT industry. For further information, please once go through our site.
AWS Training In Hyderabad

Durai Raj said...

Great information!!! I liked the way… how you conveyed the information. Thanks for it
php training institute in coimbatore
PHP Training in Coimbatore
Ethical Hacking Course in Bangalore
German Classes in Bangalore
German Classes in Madurai
Hacking Course in Coimbatore
German Classes in Coimbatore

Unknown said...

We are best and trusted bangladeshi online news portal website. Everyday we publish the national and international latest news. If you want to get regular newslatter from our newspaper, please go home page BANGLA NEWS and click the below subscribe button.

বাংলাদেশ :
Read Bangla Breaking বাংলাদেশ News on Parliament, Govt, Justice, Road Accident, Cricket, Sports, Education, Business, Agriculture, Population, Dhaka at todaybanglenews.com
রাজনীতি :
বাংলাদেশের রাজনীতির খবর/সংবাদ - Bangladesh Political News। সরকার, বিএনপি/আওয়ামী লীগ/জাতীয় পার্টি/জামায়াত, শেখ হাসিনা/খালেদা জিয়া/এরশাদ, উপজেলা, রাষ্ট্রপতি, ছাত্রলীগ/যুবলীগ/ছাত্রদল/যুবদল/ছাত্র সমাজ বিষয়ক ফিচার at todaybanglenews.com
আন্তর্জাতিক :
আন্তর্জাতিক,Read Bangla Breaking World News on USA, UK, India, Pakistan, Asia, China, Europe, Middle East, Latin America, Africa, Australia, America & UN at todaybanglenews.com
অর্থনীতি :
অর্থনীতি,Read Bangla Breaking World News on USA, UK, India, Pakistan, Asia, China, Europe, Middle East, Latin America, Africa, Australia, America & UN at todaybanglenews.com
ইসলাম ও জীবন :
ইসলাম ও জীবন, রমজান, ইজতেমা, মুসলিম বিশ্ব, মাসআলা-মাসায়েল, ইতিহাস ও ঐতিহ্য, সাক্ষাৎকার, bangladesh news, bangladesh newspaper, bangladesh news paper, bangladeshi newspaper, bangladeshi news paper at todaybanglenews.com
বিনোদন খবর :
বিনোদন খবর ও সংবাদ - Bangla Movie and Entertainment News। ছবি, শুটিং, মঞ্চ, শিল্পী, নাচ বিষয়ক ফিচার। প্রথম আলো, বাংলাদেশের সর্বাধিক পঠিত অনলাইন বাংলা সংবাদপত্র/পত্রিকা at todaybanglenews.com
খেলাধুলা :
খেলার খবর/সংবাদ - খেলাধুলা, ক্রীড়া ও ক্রিকেট - Bangla Sports News। ফুটবল, ক্রিকেট, টেনিস, বিশ্বকাপ, শিরোপা, টি-টোয়েন্টি, বল, সেমি-ফাইনাল, বোলার বিষয়ক ফিচার at todaybanglenews.com
লাইফ স্টাইল :

লাইফ স্টাইল, আমার পরিবার, ভ্রমণ, চাকরির খোঁজ, সমাধান, রান্না, রূপচর্চা, সংবাদ, টিপস, bangladesh news, bangladesh newspaper, bangladesh news paper, bangladeshi newspaper at todaybanglenews.com

Unknown said...

We want to be your most trusted ally in your pursuit of health and well-being.How you feel affects every precious day of your life. healthtipsschool understands that, which is why we’re committed to being your most trusted ally in your pursuit of health and well-being.You can depend on us to provide expert content along with genuine caring. Both of which will support, Recipe guide, and inspire you toward the best possible health outcomes for you and your amily.Bottom line: We’re human, just like you. We know that peace of mind can make all the difference in how you feel. So we’ll be here when you need us.

Health :
Healthtipsschool News reports on emerging research, new treatments, diet, exercise, and trending topics in health and wellness. Get results health tips man with different meditation techniques. Variations in technique will allow you to tap into a greater number of physiological and psychological benefits.

Weight Loss :
Wondering how to lose weight in a week ? Our weight loss tips, diet plans, videos, and success stories are the tools and motivation you need to make it happen.

Disease :
Healthtipsschool explain you This brief A-Z guide covers some of the more common Stress diseases and conditions, including a definition and the causes, symptoms & treatments.

Diabetes :
The things you've wanted to know about how to control diabetesfor type 2 diabetes and type 1 diabetes are all in one place. Learn more about the symptoms, foods to avoid, and lifestyle management.

Fitness :
Find everything you need to crush your fitness goals such as workout routines, training plans, free workout videos, fitness tips, exercise trends, workout playlists gear, clothes and more.

Nutrition :
Daily articles about food and nutrition, weight loss, and health. All articles are based on scientific evidence, written and fact checked by experts. Our licensed nutritionists writes content for you.

Lifestyle :
Tips and info on Lifestyle, beauty, fashion, travel, health, sex, love and everything else you need to live a fuller and happier life.

Celebrity News :

celebrities news latest and interviews, including their fitness tips, workout routines, health advice, and beauty secrets.

rudraveni said...

Thanks for Sharing this great article..Its really nice and useful for us… keep sharing..
AWS Training In Hyderabad