frontend testing tips

Testing multibrowser: Protractor e integrazione con Browserstack

Creare test funzionali con Protractor come trattato negli articoli precedenti va ben oltre i testing fatto durante il normale sviluppo, con poche modifiche ci permette far girare la nostra suite di test direttamente su Browserstack. In questa maniera avremo la possibilità di eseguire interi flussi applicativi  in multipiattaforma e garantendo quindi la funzionalità cross-browser della nostra applicazione.

Note

Questo articolo fa parte di una serie di pubblicazioni che ha come obiettivo conoscere ed approfondire con alcuni casi concreti riscontrati nello sviluppo quotidiano il testing funzionale di applicazioni Angular 2 eseguito tramite Protractor.

Repository di riferimento

Un esempio funzionante del progetto angular base su cui  girano i test di cui parleremo è reperibile presso: https://github.com/mzuccaroli/angular-cli-tests-example, si tratta di un semplice progetto angular2 generato con angular CLI col comando “ng new”. Per maggiori informazioni vedere il quickstart di un progetto angular2.

Browserstack

In questo articolo si darà per assodato l’utilizzo di Protractor e la presenza di una suite di test funzionali, per sapere di più come impostare un ambiente simile è possibile vedere questo articolo su come eseguire test funzionali con protractor e angular-cli, per un esempio concreto da cui partire si può vedere la repository di riferimento.

Browserstack

Un altro pre-requisto è l’accesso a un account browserstack con piano automate, si tratta di un servizio a pagamento ma, una volta configurato a dovere, ci permette di eseguire contemporaneamente su più browser e su più piattaforme i nostri test funzionali, risparmiando di fatto ore di scomodo testing “manuale”.

BrowserStack logo

BrowserStack è una piattaforma per il testing web e mobile basata su cloud che consente agli sviluppatori di testare siti web e applicazioni su browser, sistemi operativi e dispositivi mobili reali, senza richiedere agli utenti di installare o gestire internamente una serie di macchine virtuali, dispositivi ed emulatori.

Vale comunque il principio che le stesse metodologie possono essere applicate con altri tipi di server selenium che potremo gestire autonomamente, indubbiamente BrowserStack è la soluzione più “comoda”.

Come fare

L’idea è quella di creare una nuova configurazione di Protractor dedicata a browserstack da avviare all’occorrenza, vediamo come fare.

Partendo dalla configurazione base che ci fornisce angular-cli creiamo il nuovo file protractor.browserstack.conf.js

$ cp protractor.conf.js protractor.browserstack.conf.js

Aggiungiamo l’indirizzo del server selenium esposto da browserstack

'seleniumAddress': 'http://hub-cloud.browserstack.com/wd/hub',

Aggiungiamo ora le nuove sezioni “commoncapabilities” e “multicapabilities” dove potremo specificare le nostre credenziali browserstack e quali browser vogliamo utilizzare per i test

commonCapabilities: {
 'browserstack.user': 'xxxx', // TODO: insert user
 'browserstack.key': 'xxxx', // TODO: insert key
 'browserstack.local': true
},

'multiCapabilities': [
 {
  'browserName': 'Chrome'
 },
 {
  'browserName': 'Safari',
  'browser_version': '8'
 },
 {
  'browserName': 'Firefox',
  'browser_version': '50'
 },
 {
  'browserName': 'IE',
  'browser_version': '11.0'
 }
],

Per eseguire i test in parallelo sui vari browser e velocizzare il processo aggiungiamo in coda al file

exports.config.multiCapabilities.forEach(function(caps){
 for(var i in exports.config.commonCapabilities) caps[i] = caps[i] || exports.config.commonCapabilities[i];
});

A questo punto sarà sufficiente eseguire protractor con il seguente comando

$ ./node_modules/.bin/protractor protractor.browserstack.conf.js

Potremo vedere i risultati dei test a console ma potremo anche (a seconda delle configurazione del nostro account browserstack) visualizzare risultati e registrazioni filmate dei nostri test all’indirizzo: https://automate.browserstack.com/

