Tuesday, 31 May 2016

BDD (behavior-driven development)Framework : Jasmine Basics


Jasmine is a behavior-driven development framework for testing JavaScript code. It does not depend on any other JavaScript frameworks

1.    Suites:
describe Your Tests
A test suite begins with a call to the global Jasmine function describe with two parameters: a string and a function. The string is a name or title for a spec suite – usually what is being tested. The function is a block of code that implements the suite.

describe("A suite", function() {
  it("contains spec with an expectation", function() {
    expect(true).toBe(true);
  });
});

Specs:
A spec contains one or more expectations that test the state of the code. An expectation in Jasmine is an assertion that is either true or false. A spec with all true expectations is a passing spec. A spec with one or more false expectations is a failing spec.
Since describe and it blocks are functions, they can contain any executable code necessary to implement the test. JavaScript scoping rules apply, so variables declared in a describe are available to any it block inside the suite.

2.       Expectations:
Expectations are built with the function expect which takes a value, called the actual. It is chained with a Matcher function, which takes the expected value.
Matchers:
Each matcher implements a boolean comparison between the actual value and the expected value. It is responsible for reporting to Jasmine if the expectation is true or false. Jasmine will then pass or fail the spec.
  it("and has a positive case", function() {
    expect(true).toBe(true);
 });

Any matcher can evaluate to a negative assertion by chaining the call to expect with a not before calling the matcher.
it("and can have a negative case", function() {
    expect(false).not.toBe(true);
  });
});

it("works for simple literals and variables", function() {
      var a = 12;
      expect(a).toEqual(12);
    });

it("should work for objects", function() {
      var foo = {
        a: 12,
        b: 34
      };
      var bar = {
        a: 12,
        b: 34
      };
      expect(foo).toEqual(bar);
    });
  });

  it("The 'toMatch' matcher is for regular expressions", function() {
    var message = "foo bar baz";

    expect(message).toMatch(/bar/);
    expect(message).toMatch("bar");
    expect(message).not.toMatch(/quux/);
  });

  it("The 'toBeDefined' matcher compares against `undefined`", function() {
    var a = {
      foo: "foo"
    };

    expect(a.foo).toBeDefined();
    expect(a.bar).not.toBeDefined();
  });

  it("The `toBeUndefined` matcher compares against `undefined`", function() {
    var a = {
      foo: "foo"
    };

    expect(a.foo).not.toBeUndefined();
    expect(a.bar).toBeUndefined();
  });

  it("The 'toBeNull' matcher compares against null", function() {
    var a = null;
    var foo = "foo";

    expect(null).toBeNull();
    expect(a).toBeNull();
    expect(foo).not.toBeNull();
  });

  it("The 'toBeTruthy' matcher is for boolean casting testing", function() {
    var a, foo = "foo";

    expect(foo).toBeTruthy();
    expect(a).not.toBeTruthy();
  });

  it("The 'toBeFalsy' matcher is for boolean casting testing", function() {
    var a, foo = "foo";

    expect(a).toBeFalsy();
    expect(foo).not.toBeFalsy();
  });

  it("The 'toContain' matcher is for finding an item in an Array", function() {
    var a = ["foo", "bar", "baz"];

    expect(a).toContain("bar");
    expect(a).not.toContain("quux");
  });

  it("The 'toBeLessThan' matcher is for mathematical comparisons", function() {
    var pi = 3.1415926,
      e = 2.78;

    expect(e).toBeLessThan(pi);
    expect(pi).not.toBeLessThan(e);
  });

  it("The 'toBeGreaterThan' matcher is for mathematical comparisons", function() {
    var pi = 3.1415926,
      e = 2.78;

    expect(pi).toBeGreaterThan(e);
    expect(e).not.toBeGreaterThan(pi);
  });

  it("The 'toBeCloseTo' matcher is for precision math comparison", function() {
    var pi = 3.1415926,
      e = 2.78;

    expect(pi).not.toBeCloseTo(e, 2);
    expect(pi).toBeCloseTo(e, 0);
  });

  it("The 'toThrow' matcher is for testing if a function throws an exception", function() {
    var foo = function() {
      return 1 + 2;
    };
    var bar = function() {
      return a + 1;
    };

    expect(foo).not.toThrow();
    expect(bar).toThrow();
  });

  it("The 'toThrowError' matcher is for testing a specific thrown exception", function() {
    var foo = function() {
      throw new TypeError("foo bar baz");
    };

    expect(foo).toThrowError("foo bar baz");
    expect(foo).toThrowError(/bar/);
    expect(foo).toThrowError(TypeError);
    expect(foo).toThrowError(TypeError, "foo bar baz");
  });
});


