Automation for Non-Functional Testing – Mobile Network Connectivity

161

     Most of the time I thought Automation only possible for functional testing. Now, Appium supports non-functional testing like testing of connectivity while automation script execution. Here, I would like to show the capability of Appium to do connectivity testing of Android Native applications. The connectivity testing includes:

  • WiFi
  • Mobile Data
  • Airplane

     HasNetworkConnection interface support setting the connectivity while test script execution. If you are declared the driver as WebDriver then you need to cast the driver with HasNetworkConnection interface. Following are the different connectivity testing actions:

Set WiFi connection on mobile native Android
((HasNetworkConnection) driver).setConnection(Connection.WIFI);

Set Mobile Data connection on mobile native Android
((HasNetworkConnection) driver).setConnection(Connection.DATA);

Set Airplane mode on mobile native Android
((HasNetworkConnection) driver).setConnection(Connection.AIRPLANE);

Set both WiFi and Mobile Data on mobile native Android
((HasNetworkConnection) driver).setConnection(Connection.ALL);

Turn-off both WiFi and Mobile Data on mobile native Android
((HasNetworkConnection) driver).setConnection(Connection.NONE);

To understand the current connectivity on mobile native Android
((HasNetworkConnection) driver).getConnection();

     Try to use all the above actions in your Automation scripts whenever you automate mobile native Android.

make it perfect !

Writing Resilient Test Code

     Ideally, you should be able to write your tests once and run them across all supported browsers. While this is a rosy proposition, there is some work to make this a reliable success. And sometimes there may be a hack or two involved. But the length you must go really depends on the browsers you care about and the functionality you’re dealing with in your application.

     By using high quality locators we’re already in good shape, but there are still some issues to deal with.  This is especially true when working with dynamic, JavaScript heavy pages (which is more the rule than the exception in a majority of web applications you’ll deal with).

     But there is a simple approach that makes up the bedrock of reliable and resilient Selenium tests — and that’s how you wait and interact with elements. Gone are the days of waiting for the page to finish loading, or hard-coding sleeps, or doing a blanket wait time (a.k.a. an implicit wait).  Now are the wonder years of waiting for an expected outcome to occur for a specified amount of time. If the outcome occurs before the amount of time specified, then the test will proceed. Otherwise, it will wait the full amount of time specified.

We accomplish this through the use of explicit waits.

An Example

Let’s step through an example that demonstrates this against a dynamic page on the-internet. The functionality is pretty simple — there is a button. When you click it a loading bar appears for 5 seconds, after which it disappears and is replaced with the text Hello World!

Part 1: Create A New Page Object And Update The Base Page Object

Here’s the markup from the page.

Capture

        At a glance it’s simple enough to tell that there are unique id attributes that we can use to find and click on the start button and verify the finish text.

        When writing automation for new functionality like this, you may find it easier to write the test first (to get it working how you’d like) and then create a page object for it (pulling out the behavior and locators from your test). There’s no right or wrong answer here. Do what feels intuitive to you. But for this example, we’ll create the page object first, and then write the test.

Let’s create a new page object file called DynamicLoading.java in thepageobjects package.

Capture

     In this file we’ll establish inheritance to the base page object and specify the locators and behavior we’ll want to use.

Capture1

     Since there are two examples to choose from we created the methodloadExample which accepts a String of the example number we want to visit as an argument. And similar to our login page object, we have a display check for the finish text (e.g., finishTextPresent()). This check is slightly different though. Aside from the different name, it has a second argument (an integer value of 10). This second argument is how we’ll specify how long we’d like Selenium to wait for an element to be displayed before giving up.

     Let’s update our base page object to enable explicit waits, adding this newwaitForIsDisplayed method to use them.

