Перейти к содержимому

Публикации Isidor2811

21 публикаций создано Isidor2811 (учитываются публикации только с 30 марта 2023)


#168076 Одинаковые страницы

Отправлено автор: Isidor2811 30 августа 2018 - 18:03 в Автоматизированное тестирование

Элементы, которые есть не только на одной странице - выносятся в отдельный класс, а потом путём композиции он добавляется на те страницы, где присутствует.

Спасибо за ответ! Может еще найдется одна две ссылки хороших с материалом по композиции?




#168055 Одинаковые страницы

Отправлено автор: Isidor2811 30 августа 2018 - 08:05 в Автоматизированное тестирование

Всем привет!
 
Есть небольшое замешательство и пока не пойму как лкчше делать не хочу дальше создавать тесты, так как потом нужно будет много переделывать.
 
Проблема: На прикрепленном изображении мы видим две страницы: Исходящий документ (OutComeDoc) и Внутренний документ (InternalDoc). Это два отдельных класса - использую page object.
 
Сначала работал над тестами для Исходящий документ. Мы находимся на вкладке адресат (тоже отдельный класс AddressTabOutcomeDoc) 
На этой вкладке есть 3 вебелемента с которыми я работаю: два поля и выпадающий список. Дальше пример кода для одного поля:
 
Поле наименование:
@FindBy(xpath = "//input[contains(@id,'lmr_contragents-cntrl')]")
WebElement addressNameField;

public AddressTabOutcomeDoc setAddressNameField(String name){
        waitHelper.waitForVisibility(addressNameField,10);     
        addressNameField.sendKeys(name);        
        return this;
}

Использую page factory я ищу елемент на странице, потом cоздаю метод с возвращаемым типом значения AddressTabOutcomeDoc

и возвращаю this, так как я не делаю переход на другую страницу, а просто возвращаю обновленый обект страницы(вкладки) Адресат

 

Дальше когда все поля заполнены мне нужно перейти на другую вкладку (страницу(отдельный класс)). Код для этого следующий:

 @FindBy(xpath = "//input[contains(@id,'lmr_contragents-cntrl-button')]")
    WebElement addAddresatButton;

    public SenderTabOutcomeDoc goToSenderTab(){
        waitHelper.waitForVisibility(addAddresatButton,10);
        addAddresatButton.click();
        return new SenderTabOutcomeDoc(driver);
    }

Здесь у меня уже идет переход на другую страницу, поэтому я возращаю новый обьект страницы(вкладки) SenderTabOutcomeDoc.

 

Дальше отрывок кода самого теста:

....
        addressTabOutComeDoc.setAddressNameField("Иванов И.И.");
        addressTabOutComeDoc.setRegisterNameField("Петров П.П.")
        addressTabOutComeDoc.selecCity("Киев");
        SenderTabOutComeDoc senderTabOutComeDoc = addressTabOutComeDoc.goToSenderTab
....

Теперь у меня есть Внутренний документ где есть точно такая же вкладка AddressTabInternalDoc, с точно такими же полями.

 

Как работать с этой вкладкой:

 

Вариант 1. Копипастить весь код с вкладки  AddressTabOutComeDoc на вкладку AddressTabInternalDoc с заменой возвращаемых значений в методах (c return new SenderTabOutcomeDoc(driver) на return new SenderTabInternalDoc(driver);)

 

Вариант2: Пробовал наследоваться от вкладки Адресат Исходящего Внутреним документом. Тоже не получаеться. В этом случае типы возвращаемых значений нужно делать void

 

Вариант3: Разработчики советуют использовать интерфейсы.

 

 

Как работать с одинаковыми страницами? 

 

Сейчас просто использовался вариантом 1. Но в случае изменения на этой вкладки нужно будет менять в двух местах

 

 

 

 

Прикрепленные изображения

  • 123.jpg



#167516 Запускаю автотест, после прохождения авторизации тест перестает работа

Отправлено автор: Isidor2811 01 августа 2018 - 13:55 в Автоматизированное тестирование

 

Ну, у вас после логина элемент, на который вы хотите кликнуть, закрыт другим.

<div class="sc-hzDkRC cgbTV">

посмотрите что эт, наверное какая-нибудь штука которая показывается только авторизованным пользователям или что-то подобное

Это какая-то ерунда, которая не проявляется визуально при работе с сайтом, но после авторизации экранирует главную страницу (так это выглядит при выборе элемента в html), вручную работать можно, тесты не проходят. Буду разбираться.

 

WebElement element = driver.findElement(By.id("gbqfd"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", element);

https://stackoverflo...sing-javascript




#167151 Upload файла через стандартное окно Windows

Отправлено автор: Isidor2811 13 июля 2018 - 06:53 в Автоматизированное тестирование

жаль, прийдется делать на виртуальной машине. Спасибо за ответы




#167127 Upload файла через стандартное окно Windows

Отправлено автор: Isidor2811 12 июля 2018 - 11:41 в Автоматизированное тестирование

Всем привет! Есть небольшая проблема.

 

В приложении есть кнопка (сразу скажу что это не мы разрабатывали эту функциональность, и повлиять на нее мы не можем), по нажатии этой кнопки, а что самое важное даже на поле возле кнопки открывается стандартное окно загрузки файла windows 123.jpg   --->   234.jpg

 

Делаю так:

 

Копирую в буфер обмена путь к ключу

public void copyPathToKeyToClipBoard(){
        StringSelection copyToClipBoard = new StringSelection(ECPKeysConfig.pathToKey);
        Toolkit.getDefaultToolkit().getSystemClipboard().setContents(copyToClipBoard, null);
    }

После того как нажимаю на кнопку и открывается окно вставляю путь, так как поле в окне с путем к файлу активное, то никаких проблем не возникает

public void pastePathToKey() throws AWTException {
        Robot robot = new Robot();
        robot.keyPress(KeyEvent.VK_CONTROL);
        robot.keyPress(KeyEvent.VK_V);
        robot.keyRelease(KeyEvent.VK_V);
        robot.keyRelease(KeyEvent.VK_CONTROL);
        robot.keyPress(KeyEvent.VK_ENTER);
}

Но проблема в том что во время этой операции мне нужно обязательно фокусироваться на этом окне, то есть если на пример я запущу тест и на соседнем мониторе буду что то писать в word то этот путь к ключу просто будет вставлен в word.

 

Кто подскажет как решить эту проблему.

 

Сражу скажу что actions не работают. Также я не могу на прямую отправить путь к файлу в поле возле кнопки, в любом другом месте работает но не тут, так как после нажатия на поле открывается окно windows

 




#166711 Сделать клик по найденным элементам (Python Selenium)

Отправлено автор: Isidor2811 20 июня 2018 - 11:08 в Автоматизированное тестирование

Я тоже так хотел сделать, но проблема в том что цифру нельзя загнать в переменную, по синтаксису не получится.

Почему не получиться? Можно посмотреть код?




#166708 Сделать клик по найденным элементам (Python Selenium)

Отправлено автор: Isidor2811 20 июня 2018 - 10:29 в Автоматизированное тестирование

Добрый день.

Коллеги, ребята  и просто добрые люди, есть примерно следующая ситуация:

 

1) Есть циферблат (от 0 - 9) 

2) У каждой цифры свой локатор

3) Необходимо что бы я передавал пин-код из 4х цифр и соответственно происходил клик по необходимой кнопке,

сейчас хардкод при котором всегда вводится 1234.

 

 

def pin(self, pin-code=None):
WebDriverWait(self.driver, self.time_to_wait).until(
expected_conditions.visibility_of_element_located(locators.NUMPAD)
)
if not pin:
self.driver.find_element(*locators.NUMPAD_1).click()
self.driver.find_element(*locators.NUMPAD_2).click()
self.driver.find_element(*locators.NUMPAD_3).click()
self.driver.find_element(*locators.NUMPAD_4).click()
else:
pin_button = pin.split
pin_button.split(",")
 

Соответственно как это реализовать пока не знаю, быть может у вас есть идеи?

Спасибо

 

Каждую цифру пинкода, который передаете загоняете в переменную, дальше в  локаторы, например NUMPAD_3 вместо этой тройки ставите эту переменную "NUMPAD_"+var




#166556 Page Object ver.2

Отправлено автор: Isidor2811 11 июня 2018 - 09:41 в Автоматизированное тестирование

Всем еще раз привет! Вот тут http://software-test...-nasledovaniia/ я создавал тему касающейся правильности создания архитектуры Page Object. Мне указали на мои ошибки, и я начал гуглить и искать информацию по их устранению.

 

 

И так:

Архитектура классов тут: https://www.screenca...om/t/uUoP0S0wN7

 

Пока что реализовал вот как:

Создал класс BaseTest, в котором у меня реализована инициализация драйвера, также убрал SetProperty с явным указанием в нем пути к драйверу заменив его dependency WebDriverManager в pom файле. В итоге получился такой код:

public class BaseTest {

    protected WebDriver driver;

    @BeforeClass
    public void setUpDriver(){
        WebDriverManager.chromedriver().setup();
        driver = new ChromeDriver();
    }

    @AfterClass
    public void tearDown(){
        driver.quit();
    }
}

От этого класса у меня будут наследоваться все тестовые классы.

 

Дальше создал класс BasePage, от которого будут наследоваться все пейджы. Так как пейджам нужен драйвер, то в данном классе (BasePage) я создал конструктор, в итоге каждый пейдж который будет создаваться, получит драйвер через super(driver).

Также я тут создал метод find, который заменит длинное написание driver.findElement().

Код ниже:

public class BasePage {

    protected WebDriver driver;

    public BasePage(WebDriver driver){
        this.driver = driver;
    }

    public WebElement find(By locator){
        return driver.findElement(locator);
    }
}

Дальше класс самой страницы. Тут я оставил пару методов просто для наглядности, что бы не копипастить весь класс. В итоге создаем конструктор страницы, получаем драйвер, создаем переменные типа By с которыми будем работать, создаем маленькие методы (например заполнить поле, выбрать с селекта), потом создаем метод cardFill() который обьеденит эти методы.

public class NewOrgRegistrationPage extends BasePage{

    public NewOrgRegistrationPage(WebDriver driver) {
        super(driver);
    }

    String url = "http://192.168.1.111:8085/share/page/context/mine/sxg-external-registration";
    By orgRegistrationReasonDropBox = By.name("prop_uxp_orgnRegistrationReason");
    By fullOrgNameField = By.name("prop_uxp_orgnName");


    public NewOrgRegistrationPage selectOrgRegistrationReason(){
        Select selectOrg = new Select(find(orgRegistrationReasonDropBox));
        selectOrg.selectByIndex(1);
        return this;
    }
    public NewOrgRegistrationPage setFullOrgNameField(String orgName){
        find(fullOrgNameField).sendKeys(orgName);
        return this;
    }
    public NewOrgRegistrationPage visit(){
        driver.get(this.url);
        return this;
    }

    public void cardFill(){
        visit();
        selectOrgRegistrationReason();
        setFullOrgNameField("some name");
    }
}

И наконец то сам тест класс

public class CreatingNewOrgTest extends BaseTest{

    @Test
    public void cardFill(){
        NewOrgRegistrationPage page = new NewOrgRegistrationPage(driver);
        page.cardFill();
    }
}

Жду конструктивной критики особенно от пользователя Noksa, так как прошлый раз очень хорошие были замечания.

 

Но помимо критики у меня сразу есть вопросы. 

 

1. Мне кажется что в тестовых классах я не должен иметь возможности делать driver.findElement, driver.click и т.д. Тоесть на прямую обращаться к драйверу. Или я ошибаюсь?

 

2. В архитектуре классов у меня есть также класс SummaryAPI. В лекции что я смотрел, от этого класса неследовались классы BasePage и BaseTest - тоесть в них была реализация чего то общего для этих двух классов, например того же метода find:

 public WebElement find(By locator){
        return driver.findElement(locator);
 }

