А еще каждое поле у меня может иметь значение null. В таком случае, FillForm просто не трогает поле на странице, которое советует полю в классе.
Поправлюсь. Допустил ошибку в коде выше.
Вот два примера: Один создает новый класс данных, и следовательно все поля будут null, а потом присваивает значение только полю Name. Следовательно, FillForm заполнит только Name, а все остальные поля не тронет.
Во втором примере GetDefault() возвращает некоторые значения по умолчанию. В следующих двух строчках, я лишь меняю то, что мне важно для теста, а все остальное будет как есть.
/// 1
PaymentFormData formWithName = new PaymentFormData() // all fields are null by default
formWithName.Name = "Hello World";
PaymentPage page = new PaymentPage();
page.FillForm(formWithName);
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// 2
PaymentFormData formWithName = new PaymentFormData.GetDefault() // all (or some) fields will have user-predefined values
// Change only the values which are important
formWithName.Name = "Hello World";
formWithName.Bablo = 50;
PaymentPage page = new PaymentPage();
page.FillForm(formWithName);
Подход хороший, но… Как быть в тех случаях, когда необходимая последовательность заполнения формы сильно варьируется в зависимости от тест-кейса (автопопулейты, подгружаемые контролы и т.д.)?
Это прекрасно, только возникают у меня подозрения, что в .fillForm() поля дата модели жестко привязаны к вебэлементам. И если приходит одно поле, а остальные 19 null, то мы получаем 19 лишних проверок на Null. Поправь меня, если ошибаюсь.
Везде есть свои исключения. Если есть такая форма, где один элемент, зависит от другого, то я думаю, что можно разбить эту форму на группы, типа маленьких формочек, которые составляют одну.
Да, вместо 1-го будет два или 3 вызова, тут нужно смотреть на конкретную ситуацию.
У меня был такой кейс: есть форма создания пользователя.
У пользователя около 30 полей, большая часть из которых не обязательная. И можно сделать привязку между пользователей системы и Active Directory.
В случае создания обычного пользователя, нужно заполнять поля Password/Confirm
В случае Active Directory пользователя – нужно ввести логин, поставить галочку на Active Directory, дождаться, пока система подгрузит данные из AD, и продолжить заполнение.
В этом случае, FillForm просто реагировал на установку IsActiveDirectoryUser – и вел себя по-разному в обоих случаях.
Я собственно сздал данный топик, из желания оптимизировать данную операцию.
Из идей у меня есть 2 варианта. плохой и чуть лучше
Плохой, это использовать рефлекшены. Второй - на хеш мапах. На текущий момент он кажется чуть более практичным, но коммуна в праве все поставить на свои места
Итак, в качестве датаМодели используется мапа. Допустим нужно засетить одно поле amount.
@When("bla-bla set amount ="100500")
public void setCashContractAmount(String amount){
//создаем объект DTO
HashMap<String,String> dtoMap = new HashMap<String,String>();
//ложим туда связку имя необходимого поля, и значение.
//Для имен полей, я создал enum ContractFields внутри page, содержащий имена. Просто чтобы избежать риска ошибки при вводе.
dtoMap.put(CashContractsPage.ContractFields.AMOUNT.get(), amount);
//отдаем пейдже мапу
cashContract.fillForm(dtoMap);
}
// в самом pageObject нам нужно в конструкторе стрраницы создать еще одну мапу, в которую мы кладем связку имени и WebElement.
public CashContractsPage(WebDriver driver) {
super(driver);
webElementsMap.put(ContractFields.AMOUNT.get(),amount);
}
}
// ну и дальше просто мапим мапу на мапу =))
public void fillForm(HashMap<String,String> dtoMap) {
for(String elementName:dtoMap.keySet()){
webElementsMap.get(elementName).sendKeys(dtoMap.get(elementName));
}
}
[quote=“Zvonov, post:14, topic:3478”]
Второй - на хеш мапах.
[/quote]Где то я уже видел попытку подобного подхода, то ли тут, то ли на http://software-testing.ru
Проблема будет в том, что форма может состоять не только из одних инпутов, это могут быть и чекбоксы/ddl/радиобаттоны/etc или сложные контролы типа datepicker - тут одним sendKeys не отделаешься. Плюс в процессе заполнения формы часто приходится вставлять вейты, ждать стейлов, кликать на инпуты и творить прочее непотребство.
Есть еще шанс побороться. Мы создаем типизацию вебэлементов (Input, checkbox, etc) наследуем их от WebElement. Который расширяем методом setData(). А его, в свою очередь реализуем по своему для каждого типа.
Это будет работать, только если условия будут практически идеальные. На деле всегда находятся контролы, поведение которых нестандартно, тогда идут в ход всяческие хаки и трюки. А поведение форм довольно запутано и не прямолинейно.
Вот пример “покладистой” формы - тут вопросов нет.
А вот “вредной”. Форма состоит из друх фреймов (благо что автосвитч реализован), которые взаимодействуют друг с другом в процессе заполнения. И не дай бог убрать какой-нибудь, с виду не нужный вейт или клик, либо изменить порядок действий, даже в тех местах, где необходимость последовательности не очевидна (серия кликов)…
можно вопросик касательно фразы “благо что автосвитч реализован”.
Каким образом отслеживается в каком фрейме искать элемент? Можете в двух словах принцип реализации описать?
У меня в одном из веб-проектов активно используются iFrame и всплывающие/исчезающие окна. Пока переключение между ними сделано топорно, но хочется сделать прозрачно для кодера
@vmaximv и @joemast отвечать лучше через создание новой темы от комментария (справа от комментария появляется ссылка “Ответить в новой теме”), так как это уже совсем другое обсуждение
А часть из них лежит еще и на фрэймах! Я экспериментировал на этом и этом, и сразу же столкнулся с описанной проблемой. А ситуацию усугубляет еще и то, что экземпляр, реализующий WedDriver, видит только активную страницу (окно/вкладку) или фрэйм.
Хотелось бы иметь возможность разбивать страницу на такие блоки, которые работающий тест мог бы запоминать и работать с ними напрямую, без вызовов driver.switchTo().window(somehandle) или driver.switchTo().frame(frameIdentity).
Я тоже как-то пытался прикрутить такую штуку у себя для .NET, выбрал правильные инструменты, но пошел не совсем по правильному пути, так что не довел дело до конца. А сейчас понял, где оступился.
да, я тоже думал про AOP, но у меня к нему предвзятое отношение, основанное на прочтении всяких нелестных отзывов Лестные тоже были, но “осадочек остался”.
Поэтому я первым делом рассматриваю альтернативные варианты. А именно, применение паттерна Proxy и ему подобных. То есть суть в том же, что и в AOP: при обращении к элементу, обращение происходит к Proxy-объекту, который делает нужные действия до передачи управления собственно WebElement-у. Если с ними не получится, тогда буду AOP пробовать.
Пока активно этот вопрос не исследую, т.к. с серьезными проблемами топорного решения ещё не столкнулся в виду начального этапа развития автоматизации тестирования, на котором сейчас находятся мои проекты
Давайте действительно попросим модератора перенести сообщения не по теме топика в отдельную тему. Может я чего то не понимаю, но у меня это реализовано без всяческих прокси, рефлекшенов и т.д.
А что происходит при фэйле? Мне надо протестировать админку с кучей форм в которых есть много однотипных полей и если фэйл происходит в каком-то поле, то не факт, что его будут чинить. Что же получается, нужно переписывать тест?
Или например такая ситуация. бэкенд косячит и иногда дату не сохраняет на форме. И повторяться это может на любой из форм. Но вот воспроизвести это пока не удается. То есть все тесты могут быть как фэйл так и пасс. Что в этом случае делать?
@vmaximv Я имел ввиду пока что не будут чинить. Что делать в таком случае? Баг отложен на 2 месяца, но тестировать нужно продолжать дальше тестировать форму. Переписывать тесты тогда?
И опять же могут сказать, у нас есть сейчас дела по важнее чем баг повторяющийся через раз. Тогда что делать?
Разбить тесты разных форм на независимые. Если для заполнения формы #2 нужно заполнить форму #1,
то поступаем так:
создаем тест(ы) на заполенение формы #1. Возможно, с применением softAssert-ов.
создаем метод, который заполняет форму #1 БЕЗ ее тестирования. Его цель - заполнить форму во что бы то ни было. Если в процессе ее заполнения возникают ошибки, в этот метод можно запихнуть костыли по их устранению с варнинг-месседжами в логи: повторное заполнение, заполнение через джава-скрипт и тп. Далее использовать этот метод как пререквизит к тестированию формы #2 (и других зависимых форм). После устанения багов просто убираем эти костыли.
есть и другие, даже более предпочтительные варианты, но их выбор зависит от системы, с которой вы работаете (отправка пост-запроса от имени странички вместо заполнения полей, внесение изменений в базу, использование готовой конфиграции, в которой форма #1 уже заполенена и тп)
Выяснить как часто возникает такая ситуация. Исходя из этой цифри определить число запусков N, при котором ошибка точно воспроизведется. Далее создать отдельный тест на заполнение такого поля, и запускать данный тест с параметрами invocationCount = N и successPercentage = 100 (если у Вас testNG, для других раннеров ищите похожие техники).
Для предотвращения падения других тестов, пойти по способу описанному выше - создать отдельный метод по заполнению поля с датой, который будет заполнять дату X раз, пока не получится.