3.       Manually failing a spec with fail:
The fail function causes a spec to fail. It can take a failure message or an Error object as a parameter.
escribe("A spec using the fail function", function() {
  var foo = function(x, callBack) {
    if (x) {
      callBack();
    }
  };

  it("should not call the callBack", function() {
    foo(false, function() {
      fail("Callback has been called");
    });
  });
});

4.       Grouping Related Specs with describe: ( more about naming convenction)

The describe function is for grouping related specs. The string parameter is for naming the collection of specs, and will be concatenated with specs to make a spec’s full name. This aids in finding specs in a large suite. If you name them well, your specs read as full sentences in traditional BDD style.

describe("A spec", function() {
  it("is just a function, so it can contain any code", function() {
    var foo = 0;
    foo += 1;
    expect(foo).toEqual(1);
  });

  it("can have more than one expectation", function() {
    var foo = 0;
    foo += 1;
    expect(foo).toEqual(1);
    expect(true).toEqual(true);
  });
});

5.       Setup and Teardown: (beforeeach ,aftereach, beforeall, afterall)
To help a test suite DRY up any duplicated setup and teardown code, Jasmine provides the global beforeEach, afterEach, beforeAll, and afterAll functions.

As the name implies, the beforeEach function is called once before each spec in the describe in which it is called, and the afterEach function is called once after each spec.

Here is the same set of specs written a little differently. The variable under test is defined at the top-level scope — the describe block — and initialization code is moved into a beforeEach function. The afterEach function resets the variable before continuing.

describe("A spec using beforeEach and afterEach", function() {
  var foo = 0;
  beforeEach(function() {
    foo += 1;
  });

  afterEach(function() {
    foo = 0;
  });

  it("is just a function, so it can contain any code", function() {
    expect(foo).toEqual(1);
  });

  it("can have more than one expectation", function() {
    expect(foo).toEqual(1);
    expect(true).toEqual(true);
  });
});

The beforeAll function is called only once before all the specs in describe are run, and the afterAll function is called after all specs finish. These functions can be used to speed up test suites with expensive setup and teardown.

However, be careful using beforeAll and afterAll! Since they are not reset between specs, it is easy to accidentally leak state between your specs so that they erroneously pass or fail.

describe("A spec using beforeAll and afterAll", function() {
  var foo;

  beforeAll(function() {
    foo = 1;
  });

  afterAll(function() {
    foo = 0;
  });

  it("sets the initial value of foo before specs run", function() {
    expect(foo).toEqual(1);
    foo += 1;
  });

  it("does not reset foo between specs", function() {
    expect(foo).toEqual(2);
  });
});

6.       The this keyword:

Another way to share variables between a beforeEach, it, and afterEach is through the this keyword. Each spec’s beforeEach/it/afterEach has the this as the same empty object that is set back to empty for the next spec’s beforeEach/it/afterEach.

describe("A spec", function() {
  beforeEach(function() {
    this.foo = 0;
  });

  it("can use the `this` to share state", function() {
    expect(this.foo).toEqual(0);
    this.bar = "test pollution?";
  });

  it("prevents test pollution by having an empty `this` created for the next spec", function() {
    expect(this.foo).toEqual(0);
    expect(this.bar).toBe(undefined);
  });
});

7   .       Nesting describe Blocks

Calls to describe can be nested, with specs defined at any level. This allows a suite to be composed as a tree of functions. Before a spec is executed, Jasmine walks down the tree executing each beforeEach function in order. After the spec is executed, Jasmine walks through the afterEach functions similarly.

describe("A spec", function() {
  var foo;

  beforeEach(function() {
    foo = 0;
    foo += 1;
  });

  afterEach(function() {
    foo = 0;
  });

  it("is just a function, so it can contain any code", function() {
    expect(foo).toEqual(1);
  });

  it("can have more than one expectation", function() {
    expect(foo).toEqual(1);
    expect(true).toEqual(true);
  });

  describe("nested inside a second describe", function() {
    var bar;

    beforeEach(function() {
      bar = 1;
    });

    it("can reference both scopes as needed", function() {
      expect(foo).toEqual(bar);
    });
  });
});
                             
                    


8. Disabling Suites:
Suites can be disabled with the xdescribe function. These suites and any specs inside them are skipped when run and thus their results will not appear in the results.
xdescribe("A spec", function() {
  var foo;
  beforeEach(function() {
    foo = 0;
    foo += 1;
  });
  it("is just a function, so it can contain any code", function() {
    expect(foo).toEqual(1);
  });
});

9. Pending Specs
Pending specs do not run, but their names will show up in the results as pending.
describe("Pending specs", function() {
Any spec declared with xit is marked as pending.
  xit("can be declared 'xit'", function() {
    expect(true).toBe(false);
  });
Any spec declared without a function body will also be marked pending in results.
  it("can be declared with 'it' but without a function");
And if you call the function pending anywhere in the spec body, no matter the expectations, the spec will be marked pending. A string passed to pending will be treated as a reason and displayed when the suite finishes.
  it("can be declared by calling 'pending' in the spec body", function() {
    expect(true).toBe(false);
    pending('this is why it is pending');
  });
});
10. Matching Anything with jasmine.any

jasmine.any takes a constructor or “class” name as an expected value. It returns true if the constructor matches the constructor of the actual value.

describe("jasmine.any", function() {
  it("matches any value", function() {
    expect({}).toEqual(jasmine.any(Object));
    expect(12).toEqual(jasmine.any(Number));
  });

  describe("when used with a spy", function() {
    it("is useful for comparing arguments", function() {
      var foo = jasmine.createSpy('foo');
      foo(12, function() {
        return true;
      });

      expect(foo).toHaveBeenCalledWith(jasmine.any(Number), jasmine.any(Function));
    });
  });
});

11.Matching existence with jasmine.anything

jasmine.anything returns true if the actual value is not null or undefined.

describe("jasmine.anything", function() {
  it("matches anything", function() {
    expect(1).toEqual(jasmine.anything());
  });

  describe("when used with a spy", function() {
    it("is useful when the argument can be ignored", function() {
      var foo = jasmine.createSpy('foo');
      foo(12, function() {
        return false;
      });

      expect(foo).toHaveBeenCalledWith(12, jasmine.anything());
    });
  });
});

12.Partial Matching with jasmine.objectContaining

jasmine.objectContaining is for those times when an expectation only cares about certain key/value pairs in the actual.

describe("jasmine.objectContaining", function() {
  var foo;

  beforeEach(function() {
    foo = {
      a: 1,
      b: 2,
      bar: "baz"
    };
  });

  it("matches objects with the expect key/value pairs", function() {
    expect(foo).toEqual(jasmine.objectContaining({
      bar: "baz"
    }));
    expect(foo).not.toEqual(jasmine.objectContaining({
      c: 37
    }));
  });

  describe("when used with a spy", function() {
    it("is useful for comparing arguments", function() {
      var callback = jasmine.createSpy('callback');

      callback({
        bar: "baz"
      });

      expect(callback).toHaveBeenCalledWith(jasmine.objectContaining({
        bar: "baz"
      }));
      expect(callback).not.toHaveBeenCalledWith(jasmine.objectContaining({
        c: 37
      }));
    });
  });
});

13.Partial Array Matching with jasmine.arrayContaining

jasmine.arrayContaining is for those times when an expectation only cares about some of the values in an array.

describe("jasmine.arrayContaining", function() {
  var foo;

  beforeEach(function() {
    foo = [1, 2, 3, 4];
  });

  it("matches arrays with some of the values", function() {
    expect(foo).toEqual(jasmine.arrayContaining([3, 1]));
    expect(foo).not.toEqual(jasmine.arrayContaining([6]));
  });

  describe("when used with a spy", function() {
    it("is useful when comparing arguments", function() {
      var callback = jasmine.createSpy('callback');

      callback([1, 2, 3, 4]);

      expect(callback).toHaveBeenCalledWith(jasmine.arrayContaining([4, 2, 3]));
      expect(callback).not.toHaveBeenCalledWith(jasmine.arrayContaining([5, 2]));
    });
  });
});
14.String Matching with jasmine.stringMatching

