Archive

Archive for May, 2017

Cucumber report with protractor tests

Hi guys, today I will show what you can do with the module cucumber-html-report that I am currently using in my protractor automated tests.

So, it is a node library that reads the Json reports and convert them into a nice html report. It should show the coverage of your scenarios and if you want you can have pictures attached as well.
I am pasting here some snippets that you guys can use and customise as you want.
To install you need to add the cucumber-html-report in your dependencies like:
{
    "name": "Rafazzevedo",
    "version": "1.0.0",
    "description": "Rafazzevedo",
    "private": true,
    "dependencies": {
        "cucumber-html-reporter": "^0.4.0",
        "protractor": "^5.1.1"
    },

    "devDependencies": {
        "chai": "^3.5.0",
        "chai-as-promised": "^6.0.0",
        "chai-string": "^1.3.0",
        "cucumber": "^1.3.2",
        "protractor-cucumber-framework": "^1.0.2"
    }
}
Then you create an After in your Hooks class and Add the creation of the report:
import { browser } from 'protractor';
import reporter from 'cucumber-html-reporter';
import _ from 'lodash';
import Navigation from './helpers/navigation';

const API = automation.API;

const Hooks = function () {
    const api = new API(browser.params);
    const navigation = new Navigation(browser);
    const credentials = browser.params.credentials;

    this.registerHandler('BeforeFeatures', () => {
        api.authenticate(credentials);
        browser.api = api;
        browser.navigation = navigation;
        browser.get(browser.baseUrl);
    });
    this.registerHandler('AfterFeatures', () => {
        browser.getProcessedConfig().then((config) => {
            const jsonFile = config.capabilities.cucumberReportPath;
            browser.getCapabilities().then((capabilities) => {
                const reportName = createReportName
(config.capabilities, capabilities);
                const htmlFile = jsonFile.replace('.json', '.html');
                const options = {
                    name: `Automation (${reportName})`,
                    theme: 'bootstrap',
                    jsonFile,
                    output: htmlFile,
                    reportSuiteAsScenarios: true,
                };
                reporter.generate(options);
            });
        });
    });
    function createReportName(configCapabilities, browserCapabilities) {
        const browserName = configCapabilities.browserName;
        let deviceName = 'desktop';
        let browserVersion = '';
        if (!_.isUndefined(configCapabilities.chromeOptions)) {
            browserVersion = ` ${browserCapabilities.get('version')}`;
            if (!_.isUndefined(
configCapabilities.chromeOptions.mobileEmulation)) {
                deviceName = configCapabilities.chromeOptions.
mobileEmulation.deviceName;
            }
        }
        return `${browserName} ${deviceName}${browserVersion}`;
    }
};

module.exports = Hooks;
After adding these 2 functions about creating the report for multiple browsers and adding the version and the device name (desktop or mobile) in the report, you can add pictures in case of the scenario fails:
this.After((scenario) => {
        if (scenario.isFailed()) return browser.takeScreenshot().
then(screenshot => scenario.attach(new 
Buffer (screenshot, 'base64'), 'image/png'));
    });
 
You can always customise and improve the functions, if you feel that you need a picture after all the scenarios even they passed, you can just remove the condition in the after. Also you have different available themes and other options on https://www.npmjs.com/package/cucumber-html-reporter
See you guys !

Avoiding false positives with Protractor and Javascript

Do you have false positives when automating with protractor ?

Asynchronous code can be really annoying sometimes, callback pyramids, error handling on every second line, promises swallowing errors by default…

When using ES6 promises any exception which is thrown within a then or a catch handler, will be silently disposed of unless manually handled.

If you are not getting the errors, you are probably coding the promise something like this:

Promise.resolve('promised value').then(function() {
 throw new Error('error'); 
});

Then the more obvious way  to print the error is adding a catch after the promise:

Promise.resolve('promised value').then(function() {
 throw new Error('error'); 
}).catch(function(error) {
 console.error(error.stack); 
});

Remember that you need to add this after all the promises you want to print the error. Do you really think this is reliable ? Are you going to repeat yourself adding a catch after all the promises ?

So, how can you print the error without need to repeat yourself when creating a promise ? You can use .done instead of .then. This will run the promise and after print the error that you want.

Here is how you can avoid them:

Promise.resolve('promised value').done(function() {
 throw new Error('error');
 });

But what do you do when you chain multiple thens ?

There is a library called Bluebird which has a fix integrating your existing code by extending the ES6 Promises API. You can make sure you know about unhandled rejections, so no more false positives.

Promise.onPossiblyUnhandledRejection(function(error){
 throw error; 
});

Then if you want to discard an exception not because it is been swallowed, but you don’t need to print it, you can do something like this:

Promise.reject('error value').catch(function() {
});

 

Bad practices when writing your BDD scenarios

I usually write about the best practices to follow when writing your BDD scenarios. This time I will do different and write some examples that I found of how to not write your BDD scenarios.

 Example 1 – Too many steps :

  Scenario: Valid data entered
    Given a user exists
    When I visit the details access page
    And I fill in email with "test@email.com"
    And I select "read only" from "Permissions"
    And I fill in "Valid until" with "2010-03-01"
    And I press "Grant access"
    Then I should see "Access granted till 2010-03-01."
    And I should be on the details page

 

 Example 2  – UI elements dependency:

   Scenario: Adding a picture 
     Given I go to the Home page 
     When I click the Add picture button 
     And I click on the drop down "Gallery"
     And I click on the first image
     Then I should see the image added on the home page

 

 Example 3 – Excessive use of tables :

   Scenario: Adding a new data user 
     Given I am on  user details page
     When I select an existent user
     And I send some new user data
     |name |age|country|language|address |telephone|
     |James|20 |england|english |street 1|123456789|
     |Chris|30 |spain  |spanish |street 2|987654321|
     Then I should see the correct previous registered data
     |gender  |married|smoke|
     |male    |true   |true |
     |male    |false  |false|

 

 Example 4  – Code and data structure:

   Scenario: Include attachment
     Given I go to the Attachments page 
     When I click the Add attachment button with css "#attachment-button"
     And I click on the first csv file with class ".file .csv"
     Then I should see the file attached with the id ".attachment"

 

  • Write declarative scenarios.
  • Write at a higher level of abstraction, instead of being concerned with clicking widgets on a page. Surfacing UI concerns on a feature can make it fragile to ordinary design changes.
  • Try to stick to having not more than 5 steps per scenario. It’s easier to read.
  • Avoid code or data structure like xpath selectors, css class, regex in your scenario.

 

%d bloggers like this: