2011-11-03 7 views
22

Quando modellate gli oggetti della pagina, come gestireste una pagina che ha una forma e circa 50 campi di input? Qual è la migliore pratica qui?Best practice del modello a oggetti di pagina in selenio

Vuoi creare un oggetto di pagina e scrivere una funzione separata per ogni azione di input? o scriveresti una funzione quali parametri vengono passati ad esso e inserisce il testo?

ad es.

public void enterFirstName(String firstName) { 
    driver.type("firstNameField", firstName); 
} 

public void enterSecondName(String secondName) { 
    driver.type("secondNameField", secondName); 
} 

o

public void fillInForm(String inputFieldName, String text) { 
    driver.type(inputFieldName, text); 
} 

posso vedere nel primo modello, quando si scrivono i test, le prove sono più descrittivo, ma se la pagina contiene troppi campi di input, creando l'oggetto pagina diventa ingombrante.

Questo post è anche abbastanza interessante nella strutturazione test selenio nella pagina Oggetti Functional Automated Testing Best Practices with Selenium WebDriver

+0

Dai un'occhiata alla [mia domanda stackoverflow] (http://stackoverflow.com/questions/8149808/whats-the-best-way-to-use-selenium-pageobject-design-pattern) per un esempio su come Utilizzerò lo schema di progettazione degli oggetti della pagina. Io non sono al 100% me stesso ma da molte letture, sono sicuro che sto nella giusta direzione, spero che ciò che ho incollato ti aiuti. –

+0

http://selenium-tutorial.blogspot.com/2012/06/webdriver-page-objects-pattern.html –

+1

È possibile inserire tutti i tipi WebElement simili in un elenco. quindi, se hai 40 campi di testo puoi disegnare dall'elenco uno per uno, ottenere il "nome" o "id" per identificarlo, e quindi operare su di esso. – djangofan

risposta

9

mi piace sempre di rompere le cose in gruppi di informazioni correlate. Ad esempio, se dispongo di una classe utente, potrei suddividerla in alcune classi più piccole: LoginCredentials, ProfileInfo, Settings, ecc., Ma di solito avrò sempre una classe utente di livello superiore che contiene queste sottoclassi.

Una cosa che consiglierei sarebbe di passare un oggetto a una funzione FillForm piuttosto che a tutte quelle singole funzioni. Ci sono alcuni grandi vantaggi nell'usare questo approccio. Uno, potresti avere alcuni oggetti "comuni" preconfigurati che usi per molti dei tuoi casi di test. Per esempio:

public class FormInfo 
{ 
    string Domain; 
    string Name; 
    string Category; 
    // etc... 

    public FormInfo(string domain, string name, string category) 
    { 
    Domain = domain; 
    Name = name; 
    Category = category; 
    // etc... 
    } 
} 


// Somewhere in your initialization code 
public static FormInfo Info1 = new FormInfo("myDomain1", "myName1", "myCategory1"); 
public static FormInfo Info2 = new FormInfo("myDomain2", "myName2", "myCategory2"); 

You can still update one of your common merchants if you need to do something one-off: 

// In your test case: 
Info1.Category = "blah"; 
FormPage.FillForm(Info1); 

O, è possibile creare un nuovo oggetto mercantile per uno specifico caso di test, se necessario.È anche possibile fare cose come validazione campo sia utilizzando questi oggetti, o di quello che faccio di solito è rompere il modello oggetto pagina per specifica verifica dei campi, quindi se io sono la convalida del campo dominio mercantile potrei fare questo:

Info1.Domain = null; //This should make the FillForm function skip doing anything with this field. 
FormPage.FillForm(Info1); 
FormPage.DomainTextBox.Text = "field validation string"; 

Un altro importante vantaggio di questo approccio è che se la pagina viene sempre aggiornata per aggiungere, rimuovere o modificare campi, è necessario aggiornare solo l'oggetto FormInfo e la funzione FillForm e non è necessario modificare casi di test specifici che richiamano la funzione FillForm - supponendo che stiano utilizzando uno dei comuni oggetti FormInfo. Un'altra possibilità per ottenere una maggiore copertura sarebbe quella di impostare uno dei comuni oggetti FormInfo per generare stringhe casuali per ciascuno dei campi che rispettano la lunghezza minima/massima e scorrere tra tutti i diversi caratteri consentiti. Ciò consente di ottenere alcuni test aggiuntivi dallo stesso set di test, anche se potrebbe anche aggiungere un po 'di rumore se si inizia a ottenere risultati di errore solo da stringhe specifiche, quindi fate attenzione.

9

L'idea alla base del modello di oggetto pagina è che astrae l'attuazione di distanza dal chiamante. Nel primo meccanismo, lo stai facendo perché il chiamante non ha bisogno di sapere se il nome del campo di input html cambia da "firstName" a "user_first_name", mentre nella tua seconda implementazione qualsiasi modifica alla pagina effettiva dovrebbe essere trasmesso a tutti i chiamanti dell'oggetto della pagina.