Testing su server privati

Spesso ci capiterà che l’applicazione che vogliamo testare non sia raggiungibile dalla rete pubblica, è una situazione comune per ambienti di staging o per applicazioni che girano su reti private. Browserstack-local ci viene incontro in questa evenienza permettendoci di eseguire local binding dalla nostra macchina di sviluppo.

Installiamo blowserstack-local

npm install browserstack-local

Poi adattiamo la nostra configurazione importandolo e aggiungendo le chiamate beforeLaunch e afterLaunch

var browserstack = require('browserstack-local');
// Code to start browserstack local before start of test
beforeLaunch: function(){
 console.log("Connecting local");
 return new Promise(function(resolve, reject){
  exports.bs_local = new browserstack.Local();
  exports.bs_local.start({'key': exports.config.capabilities['browserstack.key'] }, function(error) {
   if (error) return reject(error);
   console.log('Connected. Now testing...');

   resolve();
  });
 });
},

// Code to stop browserstack local after end of test
afterLaunch: function(){
 return new Promise(function(resolve, reject){
  exports.bs_local.stop(resolve);
 });
}

è importante ricordarsi di abilitarlo all’interno delle commoncapabilities

'browserstack.local': true,

a questo punto potremo lanciare senza problemi test su server privati con tutti i benefici che ci può fornire browserstack.

Da notare che l’utilizzo di browserstack locale rallenta un po l’esecuzione dei test, è molto probabile che ci troveremo a dover ritoccare un po i timeout, sia di protractor che di browserstack, per evitare che i nostri test falliscano, soprattutto quelli che girano su Internet Explorer.

un esempio completo di quanto trattato è reperibile sulla nostra repository di riferimento: protractor.browserstack.conf.js.

Il risultato finale sarà un file simile al seguente:

const {SpecReporter} = require('jasmine-spec-reporter');
var browserstack = require('browserstack-local');

exports.config = {
    allScriptsTimeout: 50000,
    specs: [
        './e2e/**/*.e2e-spec.ts'
    ],

    'seleniumAddress': 'http://hub-cloud.browserstack.com/wd/hub',

    commonCapabilities: {
        'browserstack.user': 'xxxx', // TODO: insert user
        'browserstack.key': 'xxxx', // TODO: insert key
        'browserstack.local': true
    },

    'multiCapabilities': [{
        'browserName': 'Chrome'
    }, {
        'browserName': 'Safari',
        'browser_version': '8'
    }, {
        'browserName': 'Firefox',
        'browser_version': '50'
    }, {
        'browserName': 'IE',
        'browser_version': '11.0'
    }],

    baseUrl: 'http://www.testpage.demo/',
    framework: 'jasmine',
    jasmineNodeOpts: {
        showColors: true,
        defaultTimeoutInterval: 50000,
        print: function () {
        }
    },
    onPrepare() {
        require('ts-node').register({
            project: 'e2e/tsconfig.e2e.json'
        });
        jasmine.getEnv().addReporter(new SpecReporter({spec: {displayStacktrace: true}}));
    },

    // Code to start browserstack local before start of test 
    beforeLaunch: function () {

        console.log("Connecting local");
        return new Promise(function (resolve, reject) {
            exports.bs_local = new browserstack.Local();
            exports.bs_local.start({'key': exports.config.capabilities['browserstack.key']}, function (error) {
                if (error) return reject(error);
                console.log('Connected. Now testing...');

                resolve();
            });
        });
    },

    // Code to stop browserstack local after end of test
    afterLaunch: function () {
        return new Promise(function (resolve, reject) {
            exports.bs_local.stop(resolve);
        });
    }
};

// Code to support common capabilities
exports.config.multiCapabilities.forEach(function (caps) {
    for (var i in exports.config.commonCapabilities) caps[i] = caps[i] || exports.config.commonCapabilities[i];
});
0 commenti

Lascia un Commento

Vuoi partecipare alla discussione?
Fornisci il tuo contributo!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *