Question

Je aime vraiment comment le sélénium 2 par convention vous pousse vers l'utilisation PageObjects comme POJO, puis en utilisant simplement le PageFactory instancier les champs dans cette classe.

Qu'est-ce que je trouve limite est que nous réutilisons beaucoup d'éléments sur plusieurs pages. Le gros problème est que ces composants ne sont pas réutilisés le même identifiant / nom quand ils apparaissent sur différentes pages; Cependant, les tests que nous courrions pour chacun d'eux est le même.

A titre d'exemple nous recueillons des dates dans de nombreux endroits. Ainsi, un exemple la page objet pour ce qui pourrait être (mois, jour des champs supprimés):

public class DatePageObject {
    private WebDriver driver;

    DatePageObject(WebDriver driver) {
        this.driver = driver;
    }

    @FindBy( id = "someIdForThisInstance")
    private WebElement year;

    public void testYearNumeric() {
        this.year.sendKeys('aa');
        this.year.submit();
        //Logic to determine Error message shows up
    }
}

Alors je ne pouvais tout simplement tester cela avec le code ci-dessous:

public class Test {
    public static void main(String[] args) {
         WebDriver driver = new FirefoxDriver();
         DatePageObject dpo = PageFactory.initElements(driver, DriverPageObject.class);
         driver.get("Some URL");
         dpo.testYearNumeric();
    }
}

Ce que je voudrais vraiment faire est d'avoir une configuration avec laquelle Spring je peux injecter cet identifiant / nom / XPath, etc ... dans l'application.

Est-il possible que je peux le faire, sans perdre la capacité d'utiliser le PageFactory?

Modifier 1 -. Ajout de classes de niveau de base idéal, le travail sur mesure localisateurs et usines

public class PageElement {
    private WebElement element;
    private How how;
    private String using;

    PageElement(How how, String using) {
        this.how = how;
        this.using = using;
    }
    //Getters and Setters
}


public class PageWidget {
    private List<PageElement> widgetElements;
}


public class Screen {
    private List<PageWidget> fullPage;
    private WebDriver driver;

    public Screen(WebDriver driver) {
        this.driver = driver;
        for (PageWidget pw : fullPage) {
            CustomPageFactory.initElements(driver, pw.class);
        }
}

Edit 2 -. Tout comme une note, aussi longtemps que vous utilisez 2.0.a5 ou plus Sélénium, vous pouvez maintenant donner au conducteur une valeur de délai d'attente implicite

Vous pouvez remplacer votre code avec:

private class CustomElementLocator implements ElementLocator {
    private WebDriver driver;
    private int timeOutInSeconds;
    private final By by;


    public CustomElementLocator(WebDriver driver, Field field,
            int timeOutInSeconds) {
        this.driver = driver;
        this.timeOutInSeconds = timeOutInSeconds;
        CustomAnnotations annotations = new CustomAnnotations(field);
        this.by = annotations.buildBy();
        driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS); //Set this value in a more realistic place
    }


    public WebElement findElement() {
        return driver.findElement(by);
    }
}
Était-ce utile?

La solution

Vous pouvez construire votre objet des éléments Web commun (juste inventé ce nom :)) - chaque CWE représentera un « widget de » qui est utilisé sur des pages différentes. Dans votre exemple, ce sera une une sorte de date Widget - il contient l'année, le mois et un jour. Fondamentalement, ce sera une page objet.

PageFactory exige que les constantes de chaîne à utiliser dans les annotations de @FindBy.

Pour résoudre cette limitation que nous avons créé notre propre ElementLocators.

Vous pouvez utiliser la DateWidget dans votre test:

....
DateWidget widget = new DateWidget(driver, "yearId", "monthId", "dayId");
....

public void testYearNumeric() {
        widget.setYear("aa");
        widget.submit();
        //Logic to determine Error message shows up

        // ... and day
        widget.setDay("bb");
        widget.submit();
        //Logic to determine Error message shows up
    }

