bytes.cat

La wiki d'FP d'informàtica

Eines de l'usuari

Eines del lloc


Barra lateral

ASIX Administració de Sistemes Informàtics i Xarxes
Tots els mòduls del cicle
MP01 Implantació de sistemes operatius
Totes les UFs del modul
MP02 Gestió de bases de dades
Totes les UFs del modul
MP03 Programació bàsica
Totes les UFs del modul
MP04 Llenguatges de marques i sistemes de gestió d'informació
Totes les UFs del modul
MP05 Fonaments de maquinari
Totes les UFs del modul
MP06 Administració de sistemes operatius
Totes les UFs del modul
MP07 Planificació i administració de xarxes
Totes les UFs del modul
MP08 Serveis de xarxa i Internet
Totes les UFs del modul
MP09 Implantació d'aplicacions web
Totes les UFs del modul
MP10 Administració de sistemes gestors de bases de dades
Totes les UFs del modul
MP11 Seguretat i alta disponibilitat
Totes les UFs del modul
MP12 Formació i orientació laboral
Totes les UFs del modul
MP13 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP14 Projecte
Totes les UFs del modul
DAM Desenvolupament d’aplicacions multiplataforma
Tots els mòduls del cicle
MP01 Sistemes informàtics
Totes les UFs del modul
MP02 Bases de dades
Totes les UFs del modul
MP03 Programació bàsica
Totes les UFs del modul
MP04 Llenguatges de marques i sistemes de gestió d'informació
Totes les UFs del modul
MP05 Entorns de desenvolupament
Totes les UFs del modul
MP06 Accés a dades
Totes les UFs del modul
MP07 Desenvolupament d’interfícies
Totes les UFs del modul
MP08 Programació multimèdia i dispositius mòbils
Totes les UFs del modul
MP09 Programació de serveis i processos
Totes les UFs del modul
MP10 Sistemes de gestió empresarial
Totes les UFs del modul
MP11 Formació i orientació laboral
Totes les UFs del modul
MP12 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP13 Projecte de síntesi
Totes les UFs del modul
MPDual Mòdul Dual / Projecte
DAW Desenvolupament d’aplicacions web
Tots els mòduls del cicle
MP01 Sistemes informàtics
Totes les UFs del modul
MP02 Bases de dades
Totes les UFs del modul
MP03 Programació
Totes les UFs del modul
MP04 Llenguatge de marques i sistemes de gestió d’informació
Totes les UFs del modul
MP05 Entorns de desenvolupament
Totes les UFs del modul
MP06 Desenvolupament web en entorn client
Totes les UFs del modul
MP07 Desenvolupament web en entorn servidor
Totes les UFs del modul
MP08 Desplegament d'aplicacions web
Totes les UFs del modul
MP09 Disseny d'interfícies web
Totes les UFs del modul
MP10 Formació i Orientació Laboral
Totes les UFs del modul
MP11 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP12 Projecte de síntesi
Totes les UFs del modul
SMX Sistemes Microinformàtics i Xarxes
Tots els mòduls del cicle
MP01 Muntatge i manteniment d’equips
Totes les UFs del modul
MP02 Sistemes Operatius Monolloc
Totes les UFs del modul
MP03 Aplicacions ofimàtiques
Totes les UFs del modul
MP04 Sistemes operatius en xarxa
Totes les UFs del modul
MP05 Xarxes locals
Totes les UFs del modul
MP06 Seguretat informàtica
Totes les UFs del modul
MP07 Serveis de xarxa
Totes les UFs del modul
MP08 Aplicacions Web
Totes les UFs del modul
MP09 Formació i Orientació Laboral
Totes les UFs del modul
MP10 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP11 Anglès
Totes les UFs del modul
MP12 Síntesi
Totes les UFs del modul
CETI Ciberseguretat en Entorns de les Tecnologies de la Informació
Tots els mòduls del cicle
CiberOT Ciberseguretat en Entorns d'Operació
Tots els mòduls del cicle
nodejs_selenium

Testing amb Selenium en Node.js

Selenium es pot executar en diversos llenguatges, inclòs JS amb Node.js.

Ens pot ser molt pràctic per a realitzar tests per a Cordova o el propi NodeJS.

Referències:

Basics

Si tenim un projecte NodeJS podem afegir el packages amb:

$ npm install selenium-webdriver assert child-process

Si es tracta d'un projecte en un altre llenguatge podem crear la carpeta .test i posar els tests a dins, independents del projecte:

$ mkdir .test
$ cd .test
$ npm init
$ npm install selenium-webdriver assert child-process

Els tests s'executaran entrant a la carpeta .test i executant-los:

$ cd .test
$ node 01-xxxx.js

Per defecte s'executarà en mode HEADLESS (sense GUI). Si volem veure el browser:

$ HEADLESS=false node 01-xxx.js

Per executar els tests amb Chrome enlloc de Firefox:

$ CHROME_TESTS=chrome node 01-xxx.js


Projecte base

Ens convé tenir els tests independents del codi de l'aplicació. En aquest exemple tenim una estructura amb aquests arxius. Dins src pot haver el codi en PHP o altres llenguatges que ens interessi:

.
├── .gitignore
├── README.md
├── run.sh
├── src
│   ├── index.php
│   ├── register.php
│   └── ...
└── .test
    ├── BaseTest.js
    └── 01-page-h1.js

Cal que afegim la carpeta node_modules/ al .gitignore del nostre projecte, encara que no estiguem treballant en NodeJS:

.gitignore
node_modules/


Desenvolupament

En aquests tests funcionals, els tests estan aïllats del desenvolupament i del llenguatge emprat, pel què podem fer un objecte per testejar qualsevol altre projecte. Només el fitxer run.sh contindrà les i instruccions adients per engegar un o altre projecte.

Arxius de posada en marxa del server

run.sh (o run.bat en Windows) està a l'arrel del projecte, és a dir, al mateix nivell que la carpeta .test

Versió Linux

run.sh per a PHP

run.sh
#!/bin/bash
# directori del script run.sh
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# entrem a la carpeta del codi font
cd $SCRIPT_DIR/src
# engeguem el PHP server
php -S 0.0.0.0:8000

run.sh per a Cordova

run.sh
#!/bin/bash
# directori del script run.sh
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# entrem a la carpeta del codi font
cd $SCRIPT_DIR
# engeguem el cordova sense browser
cordova serve
Versió Windows

run.sh per a Cordova

run.bat
cordova serve


Llibreria Base

BaseTest.js
const {Builder, Browser, By, Key, until} = require("selenium-webdriver");
const firefox = require('selenium-webdriver/firefox');
const chrome = require('selenium-webdriver/chrome');
const { spawn } = require("child_process");
const assert = require('assert');
 
 
class BaseTest {
 
    constructor() {
        console.log("Constructing...")
        this.headless = process.env.HEADLESS=="false" ? false : true;
        this.browser = process.env.CHROME_TESTS ? "chrome" : "firefox";
        this.cmd = null;
        this.driver = null;
    }
 
    async setUp() {
        console.log("HEADLESS:"+this.headless);
        console.log("BROWSER:"+this.browser);
 
        // run server and setup driver
        await this.runServer( "../run", [] );
        await this.setupDriver();
        // deixem temps a que el servidor es posi en marxa
        await this.driver.sleep(2000);
    }
 
    async tearDown() {
        console.log("Closing server...");
        // parem server
        await this.stopServer();
        // deixem temps perquè es tanquin els processos
        await this.driver.sleep(2000);
        // tanquem browser
        console.log("Closing Selenium driver...");
        await this.driver.quit();
    }
 
    async run() {
        await this.setUp();
        try {
            await this.test();
        } finally {
            await this.tearDown();
        }
    }
 
    async test() {
        console.log("Empty test!");
    }
 
    async setupDriver() {
        let firefoxOptions = new firefox.Options();
        let chromeOptions = new chrome.Options();
        if( this.headless ) {
            console.log("Running Headless Tests...");
            firefoxOptions = new firefox.Options().addArguments('-headless');
            chromeOptions = new chrome.Options().addArguments('--headless=new');
        }
        if( this.browser=="chrome" ) {
            this.driver = await new Builder()
                .forBrowser(Browser.CHROME)
                .setChromeOptions(chromeOptions)
                .build();
        } else {
            this.driver = await new Builder()
                .forBrowser(Browser.FIREFOX)
                .setFirefoxOptions(firefoxOptions)
                .build();
        }
    }
 
    runServer( command, options ) {
        // Engeguem server amb la APP
        if( process.platform=="win32" ) {
            this.cmd = spawn(command+".bat",options,{shell:true});
        } else {
            // linux, macos (darwin), or other
            this.cmd = spawn(command+".sh",options);
        }
 
        this.cmd.stdout.on("data", data => {
            console.log(`stdout: ${data}`);
        });
        this.cmd.stderr.on("data", data => {
            console.log(`stderr: ${data}`);
        });
        this.cmd.on('error', (error) => {
            console.log(`error: ${error.message}`);
        });
        this.cmd.on("close", code => {
            console.log(`child process exited with code ${code}`);
        });
    }
 