Mentre potrebbe essere più lavoro in anticipo per creare l'oggetto della pagina, se si mantiene l'incapsulamento si salverà il lavoro a lungo termine quando la pagina html reale inevitabilmente cambia.

+0

Grazie a digitalJoel, la pagina con variabili di localizzatore pubblico (il come) definite nella parte superiore della pagina e quindi nella mia classe Test, istanzio quella pagina e passo le variabili di localizzazione al fillInform generico. In questo senso, le mie variabili sono sempre in una posizione, l'oggetto della pagina e tutti i miei test faranno riferimento a tali variabili, quindi quando cambiano, devo comunque mantenere in una posizione. –

+0

Questo sarebbe un modo per farlo. Avere i nomi come campi finali statici pubblici e quindi fornire l'unico metodo. Funziona finché non hai bisogno di eseguire qualche elaborazione speciale per un singolo valore, quindi hai un metodo separato per 'myPage.setSpecialValue (blah)' e per tutto il resto hai 'myPage.fillInForm (MyPage.MY_NAME, blah)' ed è Incoerente, ma quello può essere un ponte che puoi attraversare quando/se vieni ad esso invece di dover costruire per ora. Tocca a voi. – digitaljoel

+2

Il migliore "grazie" sarebbe di alzare il voto di alcune risposte. Su 14 risposte alle tue domande hai solo votato 4 risposte e non hai accettato alcuna risposta. Non sto parlando solo della mia risposta, ma tutte le risposte che trovi utili (come quella di Sam Woods su questa domanda) possono/devono essere riviste. – digitaljoel

0

Il modo in cui lo faccio nei miei moduli è quello di ottenere un elenco di tutti gli input sulla pagina. Quindi rimuovere tutti gli elementi di input che non sono visualizzati. Dopodiché posso inserire testo valido o non valido per ciascuno degli input. Da lì raccolgo il riepilogo della convalida per assicurarmi di ottenere l'errore corretto oppure no. Altrimenti, registrare l'eccezione.

Ciò che mi consente di inserire il testo in tanti input quanti sono nella pagina e mi consente comunque di registrare le eccezioni e inviarle via e-mail. Cattura anche campi di testo e password nel mio elenco e ho un elenco separato per i campi di controllo e le opzioni poiché ci sono cose diverse che di solito voglio fare con quelle.

ciò che si riduce a è che tutto quello che devo fare per testare una pagina è questa:

for (int i = 0; i < inputs.Count(); i++) 
{ 
    //This captures the error message string created in the input validation method 
    //nextButton is the IWebElement of the button to click to submit the form for validation 
    //ErrorMessageID is the ID of the Validation Summary display box (i.e. ErrorMessageID = "FormSummary" <asp:ValidationSummary ID="FormSummary" runat="server" CssClass="errorMessage" /> 

    string InputValidationText = utilities.InputValidation(driver, inputs, i, nextButton, ErrorMessageID) 
    if(InputValidationText != string.Empty) 
    { 
    //LogError 
    } 
} 
1

Oltre ai vostri enterWhatever() metodi, di solito anche creare un metodo createWhatever(field1, field2, ...), che posso usare come un percorso veloce per la creazione di qualunque sia la forma costruisce, da utilizzare quando il vero scopo del test è un'altra cosa. Pertanto, se ho bisogno di creare un cliente per testare la presentazione di un biglietto, il test va alla pagina CreateACustomer e invoca semplicemente il numero createCustomer(firstName, lastName, emailAddress, ...), quindi continua con l'operazione più sfumata di creazione di un ticket utilizzando quel cliente.

1

sto rispondendo una vecchia questione a beneficio dei lettori.

Insieme ad altre buone risposte qui, vorrei aggiungere alcuni suggerimenti qui per coloro che sono nuovi a POM.

Gli oggetti di pagina sono un modello di progettazione ben noto, ampiamente accettato dagli ingegneri dell'automazione, per creare un file di classe separato per ogni pagina dell'applicazione per raggruppare tutti gli elementi come proprietà e i loro comportamenti/funzionalità aziendali come metodi della classe. Ma ha pochi problemi nella creazione di una classe per una pagina - specialmente quando la pagina ha più/diversi gruppi di elementi/elementi complessi come una griglia/calendario/una tabella HTML ecc.

La classe potrebbe contenere troppe responsabilità gestire. Dovrebbe essere ristrutturato e suddiviso in classi più piccole. Vale a dire, seguendo lo Single Responsibility Responsible.

Controllare l'immagine qui per l'idea.

enter image description here

Cioè, creare frammenti di pagina riutilizzabili & lasciare che l'oggetto pagina principale di servire i frammenti di pagina.

Verificare here per ulteriori informazioni.