Я этого к сожелению понять не могу, зачем мне этод метод в тестовых классах? Если я могу его создать в BasePage, что я собстевнно и сделал, так как только в пейджах которые наследуються от этого класса я и буду его использовать. В чем смысл заносить его в SummaryAPI, потом наследовать в BaseTest и в тестовом методе иметь возможность делать find(By name("q")).

Я много где видел советы по созданию класса общего для BasePage и BaseTest. Но что там должно быть? Наведите пожалуйста примеры. Спасибо!




#166538 Наследования

Отправлено автор: Isidor2811 08 июня 2018 - 13:43 в Автоматизированное тестирование

 

Так же, я бы вам советовал сразу писать такую архитектуру, в которой не требуется в конструктор страницы передавать драйвер.

Т.е, в конструктор страницы вообще ничего не следует передавать.

 

Как вариант, использовать статичный драйвер в контейнере ThreadLocal<>.

 

Это моё субъективное мнение.

 

 

Пример с C#, на страницах не требуется объявлять конструктор, он вызывается из базового класса.

При этом все прекрасно бегает в параллельных потоках.

public class NewsPage : BasePage
    {
      ....
    }


public abstract class BasePage
    {
     ...

     protected BasePage()
        {
            Elements.Clear();
            ElementsInBlocks.Clear();
            PageFactory.InitElements(DriverManager.Driver, this, new AFieldDecorator());
        }

Еще раз спасибо за советы. Начал гуглить и нашел вот что https://www.youtube....h?v=zCjNOIp7p3c . Думаю многим пригодиться, так как тут есть 80% ваших советов. Буду разбираться :pardon:




#166520 Наследования

Отправлено автор: Isidor2811 08 июня 2018 - 06:38 в Автоматизированное тестирование

Вам нужно вынести всю логику по работе с драйвером в базовый класс для всех тестов. Всё создание драйвера и его уничтожение будет описано в одном месте.

От него и надо будет наследовать классы тестов.

 

В идеале это должна быть фабрика по созданию нужного драйвера.

В классах тестов не должно быть никакого упоминания о драйвере!

 

Тут я Вас понял! Именно из за того что я создавал драйвер в каждом классе у меня и наследование не получится. 

Фабрики для создание драйверов мне не нужно - работаем только с chrome, поэтому и указал путь на ЖД. Но уже видел ссылку где это делаеться через maven, пересмотрю потом.

И да то, что в тестах не должно быть упоминание о драйвере только сейчас понял. Но так как я только начинаю работать то для меня понимание этого уже плюс)

 

 

 

2) Сейчас у вас заполнение карточки является по сути не тестом, а precondition шагом. 

В той реализации, что у вас есть - у вас все тесты будут зависеть по факту от одного теста. Зависимые тесты - это очень плохо. Если ваш первый тест не будет работать - все остальные тоже не будут работать из-за того, что они не могут выполнить precondition шаг.

 

В идеале, нужно уходить от такого рода шагов. Например, путём создания другого precondition шага, который будет в БД приложения записывать нужные данные, а тест уже будет их использовать.

Таким образом, если создание precondition шага в интерфейсе не будет работать - вы сможете проверить другой функционал, минуя его.

Дело в том что как бы я не хотел сделать тесты независимыми - этого у меня не получиться. Возьмем для примера заполнения этой карточки. От этого теста зависит выполнение всех последующих. В конце теста есть клик на кнопку, после которого отправляеться на емейл ссылка для дальнейшей работы. Поэтому если даный тест не отработает (ссылка не прийдет) то и последуюющие шаги мне выполнять не нужно. Я не смогу начать выполнять тест с 3 или 4 этапа бизнес процесса. Только в такой последовательности. Поэтому даже при запуске, для того что бы проверить например 8 сетод (завершения БП) мне нужно тест запустить с самого начала. 

Поэтому тут к сожалению я не могу не привязываться к другим тестам.

 

Действия на страницах надо выносить не в базовый класс, а следовать PageObject паттерну, и выносить это в отдельные методы на конкретном pageobject'е. А в самих PageObject применять композицию для избежания дублирования кода.

Допустим, есть общее меню для всех страниц - его нужно выносить в отдельный класс (я их называю блоками) и используя композицию вносить его во все pageobject, где он присутствует.

Таким образом, элементы описанные в этом блоке - будут описаны в одном месте, и при их изменении вам нужно будет исправить их только в одном месте, а не на всех страницах.

 

Общее видение PageObject:

 

У вас есть страница Cards. 

Создаёте класс Cards, в нём создаете мелкие методы, которые делают что-то на этой странице.

Потом, если вас это не устраивает - делаете там же общий метод cardFill, который содержит в себе вызовы мелких методов, а не дублирует их логику.

 

А в тесте уже используете этот класс и методы из него. Здесь не нужно наследование.

 

У сейчас прикреплю код с класса OrgCard, это по сути то что вы говорите:

public class OrgCard {

    WebDriver driver;
    WebDriverWait wait;

    public OrgCard(WebDriver driver){
        this.driver = driver;
        this.wait = wait;
    }