jasmine.stringMatching is for when you don’t want to match a string in a larger object exactly, or match a portion of a string in a spy expectation.

describe('jasmine.stringMatching', function() {
  it("matches as a regexp", function() {
    expect({foo: 'bar'}).toEqual({foo: jasmine.stringMatching(/^bar$/)});
    expect({foo: 'foobarbaz'}).toEqual({foo: jasmine.stringMatching('bar')});
  });

  describe("when used with a spy", function() {
    it("is useful for comparing arguments", function() {
      var callback = jasmine.createSpy('callback');

      callback('foobarbaz');

      expect(callback).toHaveBeenCalledWith(jasmine.stringMatching('bar'));
      expect(callback).not.toHaveBeenCalledWith(jasmine.stringMatching(/^bar$/));
    });
  });
});

15. Asynchronous Support

This syntax has changed for Jasmine 2.0. Jasmine also has support for running specs that require testing asynchronous operations.

describe("Asynchronous specs", function() {
  var value;

Calls to beforeAll, afterAll, beforeEach, afterEach, and it can take an optional single argument that should be called when the async work is complete.

  beforeEach(function(done) {
    setTimeout(function() {
      value = 0;
      done();
    }, 1);
  });

This spec will not start until the done function is called in the call to beforeEach above. And this spec will not complete until its done is called.

  it("should support async execution of test preparation and expectations", function(done) {
    value++;
    expect(value).toBeGreaterThan(0);
    done();
  });

By default jasmine will wait for 5 seconds for an asynchronous spec to finish before causing a timeout failure. If the timeout expires before done is called, the current spec will be marked as failed and suite execution will continue as if done was called.

If specific specs should fail faster or need more time this can be adjusted by passing a timeout value to it, etc.

If the entire suite should have a different timeout, jasmine.DEFAULT_TIMEOUT_INTERVAL can be set globally, outside of any given describe.

  describe("long asynchronous specs", function() {
    beforeEach(function(done) {
      done();
    }, 1000);

    it("takes a long time", function(done) {
      setTimeout(function() {
        done();
      }, 9000);
    }, 10000);

    afterEach(function(done) {
      done();
    }, 1000);
  });

The done.fail function fails the spec and indicates that it has completed.

  describe("A spec using done.fail", function() {
    var foo = function(x, callBack1, callBack2) {
      if (x) {
        setTimeout(callBack1, 0);
      } else {
        setTimeout(callBack2, 0);
      }
    };

    it("should not call the second callBack", function(done) {
      foo(true,
        done,
        function() {
          done.fail("Second callback has been called");
        }
      );
    });
  });

});

How Proctractor works


Protractor works in conjunction with Selenium to provide an automated test infrastructure that can simulate a user’s interaction with an Angular application running in a browser or mobile device.

Protractor is a wrapper around WebDriverJS, the JavaScript bindings for the Selenium WebDriver API




Process Communication:

A test using Selenium WebDriver involves three processes - the test script, the server, and the browser. The communication between these processes is shown in the diagram below.

The Selenium Server takes care of interpreting commands from the test and forwarding them to one or more browsers. Communication between the server and the browser uses the WebDriver Wire Protocol, a JSON protocol. The command is interpreted by the Browser Driver.
With Protractor, the test script is run using Node.js. Protractor runs an extra command before performing any action on the browser to ensure that the application being tested has stabilized. For example, let's look at the following snippet of test code.

element(by.css('button.myclass')).click();

This will result in three commands being sent to the Browser Driver


Quick Idea about protractor

Protractor, formally known as E2E testing framework, is an open source functional automation framework designed specifically for AngularJS web applications. It was introduced during AngularJS 1.2 as a replacement of the existing E2E testing framework. The Protractor automation tool is also recommended by AngularJS for scenario testing. 
Salient features of the Protractor Automation tool:
  1. Built on the top of WebdriverJS and Selenium server
  2. Introduced new simple syntax to write tests
  3. Allows running tests targeting remote addresses
  4. Can take advantage of Selenium grid to run multiple browsers at once
  5. Can use Jasmine or Mocha to write test suites
