Selenium e la ricerca sulla tabella

Una delle operazioni più comuni che puo’ capitarvi in un test è la ricerca un testo in una tabella seguito dal click, nella stessa riga del testo trovato, su un pulsante o link per fare determinate azioni come vedere dettagli, modificare o cancellare un oggetto nella tabella.

Normalmente su un sito web vi trovate di fronte a tabelle divise in pagine per non avere una pagina troppo lunga e di conseguenza avrete anche un pulsante per proseguire alla prossima pagina, pulsante che non appare nell’ultima pagina ovviamente.

Con l’aiuto dell’estensione FlowControl, che permette di realizzare cicli o condizioni, ho quindi creato un test case che cerca il mio cognome in questa pagina (sezione s) e, se trovato, fa alcune operazioni, come memorizzare informazioni (nome, organizzazione, area) o cliccare sul link per vedere i contributi.

Il test case è il seguente:

looptest
store false ElementFound
while storedVars.ElementFound!=true && selenium.isElementPresent(“//div[@id=’content’]/table[2]/tbody/tr/td[1]/div[3]/a”);
searchSurname Stani seeContributions
gotoIf ${ElementFound}==true skipClickNext
clickAndWait //img[@alt=’Next’]
label skipClickNext
endWhile
gotoIf ${ElementFound}==true skipLastSearch
searchSurname Stani seeContributions
label skipLastSearch
verifyExpression ${ElementFound} true

Inizializziamo la variabile ElementFound a false, tale variabile ci permette di verificare alla fine se abbiamo trovato o meno il cognome (o elemento in generale).

Creiamo il ciclo (comando while) dove ad ogni iterazione verifichiamo se l’elemento è stato trovato e se è presente il link alla pagina successiva. Se l’elemento non è stato trovato allora facciamo una ricerca tramite il comando creato da me searchSurname.

Il comando searchSurname cerca nella prima colonna della tabella il cognome e, una volta trovato, clicca sul link dei contributi tramite l’azione seeContributions (per i dettagli vedere sotto).

Il comando searchSurname imposta a true la variabile ElementFound nel caso in cui il cognome è stato trovato. Se la variabile è  a true non dobbiamo cliccare sulla prossima pagina (salto alla label skipClickNext) e usciremo nel ciclo alla prossima iterazione. Se invece il cognome non è stato trovato (variabile a false) cliccheremo sul pulsante Next.

Dopo la fine del ciclo (endwhile) abbiamo bisogno di un ulteriore ricerca nel caso in cui raggiungiamo l’ultima delle pagine dove l’elemento non è stato ancora trovato e non esiste il link alla pagina successiva (salto alla label skipLastSearch).

Verifichiamo dunque alla fine se la variabile è a true (verifyExpression).

Andiamo a vedere ora il comando searchSurname:

function search(divId, textToFind, searchCol){
	obj_by_id = selenium.browserbot.getCurrentWindow().document.getElementById(divId);
	rowlist = obj_by_id.getElementsByTagName("TR");
	rowfound = -1;
	for (rowNo=1; rowNo<rowlist.length; rowNo++) {
		var cella = rowlist[rowNo].cells[searchCol];
		LOG.info("reading element "+ rowNo+": "+cella.innerHTML);
		if(cella.innerHTML == textToFind){
			LOG.info( "Found element " + textToFind + " at row "+rowNo);		
	        rowfound=rowNo;
			break;			
		}
	}
	if(rowfound==-1)
		LOG.info("Element "+textToFind+" not found!");
	return rowfound;
}

function action(divId, rowNo, actionType){
	rowPath = "//table[@id=\'"+divId+"\']/tbody/tr["+rowNo+"]";
	if(actionType == "storeName")
		selenium.doStoreText(rowPath+"/td[2]", "NameFound");
	else if(actionType == "storeOrganization")
		selenium.doStoreText(rowPath+"/td[3]", "OrganizationFound");
	else if(actionType == "storeArea")
		selenium.doStoreText(rowPath+"/td[4]", "AreaFound");
	else if(actionType == "seeContributions")
		selenium.doClick(rowPath+"/td[6]/a");
	else
		Assert.fail("Action "+actionType+" is wrong!");
}

Selenium.prototype.doSearchSurname = function(textToFind, actionType){
	var divId = "Countrytable";
	var searchCol=0;
	var found=false;

	var rowNo=search(divId, textToFind, searchCol);
	if(rowNo!=-1){
		action(divId, rowNo, actionType);
		found=true;
	}
	storedVars['ElementFound']=found;
};

Il comando searchSurname chiama la funzione search passando l’id in cui è contenuta la tabella (Countrytable) e la  colonna in cui cercare il cognome (colonna 0 ). La funzione search cerca l’esatto testo dentro ogni cella della colonna indicata e restituisce -1 se il cognome non è stato trovato oppure il numero di riga in cui il cognome si trova.

Il numero di riga insieme all’id della tabella e il tipo di azione vengono usati per chiamare la funzione action nel caso in cui qualcosa è stato trovato (rowNo!=-1).

La funzione action a seconda del tipo di azione invoca uno dei comandi di Selenium. Nel nostro caso abbiamo le azioni:

  • storeName, che memorizza il nome nella variabile NameFound
  • storeOrganization, che memorizza l’organizzazione nella variabile OrganizationFound
  • storeArea, che memorizza l’area nellla variabile AreaFound
  • seeContributions, che clicca sul link dei contributi (azione che usiamo nel nostro testcase).

Se l’utente inserisce una azione non riconosciuta allora il test fallisce e si interrompe tramite il comando Assert.fail .

Alla fine del comando searchSurname memorizziamo nella variabile ElementFound il valore true se il cognome, nella ricerca della tabella corrente, è stato trovato o false se non è stato trovato.

Per eseguire il test case  in Selenium dovete quindi includere il file goto_sel_ide.js e il comando searchSurname come estensioni di Selenium dal menu Options.

Il test case puo’ essere migliorato ma credo che comunque avrete bisogno di adattarlo alle vostre esigenze.

Buona ricerca :-)