    By orgRegistrationReasonDropBox = By.name("prop_uxp_orgnRegistrationReason");
    By fullOrgNameField = By.name("prop_uxp_orgnName");
    By shortOrgNameField = By.name("prop_uxp_orgnShortName");
    By edrpouField = By.name("prop_uxp_orgnEdrpou");
    By indexField = By.name("prop_uxp_orgnAddressIndex");
    By cityTypeDropBox = By.name("prop_uxp_orgnAddressLocationType");
    By cityNameField = By.name("prop_uxp_orgnAddressLocation");
    By streetTypeDropBox = By.name("prop_uxp_orgnAddressStreetType");
    By streetNameField = By.name("prop_uxp_orgnAddressStreet");
    By houseNumberField = By.name("prop_uxp_orgnAddressHouseNumber");
    By headLastNameField = By.name("prop_uxp_headLastName");
    By headFirstNameField = By.name("prop_uxp_headFirstName");
    By headMiddleNameField = By.name("prop_uxp_headMiddleName");
    By headPhoneField = By.name("prop_uxp_headPhone");
    By headEmailField = By.name("prop_uxp_headEmail");
    By headEdrfou = By.name("prop_uxp_headEdrphou");
    By headCertificate = By.name("file_assoc_uxp_headCertificate_0");
    By responsibleLastNameField = By.name("prop_uxp_responsiblePersonLastName");
    By responsibleFirstNameField = By.name("prop_uxp_responsiblePersonFirstName");
    By responsibleMiddleNameField = By.name("prop_uxp_responsiblePersonMiddleName");
    By responsiblePhoneField = By.name("prop_uxp_responsiblePersonPhone");
    By responsibleEmailField = By.name("prop_uxp_responsiblePersonEmail");
    By respEdrfou = By.name("prop_uxp_responsiblePersonEdrphou");
    By respCertificate = By.name("file_assoc_uxp_responsiblePersonCertificate_0");
    By createButton = By.name("save");
    By linkToHead = By.xpath("//input[@class='popupTextField']");



    public OrgCard selectOrgRegistrationReason(){
        Select selectOrg = new Select(driver.findElement(orgRegistrationReasonDropBox));
        selectOrg.selectByIndex(1);
        return this;
    }
    public OrgCard setFullOrgNameField(String orgName){
        driver.findElement(fullOrgNameField).sendKeys(orgName);
        return this;
    }
    public OrgCard setShortOrgName(String shortOrgName){
        driver.findElement(shortOrgNameField).sendKeys(shortOrgName);
        return this;
    }
    public OrgCard setEdrpou(String edrpou){
        driver.findElement(edrpouField).sendKeys(edrpou);
        return this;
    }
    public OrgCard setIndex(String index){
        driver.findElement(indexField).sendKeys(index);
        return this;
    }
    public OrgCard selectCityType(){
        Select selectCityType = new Select(driver.findElement(cityTypeDropBox));
        selectCityType.selectByIndex(1);
        return this;
    }
    public OrgCard setCityName(String cityName){
        driver.findElement(cityNameField).sendKeys(cityName);
        return this;
    }
    public OrgCard selectStreetType(){
        Select selectStreetType = new Select(driver.findElement(streetTypeDropBox));
        selectStreetType.selectByIndex(1);
        return this;
    }
    public OrgCard setStreetName(String streetName){
        driver.findElement(streetNameField).sendKeys(streetName);
        return this;
    }
    public OrgCard setHouseNumber(String houseNumber){
        driver.findElement(houseNumberField).sendKeys(houseNumber);
        return this;
    }
    public OrgCard setHeadLastName(String headLastName){
        driver.findElement(headLastNameField).sendKeys(headLastName);
        return this;
    }
    public OrgCard setHeadFirstName(String headFirstName){
        driver.findElement(headFirstNameField).sendKeys(headFirstName);
        return this;
    }
    public OrgCard setHeadMiddleName(String headMiddleName){
        driver.findElement(headMiddleNameField).sendKeys(headMiddleName);
        return this;
    }
    public OrgCard setHeadPhone(String headPhone){
        driver.findElement(headPhoneField).sendKeys(headPhone);
        return this;
    }
    public OrgCard setHeadEmail(String headEmail){
        driver.findElement(headEmailField).sendKeys(headEmail);
        return this;
    }
    public OrgCard setHeadEdrfou (String edrfou){
        driver.findElement(headEdrfou).sendKeys(edrfou);
        return this;
    }
    public OrgCard uploadHeadCertificate(String path){
        WebElement upload = driver.findElement(headCertificate);
        upload.sendKeys(path);
        return this;
    }
    public OrgCard setResponsibleLastName(String setResponsibleLast){
        driver.findElement(responsibleLastNameField).sendKeys(setResponsibleLast);
        return this;
    }
    public OrgCard setResponsibleFirstName(String responsibleFirstName){
        driver.findElement(responsibleFirstNameField).sendKeys(responsibleFirstName);
        return this;
    }
    public OrgCard setResponsibleMiddleName(String responsibleMiddleName){
        driver.findElement(responsibleMiddleNameField).sendKeys(responsibleMiddleName);
        return this;
    }
    public OrgCard setResponsiblePhone(String responsiblePhone){
        driver.findElement(responsiblePhoneField).sendKeys(responsiblePhone);
        return this;
    }
    public OrgCard setResponsibleEmail(String responsibleEmail){
        driver.findElement(responsibleEmailField).sendKeys(responsibleEmail);
        return this;
    }
    public OrgCard setRespEdrfou (String edrfou){
        driver.findElement(respEdrfou).sendKeys(edrfou);
        return this;
    }
      public void setFieldsOnTheOrgCard() {
        driver.get(ConfigFile.orgCreateUrl);
        selectOrgRegistrationReason();
        setFullOrgNameField(ConfigFile.orgName);
        setShortOrgName(ConfigFile.orgShortName);
        setEdrpou(ConfigFile.add);
        setIndex(ConfigFile.add);
        selectCityType();
        setCityName(ConfigFile.cityName);
        selectStreetType();
        setStreetName(ConfigFile.streetName);
        setHouseNumber(ConfigFile.add);
        setHeadLastName(ConfigFile.headLastName);
        setHeadFirstName(ConfigFile.headFirstName);
        setHeadMiddleName(ConfigFile.headMiddleName);
        setHeadPhone(ConfigFile.add);
        setHeadEmail(ConfigFile.headEmail);
        setHeadEdrfou(ConfigFile.add);
        uploadHeadCertificate(ConfigFile.headCerteficatePath);
        setResponsibleLastName(ConfigFile.respLastName);
        setResponsibleFirstName(ConfigFile.respFirstName);
        setResponsibleMiddleName(ConfigFile.respMiddleName);
        setResponsiblePhone(ConfigFile.add);
        setResponsibleEmail(ConfigFile.respEmail);
        setRespEdrfou(ConfigFile.add);
        uploadRespCertificate(ConfigFile.respCerteficatePath);
        createButtonClick();
    }

}