Capture

     Selenium comes with a wait function which we wrap in a private method (e.g.,private void waitFor) for reuse in this class.

     This method accepts two arguments — the condition we want to wait for (e.g.,ExpectedCondition<WebElement>) and the amount of time we want Selenium to keep checking for (e.g., Integer timeout). If a null value is passed as an argument for the timeout, then the wait time is set to 5seconds. This is handled by a ternary operator (e.g., timeout = timeout != null ? timeout : 5;).

     The waitForIsDisplayed method has two parameters — one for a locator, another for the timeout. Inside the method we call waitFor and send it anExpectedCondition to check for the visibility of an element (e.g.,.visibilityOfElementLocated(locator)). This is similar to our previous display check, but it uses a different Selenium API function that will work with the explicit waits function. You can see a full list of      Selenium’sExpectedConditions here. Unfortunately, this function doesn’t return a Boolean, so we provide one . If the condition is not met by Selenium in the amount of time provided, it will throw a timeout exception. When that happens, we catch it and return false. Otherwise, we return true.

     It’s worth noting that the second parameter is optional when callingwaitForIsDisplayed (e.g., Integer… timeout). If a timeout value is specified, it will get passed to the waitFor method. If nothing is specified,nullwill get passed instead. This gives us the freedom to call this method in our page objects without specifying a timeout (e.g.,waitForIsDisplayed(locator)) or with a timeout (e.g.,waitForIsDisplayed(locator, 20)`).

More on Explicit Waits

     In our page object when we’re using waitForIsDisplayed(finishText, 10) we are telling Selenium to check if the finish text is visible on the page repeatedly. It will keep checking until either the element is displayed or reaches ten seconds — whichever comes first.

     It’s important to set a reasonably sized default timeout for the explicit wait method. But you want to be careful not to make it too high. Otherwise you can run into similar timing issues you get from an implicit wait. But set it too low and your tests will be brittle, forcing you to run down trivial and transient issues.

     The major benefit of explicit waits is that if the behavior on the page takes longer than we expect (e.g., due to slow load times, or a feature change), we can simply adjust this one wait time to fix the test — rather than increase a blanket wait time (which impacts every test). And since the wait is dynamic (e.g., constantly polling), it won’t take the full amount of time to complete (like a static sleep would).

     If you’re thinking about mixing explicit waits with an implicit wait — don’t. If you use both together, you’re going to run into issues later on due to inconsistent implementations of implicit wait across local and remote browser drivers. Long story short, you’ll see inconsistent and odd test behavior.

Part 2: Write A Test To Use The New Page Object

     Now that we have our new page object and an updated base page, it’s time to write our test to use it.

     Let’s create a new file called TestDynamicLoading.java in the testspackage.

Capture

     The contents of this test file are similar to TestLogin with regards to the imported classes and the setUp/tearDown methods.

Capture1

     In our test (e.g., public void hiddenElementLoads()) we are visiting the first dynamic loading example and clicking the start button (which is accomplished in dynamicLoading.loadExample(“1”)). We’re then asserting that the finish text gets rendered.

     When we save this and run it (mvn clean test -Dtest=TestDynamicLoading from the command-line) it will run, wait for the loading bar to complete, and pass.

Part 3: Update Page Object And Add A New Test

     Let’s step through one example to see if our explicit wait approach holds up.

     The second dynamic loading example is laid out similarly to the last one. The only difference is that it renders the final text after the progress bar completes (whereas the previous example had the text on the page but it was hidden).

Here’s the markup for it.

Capture

     In order to find the selector for the finish text element we need to inspect the page after the loading bar sequence finishes. Here’s what it looks like.

Capture

     Let’s add a second test to TestDynamicLoading.java calledelementAppears() that will load this second example and perform the same check as we did for the previous test.

Capture

     When we run both tests (mvn clean test -Dtests=TestDynamicLoading from the command-line) we will see that the same approach will work for both cases.

Browser Timing

     Using explicit waits gets you pretty far. But there are a few things you’ll want to think about when it comes to writing your tests to work against various browsers.

     It’s simple enough to write your tests locally against Firefox and assume you’re all set. Once you start to run things against other browsers, you may be in for a rude awakening. The first thing you’re likely to run into is the speed of execution. A lot of your tests will start to fail when you point them at either Chrome or Internet Explorer, and likely for different reasons.

     In my experience, Chrome execution is very fast, so you will see some odd timeout failures. This is an indicator that you need to add explicit waits to parts of your page objects that don’t already have them. And the inverse is true when running things against older version of Internet Explorer (e.g., IE 8). This is an indicator that your explicit wait times are not long enough since the browser is taking longer to respond — so your tests timeout.

      The best approach to solve this is an iterative one. Run your tests and find the failures. Take each failed test, adjust your code as needed, and run it against the browsers you care about. Repeat until you make a pass all the way through each of the failed tests. Then run a batch of all your tests to see where they fall down. Repeat until everything’s green.

     Once you’re on the other side of these issues, the amount of effort you need to put into it should diminish dramatically.

Conclusion

      By explicitly waiting to complete an action, our tests are in a much more resilient position because Selenium will keep trying for a reasonable amount of time rather than trying just once. And each action can be tuned to meet the needs of each circumstance. Couple that with the dynamic nature of explicit waits, and you have something that will work in a multitude of circumstances — helping you endure even the toughest of browsers to automate.

     This is one of the most important concepts in testing with Selenium. Use explicits waits often.

Reference

http://elementalselenium.com/

Automation and BDD Framework using Cucumber

     In this article, I would like to share the concept of configuring BDD (behavior-driven development) and running of Selenium using Cucumber. Cucumber –JVM is based on cucumber framework which allows to writes feature file in plain text using Gherkin language, this feature is supported by step definitions file which has implemented automation code of Webdriver.

Configuration and Implementation

Seven Steps to configure BDD (behavior-driven development) and running of Selenium or Appium using Cucumber – JVM:

1. First create a maven eclipse project.

2. Create pom.xml and add all the dependendcies

3. Create a feature file and put into “resources” folder.

4. Create step definition file for above scenario and implement WebDriver (for Web based applications) or AppiumDriver (for native applications) automation code. So Create a java file to keep the step definition and put this file under respective package of source folder” src/main/java”.

5. Create Cucumber runner java class which defines cucumber-jvm configuration and put under respective package of source folder ” src/test/java”.

6. Open command prompt and goto project directory and run “mvn install”

7. You should see test will execute and after execution report is generated under directory “\target\cucumber-html-report”. Open index.html file to see the report.

Following are the detailed explanations:

Step 1:  First create a maven eclipse project.

+—src

¦   +—main

¦   ¦   +—java

¦   ¦       +—com

¦   ¦           +—projectname

¦   ¦               +—tests

¦   +—test

¦       +—java

¦           +—com

¦               +—projectname

¦                   +— cucumberrunner

Step 2:  maven pom.xml file has below code:

<project xmlns=http://maven.apache.org/POM/4.0.0&#8221; xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance&#8221;

       xsi:schemaLocation=http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&#8221;>

       <modelVersion>4.0.0</modelVersion>

       <groupId>CucumberTestNG1</groupId>

       <artifactId>CucumberTestNG1</artifactId>

       <version>0.0.1-SNAPSHOT</version>

       <packaging>jar</packaging>

       <name>CucumberTestNG1</name>

       <url>http://maven.apache.org</url&gt;

       <properties>

              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

       </properties>

       <build>

              <plugins>

                     <plugin>

                           <groupId>org.apache.maven.plugins</groupId>

                           <artifactId>maven-surefire-plugin</artifactId>

                           <version>2.18.1</version>

                           <configuration>

                                  <suiteXmlFiles>

                                         <suiteXmlFile>resources/testng.xml</suiteXmlFile>

                                  </suiteXmlFiles>

                           </configuration>

                     </plugin>

              </plugins>

       </build>

       <dependencies>

              <dependency>

                     <groupId>org.seleniumhq.selenium</groupId>

                     <artifactId>selenium-java</artifactId>

                     <version>2.50.0</version>

              </dependency>

              <dependency>

                     <groupId>io.appium</groupId>

                     <artifactId>java-client</artifactId>

                     <version>3.3.0</version>

              </dependency>

              <dependency>

                     <groupId>org.testng</groupId>

                     <artifactId>testng</artifactId>

                     <version>6.9.10</version>

              </dependency>

              <dependency>

                     <groupId>info.cukes</groupId>

                     <artifactId>cucumber-testng</artifactId>

                     <version>1.2.4</version>

              </dependency>

              <dependency>

                     <groupId>info.cukes</groupId>

                     <artifactId>cucumber-java</artifactId>

                     <version>1.2.4</version>

                     <scope>test</scope>

              </dependency>

              <dependency>

                     <groupId>info.cukes</groupId>

                     <artifactId>cucumber-jvm</artifactId>

                     <version>1.2.4</version>

                     <type>pom</type>

              </dependency>

              <dependency>

                     <groupId>info.cukes</groupId>

                     <artifactId>cucumber-jvm-deps</artifactId>

                     <version>1.0.5</version>

              </dependency>

              <dependency>

                     <groupId>net.masterthought</groupId>

                     <artifactId>cucumber-reporting</artifactId>

                     <version>1.2.0</version>

              </dependency>

              <dependency>

                     <groupId>info.cukes</groupId>

                     <artifactId>gherkin</artifactId>

                     <version>2.12.2</version>

              </dependency>

              <dependency>

                     <groupId>org.mockito</groupId>

                     <artifactId>mockito-all</artifactId>

                     <version>2.0.2-beta</version>

              </dependency>

              <dependency>

                     <groupId>com.google.guava</groupId>

                     <artifactId>guava</artifactId>

                     <version>18.0</version>

              </dependency>

              <dependency>

                     <groupId>org.hamcrest</groupId>

                     <artifactId>hamcrest-all</artifactId>

                     <version>1.3</version>

              </dependency>

       </dependencies>

</project>

Step 3: Create a feature “googlesearch.feature” file and put into “resources” folder. This file contain below scenario:

Feature: Google Search

  Scenario: Advance Search in Google

    Given user is on google search page

    When enter “journey of quality” text into search field

    And click on search button

    Then verify google logo is “true”

Step 4: Now need to create step definition file for above scenario and implement WebDriver (for Web based applications) or AppiumDriver (for native applications) automation code. So Create a java file “GoogleSearchTest.java” and put under package “com.projectname.tests” of source folder” src/main/java” and write below code:

package com.projectname.tests;

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.chrome.ChromeDriver;

import org.testng.Assert;

import cucumber.api.java.After;

import cucumber.api.java.Before;

import cucumber.api.java.en.Given;

import cucumber.api.java.en.Then;

import cucumber.api.java.en.When;

public class GoogleSearchTest {

       public static WebDriver driver;

       // Not TestNG annotation and it related to cucumber.api

       @Before

       public void setUp() {

              System.setProperty(

                           “webdriver.chrome.driver”,

                           “E://Softwares//Important tools//selenium-2.44.0//Old Drivers//chromedriver.exe”);

              driver = new ChromeDriver();

              driver.manage().window().maximize();

       }

       // Not TestNG annotation and it related to cucumber.api

       @After

       public void tearDown() {

              // driver.quit();

       }

       // This annotation related to precondition in test execution like

       // @BeforeTest/@BeforeMethod/@BeforeClass

       @Given(“^user is on google search page$”)

       public void user_is_on_google_search_page() throws Throwable {

              driver.get(“https://www.google.co.in/&#8221;);

       }

       // This annotation same as @Test of TestNG, here we are doing actual

       // operation

       @When(“^enter \”([^\”]*)\” text into search field$”)

       public void enter_text_into_search_field(String arg) throws Throwable {

              driver.findElement(By.id(“lst-ib”)).sendKeys(arg);

       }

       // This annotation same as @Test of TestNG, here we are doing actual

       // operation

       @When(“^click on search button$”)

       public void click_on_search_button() throws Throwable {

              driver.findElement(By.id(“sbds”)).click();

       }

       // This annotation related to postcondition in test execution like

       // @AfterTest/@AfterMethod/@AfterClass

       @Then(“^verify google logo is \”([^\”]*)\”$”)

       public void verify_google_logo_is(boolean msg) throws Throwable {

              WebElement message = driver.findElement(By

                           .xpath(“.//*[@id=’logo’]/img”));

              Assert.assertEquals(message.isDisplayed(), msg);

       }

}

Step 5: Now create “Cucumberrun.java” which defines cucumber-jvm configuration and put under package “com.projectname.cucumberrunner” of source folder” src/test/java”.

package com.projectname.cucumberrunner;

import cucumber.api.CucumberOptions;

import cucumber.api.testng.AbstractTestNGCucumberTests;

@CucumberOptions(features = “resources/googlesearch.feature”,

glue = “com.projectname.tests”, format = {

              “html:target/cucumber-html-report”,

              “json:target/cucumber-json-” + “report.json” })

public class Cucumberrun extends AbstractTestNGCucumberTests {

}

Step 6. Open command prompt and goto project directory and run command:

mvn install (or you can directly right click on “pom.xml” and run “Maven install”

Step 7: You should see test will execute and after execution report is generated under directory “\target\cucumber-html-report”. Open index.html file, report should be as below:

Capture

Enjoy your development……………

Inspect elements in Mobile Web application

     Web content behaves differently on mobile than on desktop. While automating mobile web application most of the time I have faced lots of problem in identifying the element locators to do the actions. Here we have the Chrome DevTools for inspect element of Mobile Web application in Android and Safari Web Inspector for inspect elements of Mobile Web application in iOS.

Inspect elements using Chrome DevTools

Requirements:

1. Chrome 32 or later installed on your development machine.

2. A USB cable to connect your Android device.

3. Android 4.0+ and Chrome for Android.

Steps:

1. Connect Android mobile device to PC (make sure that Android Debugging enabled in Android Developer Option in device).

2. Open chrome browser in Android mobile device.

3. Open below URL in Desktop chrome browser:

              chrome://inspect/#devices

You can see the connected device in Chrome Developer Tool page.

1

4. Enter the URL which you want to automate and inspect elements. URL must be entered in “Open tab with url” edit box, then tap on ‘open’ button and you can see that the specified URL gets open in Device browser.

5. Click on ‘inspect’ link and it will open another window to inspect the elements. Once it gets loaded you can start inspect elements and go ahead automation.

2

 

Inspect elements using Safari Web Inspector           

1. Open Safari on your iOS device.

2. Connect it to your computer via USB.

3. Open Safari on your computer.

4. In Safari’s menu, go to Develop and, look for your device’s name.

5. Select the tab you want to inspect.

 

 

How to write maintainable tests in Selenium or Appium or any automation scripting

testable-and-maintainable-code-in-php-400

 

     One of the biggest challenges with Selenium tests is that they can be brittle and challenging to maintain over time. This is largely due to the fact that things in the application you’re testing change — causing your tests to break.

     But the reality of a software project is that change is a constant. So we need to account for this reality somehow in our test code in order to be successful.

A Page Objects Primer

     Rather than write your test code directly against your app, you can model the behavior of your application into simple objects and write your tests against them instead. That way when your app changes and your tests break, you only have to update your test code in one place to fix it.

     With this approach, we not only get the benefit of controlled chaos, we also get reusable functionality across our suite of tests and more readable tests.

Step 1: Create A Page Object And Update Test

   First we’ll need to create a package called pageobjects in our src/tests/java directory. Then let’s add a file to the pageobjects package called Login.java. When we’re done our directory structure should look like this.

Capture

And here’s the code that goes with it.

Capture

     At the top of the file we specify the package where it lives and import the requisite classes from our libraries. We then declare the class (e.g., public class Login), specify our field variables (for the Selenium instance and the page’s locators), and add three methods.

  The first method (e.g., public Login(WebDriver driver)) is the constructor. It will run whenever a new instance of the class is created. In order for this class to work we need access to the Selenium driver object, so we accept it as a parameter here and store it in the driver field (so other methods can access it). Then the login page is visited (with driver.get).

     The second method (e.g., public void with(String username, String password)) is the core functionality of the login page. It’s responsible for filling in the login form and submitting it. By accepting strings parameters for the username and password we’re able to make the functionality here dynamic and reusable for additional tests.

     The last method (e.g., public Boolean successMessagePresent()) is the display check from earlier that was used in our assertion. It will return a Boolean result just like before.

Now let’s update our test to use this page object.

Capture

     Since the page object lives in another package, we need to import it (e.g.,import pageobjects.Login;).

       Then it’s a simple matter of specifying a field for it (e.g., private Login login), creating an instance of it in our setUp method (passing the driver object to it as an argument), and updating the test with the new actions.

      Now the test is more concise and readable. If you save this and run it (e.g.,mvn clean test from the command-line), it will run and pass just like before.

Step 2: Write Another Test

      Creating a page object may feel like more work than what we started with initially. But it’s well worth the effort since we’re in a much sturdier position (remember: controlled chaos) and able easily write follow-on tests (since the specifics of the page are abstracted away for simple reuse).

Let’s add another test for a failed login to demonstrate.

    First, let’s take a look at the markup that gets rendered when we provide invalid credentials:

Capture

Here is the element we’ll want to use.

class=”flash error”

     Let’s add a locator to our page object along with a new method to perform a display check against it.

Capture

Now we’re ready to add another test to check for a failure condition.

Capture

       If we save these changes and run our tests (mvn clean test) we will see two browser windows open (one after the other) testing for successful and failure login scenarios.

Why Asserting False Won’t Work (yet)

      You may be wondering why we didn’t just check to see if the success message wasn’t present in our assertion.

Capture

      There are two problems with this approach. First, our test will fail. This is because Selenium errors when looking for an element that’s not present on the page — which looks like this:

      Second, the absence of a success message doesn’t necessarily indicate a failed login. The assertion we ended up with is more concise.

Step 3: Confirm We’re In The Right Place

     Before we can call our page object finished, there’s one more addition we should make. We’ll want to add an assertion to make sure that Selenium is in the right place before proceeding. This will help add some resiliency to our test.

     As a rule, you want to keep assertions in your tests and out of your page objects. But this is the exception to the rule.

Capture

       After importing the assertion library we put it to use in our constructor (after the Selenium command that visits the login page). With it we’re checking to see that the login form is displayed. If it is, the tests using this page object will proceed. If not, the test will fail and provide an output message stating that the login form wasn’t present.

     With Page Objects you’ll be able to easily maintain and extend your tests. But how you write your Page Objects may vary depending on your preference/experience.

Reference: http://elementalselenium.com/