Advertisements

6 thoughts on “Selenium e la ricerca sulla tabella

  1. Ciao!
    Ho letto e cercato di capire quello che hai scritto ma purtroppo non sono troppo sveglia in fatto di informatica :p
    Attualmente uso Selenium IDE (plug-in per firefox) per compiere delle azioni ripetitive dentro un sito non mio. Per farlo però prima mi devo loggare inserendo user e password a manina e solo dopo faccio andare Selenium… e mi rompo le scatole non poco.
    Avevo quindi intenzione di fare una lista su una pagina web creata da me tipo:
    utente1@email.it | password
    utente2@email.it | password
    utente3@email.it | password
    al cui interno ci metto in sequenza gli utenti e usare Selenium affinchè copi e incolli utente1 e password, si logghi, fa quello che deve fare, si slogghi e poi automaticamente copi e incolli utente2 ecc…
    Credo che con quello che hai scritto tu su questo post si possa fare, ma purtroppo non riesco a capire come… :'(
    Riusciresti a darmi una mano? Grazie, Teresa

  2. Ma, guarda, immagino che via chat sia più semplice, ma bastava anche un help direttamente sul tuo blog :)
    Comunque il plugin per Selenium-ide sono riuscita a installarlo: non appare nella lista, mi sento una figa!
    Teresa

    • Allora per rimanere sul blog :-) quello che ti consiglio è usare variabili globali da memorizzare nel primo test case (che usi giusto per memorizzare variabili che sono condivise tra test case) e lo puoi fare con l’estensione: http://wiki.openqa.org/display/SEL/global

      Quindi nel primo test case inserisci email e password per ogni utente.
      Poi fai un secondo test case con solo il login, un altro per l’operazione e un altro per il logout. In questa maniera puoi riusare login e logout nella test suite ma dovrai usare diverse variabili (email e password) ovviamente. Puoi allargare il discorso facendo un loop ma meglio andare per passi.

      Se mi mandi il tuo contatto gmail possiamo anche chattare.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s