Где выполнять проверки Assert & Verify

Могут ли проверки быть внутри Framework? Например:

@Test
public void firstTest(){
...
card.popup("Имя","12345","verify") //Вызываем метод с заданными параметрами
...
}```
Обращаемся к методу в Framework где:

**Имя** - поле которое хотим проверить
**12345** - значение
**verify** - действие, в данном случае проверка не Assert

В методе я бы мог автоматически из нужного класса выдавать локатор.
Правильно ли это вообще делать и почему (чем это черевато)?

Почему бы и нет. Но я бы посоветовал вам как можно скорее уходить от функциональной нотации, и использовать ООП.
card.getPopup().getField(“Name”).verifyValue(“12345”)

я стараюсь избегать ассертов в page object’ах и frameworke

для меня выстраилась такая картина:
framework - тут все ясно, наше “ядро” для постройки тестов
page object - страницы (там не использую ассертов, т.к. по сути страница не может что либо проверить или знать, как работает тот или иной функционал) она лишь может сделать какое либо действие или вернуть нам другую страницу
test method - а вот он как раз “тестировщик”, который с помощью page object’ов работает с страницами приложения as user from browser. “он” вызывает страницы и проверяет ассертами тот или иной функционал

1 лайк

Если можете поясните, почему это плохо? Где вообще можно об этом почитать, так как в основной книге я такого не припомню.(Шиндлер)

А это разве не очивидно?

  1. Абсолютно не читабельно - вам пришлось расписывать значение всех параметров.
  2. Абсолютно не “писабельно” - что бы узнать какие значения параметра допустимы (“verify”,“type”,“click”) придется лезть в код.
  3. Рано или поздно вам перестанет хватать 3 параметров и их число может начать расти лавинообразно.
  4. Да просто посмотрите в код popup() - я представляю какой там адъ из ифов, кейсов и т.д. Дальше будет хуже.

По той же причине пришлось переписывать Selenium RC :wink:

1 PageObject может быть использован в N тестах. Каждый тест проводит свою уникальную проверку. Допустим вы засунули assert в метод проходящий через M тестов. Зачем M тестам проводить “чужую” проверку? Что будет с M тестами в случае фейла вашего ассерта? Сможете ли вы дать однозначный ответ на вопрос, работоспособен ли функционал, тестируемый конкретным тестом из множества M, если сработал “чужой” ассерт?

Вообще говоря, аргументов “против” очень много. Часть из них уже осветили выше.

Вопрос лежит не в этой плоскости, просто неверно сформулирован.

Если конкретно взять на примере редактирования поля, вот таким образом будет не правильно? Проверки будут проходить мимо, пока их не передашь через параметр.


public class Test {
Card card = new Card();

@Test
public void field(){
...
card.popup("Имя","12345","Edit")
card.popup("Имя","12345","Verify")
...
}
}

...

//Framework
public class Card{

public void popup (String name, String value, String settings){
switch(settings){
case "edit":
...
break;
case "verify":
assertTrue(...)
break;

default:
break;


}
}

тихий ужас.
а что если похожих сущностей как popup будет 10 ? 100 ? у каждого будет копи-паст реализация edit’ов и проверок ?
опять же, все доступные значения для “String settings” надо держать в голове.
в общем, выглядит это как !!! абсолютно не поддерживаемый !!! подход при разработке автотестов.

очень советую почитать/посмотреть доклады/видео на ютубе/etc про Page Object паттерн.

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

@Test
public void field(){
...
card.popup("Имя","12345","Edit")
card.popup("Имя","12345","Verify")
...
}

и

@Test
public void field(){
...
card.popup("Имя","12345","Edit")
assertTrue(elements.name.equals("12345"));
...
}
}

Это действительно можно считать за полноценный ответ по вышеуказанному мной комменту? (Имеется ввиду вот это?)

Коллеги, этот топик постепенно скатывается из обсуждения чего-то «высокого» в обсуждение каких-то антипаттернов в программировании.

Про антипаттерны для программистов написано много интересного… Тем не менее, не все антипаттерны для программирования приложений нужно считать антипатернами для программирования тестов.

Парочка примеров:

  • погуглите что люди пишут про Singleton. Так это паттерн или антипаттерн?
  • А какие аргументы приводят те, кто считает Singleton антипатерном?

Копи-паст… Это конечно же плохо… особенно когда копи-пастится текст локатора, вместо того чтобы завести для локатора переменную, или константу, или поместить в PageObject.
А вот для шагов в коде теста, копи-паст не так уж и плох, в разумных пределах, конечно. Я всегда за то, чтобы вынести повторяющийся код в параметризируемые методы… Вынести в метод – это просто. Но, иногда для этого приходится создавать очень непростые абстракции. Это например паттерн «Шаблонный» метод или «Стратегия». Эти два паттерна избавляют от цепочек if-ов… Я пробовал их использовать, и скажу: ну нет уж… иногда лучше if-ы.

Свое длинное вступление я хочу завершить вот этим чудо видео, которое может помочь в освоении «чистого кода» (да, да который попахивает только шампунем):

А теперь немного по теме:

@mindjin, на самом деле, верно или нет вы пишите код – очень зависит от контекста. Если вы просто хотите написать тест «без задней мысли» :slight_smile: – то выбранный вами подход не верен для Java.

Java – это типизированный язык объектно-ориентированный язык. И код, который на нем пишется должен соответствовать этому стилю. Должны быть классы, методы.
Команды, переданные текстовыми строками, как то «edit» или «verify» – идут вопреки идее языка.

Огромный один единственный метод, который делает всё на свете – говорит о том, что в его коде вы скоро утонете.

Я предлагаю, вместо:

card.popup("Имя","12345","Edit")
card.popup("Имя","12345","Verify")

Создать и вызывать отдельные методы:

card.editName("12345");
card.verifyName("12345");

Таким образом, вы сделаете много маленьких методов, вместо большого кейса. Каждый метод будет решать свою задачу. Вам может показаться то, что писать все в одном методе с огромном кейсе – намного лёгче… это так и есть. Но, в долгосрочной перспективе, подход с методами облегчит поддержку кода.

@mindjin, а хотите теперь я найду аргумент в защиту вашего кода?

Вот представляете, у вас есть внешний Excel файл следующего формата:

Field	Value	Command
Имя	123	Edit
Имя	123	Verify

Если вы хотите чтобы непонимающие в программировании мануальщики писали вам тесты – то вам достаточно написать парсер этого файла, ну что-то по типу (псевдокод):

while (excel.HasNextLine())
{
	columns = excel.ReadNextLine()
	card.popup(columns[0],columns[1],columns[2])
}

Вы вот движок (парсер) напишете один раз, а мануальщики без перекомпиляции страшного кода, будут вам всю жизнь такие Excel’ки писать.

Так работают многие Keyword-Driven фреймворки, например вот этот:

Что-то похожее, я уверен, можно найти и в Robot Framework.

На одном моем проекте был такой парсер. И исторически, он вырос до огромных размеров. Даже, учитывая то, что мы выносили большую часть реализации в отдельные методы. Когда один человек уходил его дебажить… то мы знали, что сегодня он уже не вернётся…

Если вам это не нужно сейчас… то используйте отдельные небольшие, чёткие, конкретные методы, пока судьба не заставит вас писать подобные парсеры.

В свое время люди напридумывали кучу паттернов. И поверьте, это было сделано не спроста. Все они создавались на опыте ошибок / проблем, с которыми мы так или иначе периодически сталкиваемся. Вам ребята объясняют очевидные преимущества / недостатки, но в сухой теории вам вряд ли удастся все понять. Нужно пробовать. И осознание многих вещей к вам придет только со временем, с опытом. А от того, что вы сейчас все поддадите сомнению только из-за того, что не можете этого понять, легче не станет никому. В итоге, тема раздуется до обсуждения смысложизенных проблем, обсасывания все тех же паттернов и т.п. Если хотите в чем-то разобраться - пробуйте, анализируйте, выделяйте плюсы / минусы. Понять на словах не всегда представляется возможным. Особенно, если опыта всего несколько месяцев.

1 лайк

Полностью поддерживаю ответ @ArtOfLife.

Сразу «правильно» всё-всё не сделать. Я думаю, что многие из нас получили опыт, учась на собственных ошибках. Иногда намного эффективнее что-то вначале сделать… проанализировать возникшие по пути проблемы… и исправить их, либо – выбросить все и переписать заново :wink:

2 лайка

Итого:
А. Можно ли функционал проверок выносить за пределы тестов? Ответ: Да

EmailManager.waitForNewEmail(SUBJECT).verifyBodyContains(CONTENT);
table.verifyOrderDescending("Last Name");
alerts.link(ALERT).verifyExists();
sessionTimeout.verifyTextExists("Your session will expire");

B. Можно ли это делать так card.popup("Имя","12345","Verify")? Ответ: Можно, но не нужно :smile:

PS: Кейворды тут не оправдание, их можно реализовать через рефлекшен :wink: Я даже как-то пробовал запилить аналог tafcore-сценариев - особых проблем не припомню.

Спасибо огромное за ответы. Буду исправляться и стараться писать чистый код =)

1 лайк