Тоесть сначала я ищу все обьекты с которыми я буду работать, потом я создаю методы для каждого этого обьекта(заполнения полей, выбор из селекта) и т.д. А потом создаю метод setFieldsOnTheOrgCard(), после вызова которого у меня будет заполняться вся карточка.

 

На сколько я понял вы предлагаете уже в тестах создать метод напримет cardFill() в нем создать обьект OrgCard  и на нем вызвать метод orgcard.setFieldsOnTheOrgCard(); 

 

Для первого класса у меня такая же реализация. А для других классов  я почему то решил что нужно делать наследования. То есть Вы говорите что нужно и для других классов создавать обьект класса OrgCard  и на нем вызвать метод orgcard.setFieldsOnTheOrgCard(), а не делать наследование

 

 

Спасибо за довольно обширный ответ!




#166517 Наследования

Отправлено автор: Isidor2811 07 июня 2018 - 17:19 в Автоматизированное тестирование

Уберите из класса наследника весь дублирующий код.

То есть остаться должен только cardFill.

 

 

Проблема была все таки в том что я опять указал public WebDriver driver во втором классе. Убрав это объявления переменной все заработало. Спасибо! 

 

 

 

 а вот наследовать тесты - плохая практика.

 

Вот здесь я не понял Вас немного. Каждый методу меня это этап бизнес процесса. Вот cardFill  - это заполнение карточки заявления. В итоге я хочу на одной ветке БП создать этот метод (так как я и сделал в классе FirstBP_OrgCreating) , а дальше наследовать все классы от этого класса, и просто вызывать этот метод. Я не могу понять чем это чревато?

 

 

А лучше, все что хотите дублировать вынесите в base-класс, в котором будут только общие вещи и ни одного теста. И оба класса отнаследуйте от него, а тесты уже в них пишите. 

 

Дело в том что вот этот метод (заполнения карточки заявления будет общий для 10 тестов (10 веток БП)) Что измениться если я вынесу этот метод в base-class и буду наследоваться от него, а не от первого тестового класса? 

 

 

 




#166512 Наследования

Отправлено автор: Isidor2811 07 июня 2018 - 14:38 в Автоматизированное тестирование

Привет всем. Есть небольшая проблема.

 

У меня есть класс (кусок кода представлен ниже)

public class FirstBP_OrgCreating {

    public WebDriver driver;
    public WebDriverWait wait;
     
    @BeforeClass
    public void setUp(){
        System.setProperty("webdriver.chrome.driver","E:\\chromedriver.exe");
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        wait = new WebDriverWait(driver,20);
        ConfigFile configFile = new ConfigFile();
        configFile.initializeAllField();
    }

    @Test(priority = 0)
    public void cardFill() throws InterruptedException {
        OrgCard orgcard = new OrgCard(driver);
        orgcard.setFieldsOnTheOrgCard();
        PopUpMessage popUpMessage = orgcard.createButtonClick();
        popUpMessage.getLinkFromPopUp();
   }

В этом классе есть 3 метода, которые я хочу использовать в классе №2, один из этих методов cardFill().

 

Код второго класса ниже.

public class OrganizationCabinetReject extends FirstBP_OrgCreating {

    public WebDriver driver;
    public WebDriverWait wait;

    @BeforeClass
    public void setUp(){
        System.setProperty("webdriver.chrome.driver","E:\\chromedriver.exe");
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        wait = new WebDriverWait(driver,20);
        ConfigFile configFile = new ConfigFile();
        configFile.initializeAllField();
    }

    @Test(priority = 1)
    public void cardFill() throws InterruptedException {
        super.cardFill();
    }

В итоге я получаю NullPointerException

 

 
java.lang.NullPointerException
at OrgCard.setFieldsOnTheOrgCard(OrgCard.java:157)
at FirstBP_OrgCreating.cardFill(FirstBP_OrgCreating.java:32)
at OrganizationCabinetReject.cardFill(OrganizationCabinetReject.java:30)
.....
.....
 
где 157 строка это driver.get(ConfigFile.orgCreateUrl);
 
Как сделать это правильно?
 

 

 




#166390 Автоматизация больших бизнес процессов

Отправлено автор: Isidor2811 30 мая 2018 - 08:36 в Автоматизированное тестирование

1. Селениум - это библиотека, позволяющая эмулировать Ваши действия в браузере, а testNG - делает из Ваших методов "тесты". Но если абстрагироваться от этого, Ваш код это просто обычный код на выбранном Вами ЯП (в данном случае Java) со всеми вытекающими из этого возможностями. 

Поэтому на Ваш первый вопрос, ответ - да, Вы можете создать объект другого класса и использовать его методы.

Или можете сделать их статичными и использовать их без создания объекта.

 

2. Не претендую на то, что мой подход самый-самый правильный. но в моём понимании, в xml'ке должны быть только такие тесты, порядок выполнения которых не принципиален. 

А по поводу if'а - если Ваша цель проверить две разные ситуации - то, на мой взгляд, это все же должно быть два отдельных теста (вроде registerOrgCabinetWithApprove и registerOrgCabinetWithReject) . Даже если они во многом похожи - похожую часть можно в отдельный метод вынести (это же Java, почему нет?).

И еще раз спасибо! Это то что я хотел услышать, теперь со спокойной душой пойду переделывать то что уже "насоздавал", хотя подозреваю что с нуля буде проще написать.




#166389 Page object model, Maven и еще пару вопросов

Отправлено автор: Isidor2811 30 мая 2018 - 08:32 в Автоматизированное тестирование

 

Ссылок, к сожалению, нет.

 

Условный пример (это не полноценный PageManager).

public class PageManagerLite {
    private static WebDriver driver;
    private static WebDriverWait howLong;

    private StartPage startPage;
    private LoginPage loginPage;
    

    public class PageManagerLite(WebDriver driver, howLong) {
        this.driver = driver;
        this.howLong = howLong;
    }

    private StartPage startPage() {
        // создаем и запоминаем страницу, если она ещё не создавалась
        startPage = startPage == null ? new StartPage(driver, howLong) : startPage;
        return startPage;
    }

    private LoginPage loginPage() {
        // создаем и запоминаем страницу, если она ещё не создавалась
        loginPage = loginPage == null ? new LoginPage (driver, howLong) : loginPage;
        return loginPage;
    }
}

// в методе postLinkClick
public LoginPage postLinkClick() {
    // что-то делается
    return pages.loginPage(); // для этого нужно, чтобы страницы знали про PageManager, т.е. при их создании надо и на него ссылку им передавать
}

// В классе тестов

private PageManagerLite pages;

public void init() {
    pages = new PageManagerLite(driver, howLong);
}

public void Method1(){
    driver.get("https://www.ukr.net/");
    pages.startPage().postLinkClick();
    pages.loginPage().setLogin("UserName");
}

Спасибо!




#166384 Автоматизация больших бизнес процессов

Отправлено автор: Isidor2811 30 мая 2018 - 06:38 в Автоматизированное тестирование

createOrgTest() - это уже отдельный метод. Сейчас он у вас запускается один раз, первым приоритетом.

Можно просто убрать аннотацию @Test и поставить вместо неё @BeforeMethod. Тогда перед выполнением каждого теста в этом классе - будет вызываться createOrgTest() и делать вам "первый шаг БП".

Если тесты, которым нужен этот шаг - в разных классах, то просто вызывайте в коде тех тестов первой строкой метод createOrgTest() (в этом случае аннотация @BeforeMethod уже не требуется, можно оставить @Test для отдельной проверки этого процесса). 

 

Тогда еще одно уточнение, даже наверное два.

 

1. Кроме первого метода, у меня есть еще много которые будут повторяться каждый раз, например

 - заполняю поля карточки и кликаю на кнопку "Отправить" (метод 1)

 - проверяю почту на наличия письма, открываю его и сравниваю текст письма с ожидаемым результатом. (метод 2)

 - открываю ссылку в письме и подписываю документ который открылся. (метод 3)

..... метод (N)

 

То есть у меня например будет 4-5 методов которые всегда нужно вызывать для разных веток БП (так как на данном этапе нет никаких ветвлений в БП). А дальше идет метод который отличается от того что например был в пред идущей ветки БП.

 

В пред идущей ветке я подписал документ и БП пошел в одном направлении, а тут я отклонил документ и БП пошел по другому пути.

 

А теперь само уточнение: В первом класcе (Class1), я создаю все эти методы, аналогично тому, что я показал выше (то есть у меня будет "простыня"), а дальше например в классе (Class2) я создаю метод в котором создаю обьект класса Class1 и вызываю метод который мне нужен с этого класса?

 

2. Тут вопрос уже по testng

 

Есть первая ветка БП. Есть два класса которые проверяют эту ветку. В каждом классе 8 методов. 5 первых абсолютно одинаковые(это то что я спрашивал в первом уточнении) а 6 метод у меня идет с ветвлением (там можно либо отклонить, либо подтвердить действие) и от этого уже нужно выполнить либо метод 6,7 либо метод 7,8

 

 Код метода ниже:

@Parameters({"isFull"})
    @Test(priority = 4)
    public void registerOrgCabinet(String isFull) throws InterruptedException, AWTException {
        driver.get(ConfigFile.loginCabinetURL);
        Login login = new Login(driver,wait);
        login.setUserName(ConfigFile.loginVORVDEIR);
        login.setPassword(ConfigFile.passwordVORVDEIR);
        login.logInButtonClick();
        TaskList taskList = new TaskList(driver,wait);
        taskList.requestAndPapersLeftMenuButtonClick();
        taskList.viewAllSearchFieldsButtonClick();
        taskList.setTaskNameSearchField(Variables.getOrgName());
        taskList.searchButtonClick();
        taskList.taskLinkClick();
        Signing signing = new Signing(driver,wait);
        signing.contentWait();
        taskList.takeToWorkButtonClick();
        signing.contentWait();

        if(isFull.equals("1")) {
            taskList.approveButtonClick();
        }
        else {
            taskList.setRejectReasonField();
            taskList.rejectButtonClick();
        }
    }

Можна не обращать внимание на все что выше блока if(). 

 

Дальше сразу покажу код testng.xml

<classes
            <class name="FirstBranch_YES_YES">
                <methods>
                    <include name="initialize"/>
                    <include name="cardFillYesYes"/>
                    <include name="emailCheckForECP"/>
                    <include name="signByHead"/>
                    <include name="emailCheckAfterECPByResp"/>
                    <parameter name="isFull" value="1">
                    <include name="registerOrgCabinet"/>
                    <include name="emailCheckAfterApproveDEIRByHead"/>
                    <include name="emailCheckAfterApproveDEIRByResp"/>
                    </parameter>
                </methods>
            </class>
        </classes>

И так, поясню как я это вижу. В testng.xml я запускаю методы в том порядке котором идет БП. Дальше в методе registerOrgCabinet я передаю параметр (либо 1 - подтверждаем и выполняем методы emailCheckAfterApproveDEIRByHead и emailCheckAfterApproveDEIRByResp, либо 0 - и мне тогда нужно выполнить методы emailCheckAfterRejectDEIRByHead и emailCheckAfterRejectDEIRByResp)

 

Таким образом полный testng.xml выглядит так:

<classes
            <class name="FirstBranch_YES_YES">
                <methods>
                    <include name="initialize"/>
                    <include name="cardFillYesYes"/>
                    <include name="emailCheckForECP"/>
                    <include name="signByHead"/>
                    <include name="emailCheckAfterECPByResp"/>
                    <parameter name="isFull" value="1">
                    <include name="registerOrgCabinet"/>
                    <include name="emailCheckAfterApproveDEIRByHead"/>
                    <include name="emailCheckAfterApproveDEIRByResp"/>
                    </parameter>
                </methods>

                 <methods>
                    <include name="initialize"/>
                    <include name="cardFillYesYes"/>
                    <include name="emailCheckForECP"/>
                    <include name="signByHead"/>
                    <include name="emailCheckAfterECPByResp"/>
                    <parameter name="isFull" value="0">
                    <include name="registerOrgCabinet"/>
                    <include name="emailCheckAfterRejectDEIRByHead"/>
                    <include name="emailCheckAfterRejectDEIRByResp"/>
                    </parameter>
                </methods>

            </class>
        </classes>

Но есть подозрения что я сделал не так как надо. Может надо было два метода делать и не делать блок if, или средствами testng это можно сделать по другому

 

Извините, что так много текста вышло, но если я пойму для себя эти два момента, то дальше все станет намного проще. 




#166381 Page object model, Maven и еще пару вопросов

Отправлено автор: Isidor2811 30 мая 2018 - 06:01 в Автоматизированное тестирование

Последний вариант. Создаете объект страницы и сохраняете в него то, что вернет startPage.postLinkClick().

 

Альтернативный вариант - сами объекты страницы - статичные объекты какого-нибудь отдельного класса. Тогда postLinkClick будет менять соответствующий статичный объект и его же и возвращать.

Тогда в самом тесте - просто обращаетесь сразу к объектам соответствующих страниц.

Но это костыль, лучше уж сделать полноценный PageManager и взаимодействовать со страницами через него.

 

Спасибо большое, вроде разобрался. Может у вас есть ссылки на какие то исходники, где есть написанные тест кейсы с использованием page object, или что то в єтом духе. Буду очень признателен. 




#166375 Page object model, Maven и еще пару вопросов

Отправлено автор: Isidor2811 29 мая 2018 - 14:13 в Автоматизированное тестирование

Я снова тут, и все еще пытаюсь разобраться с page object и возвращением объектов страницы.

Есть такой вот класс StartPage. В этом классе я определяю объект с которым буду работать и метод для него. Это класс для главной страницы почтового сервиса https://www.ukr.net/

 

Насколько я понял если после нажатия на ссылку никакого перехода не было бы, то мне нужно было бы возвращать обьект этой же страницы тоесть так: return this;

public class StartPage {

    private final WebDriver driver;
    private final WebDriverWait howLong;

    public StartPage(WebDriver driver, WebDriverWait howLong){
       this.driver = driver;
       this.howLong = howLong;
    }

    By postLink = By.linkText("Пошта");

    public LoginPage postLinkClick(){
        howLong.until(ExpectedConditions.elementToBeClickable(postLink));
        driver.findElement(postLink).click();
        return new LoginPage(driver,howLong);
    }
}

Но так как при нажатии на ссылку я перехожу уже на другую страницу, то мне нужно возвращать обьект страницы на которую будет переход return new LoginPage(driver,howLong);

 

Теперь я создаю метод Method1 с аннотацией @Test уже в другом классе (там где у меня будут все тестовые методы)

@Test
public void Method1(){
  StartPage startPage = new StartPage(driver, howLong);
  driver.get("https://www.ukr.net/");
  startPage.postLinkClick();
}

В этом классе я создаю обьект класса StartPage и вызываю метод startPage.postLinkClick();

 

И тут то что я не понимаю. Я вызвал этот метод, он мне возращает обьект на страницу LoginPage, мне в этом методе нужно создать обьект даного класса? Другими словами, как мне теперь взаимодействовать с обьектами на странице LoginPage? Тот обьект что мы только что получили после вызова метода startPage.postLinkClick(), как с ним работать?

 

Или мне нужно было сразу создать два обьекта, а потом уже работать с "модифицированым"? Типа так:

@Test
public void Method1(){
  StartPage startPage = new StartPage(driver, howLong);
  LoginPage loginPage = new LoginPage(driver, howLong)
  driver.get("https://www.ukr.net/");
  startPage.postLinkClick();
}

Этот момент не могу понять, поэтому и сама концепция возвращение обьектов не вкладываеться в голове. Поясните пожалуйста.

 

Update:

Или вот так делать?

 public void Method1(){
        StartPage startPage = new StartPage(driver, howLong);
        driver.get("https://www.ukr.net/");
        LoginPage loginPage = startPage.postLinkClick();
        loginPage.setLogin("UserName");
    }



#166374 Автоматизация больших бизнес процессов

Отправлено автор: Isidor2811 29 мая 2018 - 13:20 в Автоматизированное тестирование

Всем еще раз привет!

Только учусь - так что не судите строго.

 

И так...вопрос вот в чем. Имеется очень длинный бизнес процесс (дальше БП). Код например заполнения карточки документа прикрепляю ниже:

@Test(priority = 1)
    public void createOrgTest() throws InterruptedException {
        driver.get(ConfigFile.createCabinetURL);
        OrganizationCabRegister orgCabReg = new OrganizationCabRegister(driver,wait);
        orgCabReg.selectOrgRegistrationReason();
        orgCabReg.setFullOrgNameField(Variables.getOrgName());
        orgCabReg.setShortOrgName(Variables.getOrgName());
        orgCabReg.setEdrpou("33"+ConfigFile.addToName);
        orgCabReg.setIndex("0011"+ConfigFile.addToName);
        orgCabReg.selectCityType();
        orgCabReg.setCityName("Вінниця"+ConfigFile.addToName);
        orgCabReg.selectStreetType();
        orgCabReg.setStreetName("Келецька"+ConfigFile.addToName);
        orgCabReg.setHouseNumber("32"+ConfigFile.addToName);
        orgCabReg.setHeadLastName(Variables.getHeadLastName());
        orgCabReg.setHeadFirstName(Variables.getHeadFirstName());
        orgCabReg.setHeadMiddleName(Variables.getHeadMiddleName());
        orgCabReg.setHeadPhone("+38066545574"+ConfigFile.addToName);
        orgCabReg.setHeadEmail(ConfigFile.headEmail);
        orgCabReg.setResponsibleLastName(Variables.getResponsibleLastName());
        orgCabReg.setResponsibleFirstName(Variables.getResponsibleFirstName());
        orgCabReg.setResponsibleMiddleName(Variables.getResponsibleMiddleName());
        orgCabReg.setResponsiblePhone("+3877447755"+ConfigFile.addToName);
        orgCabReg.setResponsibleEmail(ConfigFile.respEmail);
        orgCabReg.createButtonClick();
        orgCabReg.setLinkToHead();
    }

Заполнение этой карточки это всегда первый шаг БП, дальше уже идет проверка, отклонение и т.д. То есть мне этот метод нужно использовать много раз, для разных веток БП. Как правильно это сделать?

 

 

У меня сейчас просто копитаст в этого куска в разные классы. Так конечно нельзя, а как правильно?

Вынести этот метод в отдельный класс? 

 

Хочу что бы всего один екземпляр этого кода был, что бы случае изменений быстро поправить в одном месте.

 

Надеюсь что понятно изложил. Буду рад помощи!

 

 

 

 




#166201 Page object model, Maven и еще пару вопросов

Отправлено автор: Isidor2811 15 мая 2018 - 06:12 в Автоматизированное тестирование

 

2)Ты мешаешь неявные Implicit  и явные Explicit(WebDriverWait и ExpectedCondition) ожидания. Поэтому получается ерунда
 
 

 

Микс явных и неявных ожиданий к концепции ПО отношения не имеет. А почему это плохо - уже на всех конференциях доложили и во всех блогах написали, гуглите.

 

Хоть убейте не могу понять где я делаю микс. Согласно этой ссылке я использую только явные ожидания https://kreisfahrer....ozhidaniya.html

 

а вот собстевенно код от туда 

Более предпочтительно использовать WebDriverWait и ExpectedCondition:
WebDriver driver = new FirefoxDriver();
driver.get("http://some_url");
WebElement dynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By.id("dynamicElement_id")));

Если я что то не понял, ткните пожалуйста носом на ссылку, а то это довольно таки важная тема




#166200 Page object model, Maven и еще пару вопросов

Отправлено автор: Isidor2811 15 мая 2018 - 06:06 в Автоматизированное тестирование

Почему любой экшн-метод пейдж-обжекта должен возвращать пейдж-обжект станет понятно как только в тесте появится второй ПО.

ПО? извините за тупость, но розшифруйте пожалуйста аббревиатуру 

А то я и прям не понимаю зачем возвращать что то, если метод просто делает какое то действие. И набор таких методов даст мне проверку тест кейса




#166190 Page object model, Maven и еще пару вопросов

Отправлено автор: Isidor2811 14 мая 2018 - 08:42 в Автоматизированное тестирование

Всем привет! 

 

Начал изучать автоматизацию в тестировании, и хочется с самого начала делать все правильно, поэтому изучил Page object model, и пока читал но не практиковал, то все было понятно, но когда начал писать код, то немного запутался.

 

Сейчас напишу как я это вижу с кусками кода.

 

1. Создаю класс MainPage в котором будут храниться локаторы с которыми я буду работать. Для примера создал myAccountButton и signUpButton. 

2. Создаю конструктор для инициализации WebDriver и WebDriverWait. 

3. Потом создаю методы.

 

Код ниже. Тут для меня все понятно. Разве что инициализация  WebDriverWait. Для себя я решил, что добавлю ее в конструктор вместе с WebDriver.

И тут первый вопрос! Надо ли это делать - добавлять в конструктор? Или можно с ним (WebDriverWait) работать по другому. Блин..прочитал даже мне стало не совсем понятно, но надеюсь что Вы поймете.

public class MainPage {

    WebDriver driver;
    WebDriverWait howLong;

    By myAccountButton = By.xpath("//div[contains(@class,'col-md-6')]//li[@id='li_myaccount']/a");
    By signUpButton = By.xpath("//li[@id='li_myaccount' and @class='open']//ul//child::li[2]/a");

    public MainPage(WebDriver driver, WebDriverWait howLong){
        this.driver = driver;
        this.howLong = howLong;
    }

    public void clickMyAccountButton(){
        howLong.until(ExpectedConditions.elementToBeClickable(myAccountButton));
        driver.findElement(myAccountButton).click();
    }
    public void clickSignUpButton(){
        howLong.until(ExpectedConditions.elementToBeClickable(signUpButton));
        driver.findElement(signUpButton).click();
    }
}

Дальше: 

Я создаю класс SignUp уже в другом пакете и тут пишу код для самого теста.

 

Вопрос №1. Я создал метод driverStart() с аннотацией @BeforeMethod и там я уже создаю обьект WebDriver driver,  WebDriverWait howLong. 

Это можно делать в этом методе? Или же дальше есть метод signUpTest() и эту инициализацию нужно делать в нем?

 

Вопрос №2. System.setProperty("webdriver.chrome.driver","E:\\chromedriver.exe"); можно прописать в pom.xml?

public class SignUp {

    WebDriver driver;
    WebDriverWait howLong;

    @BeforeMethod
    public void driverStart(){
        System.setProperty("webdriver.chrome.driver","E:\\chromedriver.exe");
        driver = new ChromeDriver();
        howLong = new WebDriverWait(driver,30);
        driver.manage().window().maximize();
        driver.get("https://www.phptravels.net/");
    }

    @Test
    public void signUpTest(){
       MainPage mp = new MainPage(driver,howLong);
       mp.clickMyAccountButton();
       mp.clickSignUpButton();
    }

    @AfterMethod
    public void quiteDriver(){
        driver.quit();
    }

}

Вообщем объяснил немного не так как хотел. Просто сделайте замечания по коду. Хочется по крайней мере начать правильно. Заранее спасибо.