    async stopServer() {
        // tanquem servidor
        if( process.platform=="win32" ) {
            spawn("taskkill", ["/pid", this.cmd.pid, '/f', '/t']);
        } else {
            // Linux, MacOS or other
            await this.cmd.kill("SIGHUP")
        }
    }
 
}
 
// publiquem l'objecte BaseTest
exports.BaseTest = BaseTest;


Test 01 : comprovem header H1

01-header-h1.js
// carreguem les llibreries
const { BaseTest } = require("./BaseTest.js")
const { By, until } = require("selenium-webdriver");
const assert = require('assert');
 
// heredem una classe amb un sol mètode test()
// emprem this.driver per utilitzar Selenium
 
class MyTest extends BaseTest
{
	async test() {
        // testejem H1 a la home page
        //////////////////////////////////////////////////////
        await this.driver.get("http://localhost:8000/browser/www/");
        var currentText = await this.driver.findElement(By.tagName("h1")).getText();
        var expectedText = "Tasklist";
        assert( currentText==expectedText, "Títol H1 de la pàgina principal incorrecte");
 
        console.log("TEST OK");
	}
}
 
// executem el test
 
(async function test_example() {
	const test = new MyTest();
	await test.run();
	console.log("END")
})();


Test 02 : formulari buit

Aquest exemple testeja que si deixem buit el nom, ens surt un alert que ens avisa.

02-nom-buit.js
// carreguem les llibreries
const { BaseTest } = require("./BaseTest.js")
const { By, until } = require("selenium-webdriver");
const assert = require('assert');
 
// heredem una classe amb un sol mètode test()
// emprem this.driver per utilitzar Selenium
 
class MyTest extends BaseTest
{
	async test() {
        // testejem login
        //////////////////////////////////////////////////////
        await this.driver.get("http://localhost:8000/register.php");
        //await this.driver.findElement(By.name("nom")).getText();
 
        // el INPUT name="nom" està buit
 
        await this.driver.findElement(By.xpath("//button[text()='Seguent']")).click();
 
        // comprovem que l'alert message és ERRONI
        await this.driver.wait(until.alertIsPresent(),2000,"ERROR TEST: després del SEGUENT ha d'aparèixer un alert amb el resultat de la validació del NOM.");
        let alert = await this.driver.switchTo().alert();
        let alertText = await alert.getText();
        let assertMessage = "El NOM no pot estar buit.";
        assert(alertText==assertMessage,"ERROR TEST: si el nom està buit, l'alert ha de dir: '"+assertMessage+"'.");
        await alert.accept();
 
        console.log("TEST OK");
	}
}
 
// executem el test
 
(async function test_example() {
	const test = new MyTest();
	await test.run();
	console.log("END")
})();


Test Cordova : afegir tasca

Aquest exemple inclou l'ús de prompts, que es fa com si fos un alert.

Fixeu-vos que Cordova necessita anar a la web /browser/www.

addtask.js
// carreguem les llibreries
const { BaseTest } = require("./BaseTest.js")
const { By, until } = require("selenium-webdriver");
const assert = require('assert');
 
// heredem una classe amb un sol mètode test()
// emprem this.driver per utilitzar Selenium
 
class AddTaskTest extends BaseTest
{
	async test() {
        // testejem afegir tasca en tasklist de Cordova
        //////////////////////////////////////////////////////
        await this.driver.get("http://localhost:8000/browser/www/");
 
        // cliquem botó "+"
        await this.driver.findElement(By.xpath("//button[text()='+']")).click();
 
        // el prompt pel text de la tasca es tracta igual que un alert en Selenium
        await this.driver.wait(until.alertIsPresent(),2000,"ERROR TEST: el botó '+' d'afegir tasca ha d'obrir un prompt.");
        let prompt = await this.driver.switchTo().alert();
        // afegim el text de la tasca i acceptem
        var taskText = "lalala";
        prompt.sendKeys(taskText);
        await this.driver.sleep(1000);
        await prompt.accept();
        await this.driver.sleep(1000);
 
        // checkejem tasca
        await this.driver.findElement(By.xpath("//li[text()='"+taskText+"']")).click();
 
        console.log("TEST OK");
	}
}
 
// executem el test
 
(async function test_example() {
	const test = new AddTaskTest();
	await test.run();
	console.log("END")
})();

Crea un test DelTaskTest similar a l'anterior que:

  • Crei 3 tasques amb noms aleatoris.
  • Esborri una d'elles.
  • Comprovi que no existeix la tasca esborrada i sí que romanen les altres dues.
nodejs_selenium.txt · Darrera modificació: 2024/01/31 20:23 per enric_mieza_sanchez