Protractor is a wrapper (built on the top) around Selenium WebDriver, so it contains every feature that is available in the Selenium WebDriver. Additionally, Protractor provides some new locator strategies and functions which are very helpful to automate the AngularJS application. Examples include things like: waitForAngular, By.binding, By.repeater, By.textarea, By.model, WebElement.all, WebElement.evaluate, etc.
AngularJS team added accessors to angular models, bindings, ng-options – and finding elements inside ng-repeat. These additions make querying for elements much easier.
For example – let’s get all the ages of the cats that the repeater 
<div ng-repeat="cat in pets">
<span>{{cat.name}}</span>
<span>{{cat.age}}</span>
</div>
 var ages = element.all( by.repeater('cat in pets').column('{{cat.age}}'));


setting up protractor

Download and install NodeJS. http://nodejs.org/download/.
To verify your installation, please type in the command

npm –version                          

Install Protractor Globally:

Open the command prompt and type in the following command to install protractor globally. (Using npm)
This will install two command line tools, protractor and webdriver-manager.

npm install -g protractor

To verify your installation, please type in the command

Protractor   --version

If Protractor is installed successfully then the system will display the installed version. Otherwise you will have to recheck the installation.

Grid Setup:

The webdriver-manager is a helper tool to easily get an instance of a Selenium Server running. Use it to download the necessary binaries with:

webdriver-manager update

Now start up a server with:

webdriver-manager start

This will start up a Selenium Server and will output a bunch of info logs. Your Protractor test will send requests to this server to control a local browser. You can see information about the status of the server at http://localhost:4444/wd/hub.

Write a Simple Test: ( save as FirstSpec.js)

describe('angularjs homepage todo list', function() {
  it('should add a todo', function() {
    browser.get('https://angularjs.org');

    element(by.model('todoList.todoText')).sendKeys('write first protractor test');
    element(by.css('[value="add"]')).click();

    var todoList = element.all(by.repeater('todo in todoList.todos'));
    expect(todoList.count()).toEqual(3);
    expect(todoList.get(2).getText()).toEqual('write first protractor test');

    // You wrote your first test, cross it off the list
    todoList.get(2).element(by.css('input')).click();
    var completedAmount = element.all(by.css('.done-true'));
    expect(completedAmount.count()).toEqual(2);
  });
});

Configuration ( save as conf.js)

exports.config = {
  seleniumAddress: 'http://localhost:4444/wd/hub',
  specs: ['FirstSpec.js']
};

To Run The Test:
Run>protractor conf.js




That’s all.





Can we use Selenium WebDriver to Automate AngulatJS Applications?

    YES.

     Selenium Interacts with Web Elements ( I.e. HTML content ) to perform Actions.
     So, underlying technology is not a constraint for selenium. It works as expected.

     Then Why Protractor?
     Let’s look at a simple AngulerJS application view souce.

<!DOCTYPE HTML>
<html ng-app="calculator">
<head>
<script src="./calc.js"></script>
<link href="./bootstrap.css" rel="stylesheet">
<title>Super Calculator</title>
</head>
<body class="ng-cloak">
<div ng-controller="CalcCtrl" class="container">
<div>
<h3>Super Calculator</h3>
<form class="form-inline">
<input ng-model="first" type="text" class="input-small"/>
<select ng-model="operator" class="span1"
ng-options="value for (key, value) in operators">
</select>
<input ng-model="second" type="text" class="input-small"/>
<button ng-click="doAddition()" id="gobutton" class="btn">Go!</button>
<h2>{{latest}}</h2>
</form>
</div>
<h4>History</h4>
<table class="table">
<thead><tr>
<th>Time</th>
<th>Expression</th>
<th>Result</th>
</tr></thead>
<tr ng-repeat="result in memory">
<td>
{{result.timestamp | date:'mediumTime'}}
</td>
<td>
<span>{{result.first}}</span>
<span>{{result.operator}}</span>
<span>{{result.second}}</span>
</td>
<td>{{result.value}}</td>
</tr>
</table>
</div>
</body>
</html>

Were you able to see any known Attributes in any Tags to locate an element using By class methods?
I.e ID, NAME etc.

NO rite?

Were you able to see anything new in this code?

Attributes:
ng-controller
ng-model
ng-options
ng-repeat

Can we perform required Actions on the elements which contains above attributes?
Yes, But Could be quite difficult way to achieve required actions.

Again, Why these new attributes? Who brought in?
AngulerJS development team, so there is no escape.

So, will be happy if I give you easier way to locate elements and perform Actions on top of it.
Yes. 

Eg:
         1.       element.all( by.repeater('result in memory').column('{{ result.operator }}'));
         2.       element(by.css('some-css'));
         3.       element(by.model('item.name'));
         4.       element(by.binding('item.name')); 


Salient features of the Protractor Automation tool:

1. Built on the top of WebdriverJS and Selenium server
2. Introduced new simple syntax to write tests
3. Allows running tests targeting remote addresses
4. Can take advantage of Selenium grid to run multiple browsers at once
5. Can use Jasmine or Mocha to write test suites










Monday, 30 May 2016

How a Selenium Event Works?

WebDriver introduces a JSON wire protocol for various language bindings to communicate with the browser controller.
For example, to click an element in the browser, the binding will send POST request on/session/:sessionId/element/:id/click
So, at one end there is the language binding and a server, known as Selenium server, on the other. Both communicate using the JSON wire protocol.

Wednesday, 11 May 2016

How PageFactory DP is different from Page Object Model

Assume you are already aware of Page Object Design pattern.

Quick Recap:
 Each web page in the application there should be corresponding page class.
- Object Repository is independent of test cases.
- Flows in the UI should be separated from verification.

Advantages:
- Easy to Maintain
- Easy Readability of scripts
- Reduce or Eliminate duplicacy
- Re-usability of code

- Reliability


Page Factory :

- Extension to Page Object Model , but Page Factory is much enhanced model.


"Factory class can be used to make using Page Objects simpler and easier".

- We use Page Factory pattern to initialize web elements which are defined in Page Objects.
  Once we call initElements() method, all elements will get initialized.
- It is used to initialize elements of a Page class without having to use ‘FindElement’ or ‘FindElements’. Annotations can be used to supply descriptive names of target objects to improve code readability.

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.support.PageFactory;

import com.abof.selenium_pagefactory.pom.utils.WebElementWait;

public class HeaderPage {
WebDriver driver;

@FindBy(how = How.LINK_TEXT, using = "Track my order")
private WebElement linkTrackMyOrder;

@FindBy(how = How.ID, using = "Header_GlobalLogin_signInQuickLink")
private WebElement linkSignIn;

@FindBy(how = How.ID, using = "Header_GlobalLogin_signOutQuickLinkUser")
private WebElement linkSignOut;

@FindBy(how = How.ID, using = "Header_GlobalLogin_loggedInDropdown_SignOut")
private WebElement btnSignOut;

public HeaderPage(WebDriver driver) throws Exception {
this.driver = driver;
PageFactory.initElements(driver, this);
}

public void navigateToSignInPage() {
linkSignIn.click();
}

public void signOut() {
linkSignOut.click();
btnSignOut.click();
}

public void navigateToTrackingOrderPage() {
linkTrackMyOrder.click();
}

public String getMeLoggedInPersonFirstName() {
WebElementWait.elementIsDisplayedFluentlyPredicate(linkSignOut, 5, 500);
return linkSignOut.getText();
}


}


PageFactory Instantiates all the elements of the web page at the start when we Initialized any page class objects. But think of the elements which will display on the web page after some action, say Ajax action. In PageFactory, every time when we call a method on the WebElement, the driver will go and find it on the current page once again.

In an AJAX-heavy application this is what we would like to happen, but in the case of regular application where elements are stable and when we know that the element is always going to be there and won’t change.  It would be handy if we could ‘cache’ the element once we’d looked it up and save some time of execution by commanding PageFactory to not search the WebElements on the page again.

Advantages of PageFactory
- less code using @FindBy
- Initialize all elements at a time
- using cache feature, we can save execution time
AjaxElementLocatorFactory feature