La classe DateWidget, qui contient des localisateurs personnalisés et parseurs annotation est:

package pagefactory.test;

import java.lang.reflect.Field;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.pagefactory.Annotations;
import org.openqa.selenium.support.pagefactory.ElementLocator;
import org.openqa.selenium.support.pagefactory.ElementLocatorFactory;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.Wait;
import org.openqa.selenium.support.ui.WebDriverWait;

public class DateWidget {

    // These constants are used to identify that they should be changed to the actual IDs
    private static final String YEAR_ID = "$YEAR_ID$";
    private static final String MONTH_ID = "$MONTH_ID$";
    private static final String DAY_ID = "$DAY_ID$";

    // Elements whose ids will be replaced during run-time
    /** Year element */
    @FindBy(id = YEAR_ID)
    private WebElement year;

    /** Month element */
    @FindBy(id = MONTH_ID)
    private WebElement month;

    /** day element */
    @FindBy(id = DAY_ID)
    private WebElement day;

    // The ids of the elements
    /** ID of the year element */
    private String yearId;

    /** ID of the month element */
    private String monthId;

    /** ID of the day element */
    private String dayId;

    public DateWidget(WebDriver driver, String yearId, String monthId,
            String dayId) {
        this.yearId = yearId;
        this.monthId = monthId;
        this.dayId = dayId;

        PageFactory.initElements(new CustomLocatorFactory(driver, 15), this);
    }

    public String getYear() {
        return year.getValue();
    }

    public void setYear(String year) {
        setValue(this.year, year);
    }

    public String getMonth() {
        return month.getValue();
    }

    public void setMonth(String month) {
        setValue(this.month, month);
    }

    public String getDay() {
        return day.getValue();
    }

    public void setDay(String day) {
        setValue(this.day, day);
    }

    public void submit() {
        year.submit();
    }

    private void setValue(WebElement field, String value) {
        field.clear();
        field.sendKeys(value);
    }

    private class CustomLocatorFactory implements ElementLocatorFactory {
        private final int timeOutInSeconds;
        private WebDriver driver;

        public CustomLocatorFactory(WebDriver driver, int timeOutInSeconds) {
            this.driver = driver;
            this.timeOutInSeconds = timeOutInSeconds;
        }

        public ElementLocator createLocator(Field field) {
            return new CustomElementLocator(driver, field, timeOutInSeconds);
        }
    }

    private class CustomElementLocator implements ElementLocator {
        private WebDriver driver;
        private int timeOutInSeconds;
        private final By by;

        public CustomElementLocator(WebDriver driver, Field field,
                int timeOutInSeconds) {
            this.driver = driver;
            this.timeOutInSeconds = timeOutInSeconds;
            CustomAnnotations annotations = new CustomAnnotations(field);
            this.by = annotations.buildBy();
        }

        @Override
        public WebElement findElement() {
            ExpectedCondition<Boolean> e = new ExpectedCondition<Boolean>() {
                public Boolean apply(WebDriver d) {
                    d.findElement(by);
                    return Boolean.TRUE;
                }
            };
            Wait<WebDriver> w = new WebDriverWait(driver, timeOutInSeconds);
            w.until(e);

            return driver.findElement(by);
        }
    }

    private class CustomAnnotations extends Annotations {

        public CustomAnnotations(Field field) {
            super(field);
        }

        @Override
        protected By buildByFromShortFindBy(FindBy findBy) {

            if (!"".equals(findBy.id())) {
                String id = findBy.id();
                if (id.contains(YEAR_ID)) {
                    id = id.replace(YEAR_ID, yearId);
                    return By.id(id);
                } else if (id.contains(MONTH_ID)) {
                    id = id.replace(MONTH_ID, monthId);
                    return By.id(id);
                } else if (id.contains(DAY_ID)) {
                    id = id.replace(DAY_ID, dayId);
                    return By.id(id);
                }
            }

            return super.buildByFromShortFindBy(findBy);
        }

    }

}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top