Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Для первой версии - неплохо
- но есть еще над чем поработать)
- */
- static {
- Configuration.remote = Config.REMOTEHOST;
- }
- /*
- https://github.com/codeborne/selenide/blob/04561fd8e68ef8b475eecf0c8bdce767db57438d/src/main/java/com/codeborne/selenide/Configuration.java
- http://joxi.ru/5md7jYwtvlRxOr
- можно вполне обходиться и без кода Configuration.remote = ...;
- просто при запуске использовав "-Dremote=..."
- понимаю, что так удобнее - при запусках из-под IntelIJ Idea, да и чтобы еще и лишего не писать
- судя по Config.REMOTEHOST - ты занулял эту строку перед выкладыванием в репозиторий
- ну мог бы уже и null прописать - чтобы я у себя твой проект без проблем запускала - безо всяких правок)
- я бы все же - сам проект оставила без лишних вещей - типа класса Config и кода Configuration.remote = Config.REMOTEHOST;
- прежде всего для того - чтобы понимать глядя на решение - что вот для решения такой-то задачи - надо то-то и то-то
- ведь реально - для конкретно этой решения задачи - этого делать не нужно
- а чтобы тебе было по-прежнему удобно (или как ты там про лень писал что-то) - ну напиши bat-файл в 2-3 строки
- и запускай проект где тебе нравится)
- в данном случае - я не настаиваю - чтоб избавился от Config и кода Configuration.remote = Config.REMOTEHOST;
- т к в общем - более ничего в проекте не пришлось под это твое желание подпиливать
- т е - все аккуратно получилось
- у нас есть задача - чтоб ты на выходе получил проект
- который решает такую-то задачу
- и это решение было если не идеальным, то достаточно хорошим)
- если этой цели твои ноу-хау не мешают - то ОК - так даже интереснее
- а если будут засорять решение - буду возражать)
- пока норм)
- оставляй если хочешь
- */
- *****************************
- public class EndToEndToDoMVCWorkflow {
- ...
- @Test
- public void endToEndToDoMVCWorkflow() {
- /*
- вспомни про conventions для имен тест-классов
- https://docs.google.com/document/d/13dNyFGbI7mV22UUhH8E0LJ7SzabAmX7Bw7VCHScYfiU/edit#bookmark=id.bligsp5b94xo
- в тест-классе могут быть не только EndToEnd тесты, но и еще какие-то другие
- потому информацию об этом выносить в имя тест-класса - не стоит
- в общем-то, понять - что это е2е сценарий - можно просто глядя на код
- потому - вообще не стоит в именах тест-класса или тест-метода это подчеркивать
- помимо того, часто информацию о том, что это smoke покрытие - тоже, в имена тест-классов и тест-методов не выносят
- далее по курсу будем разбирать категории - вот там как раз это можно и полезно указывать
- */
- ***************************************
- public void endToEndToDoMVCWorkflow() {
- open("https://todomvc4tasj.herokuapp.com/");
- /*
- тут было бы полезно пропустить строку - чтобы отделить открытие приложения от уже тестируемых действий
- */
- add("1");
- edit("1", "5");
- /*
- тут более полезным был бы код edit("1", "1 edited");
- далее по тексту таски было бы яснее - что это такое за таска
- edit("1"... - проверяет предыдущую операцию, это ок
- после edit - нет проверки, ни просто проверки, ни косвенной через действие
- */
- open("https://todomvc4tasj.herokuapp.com/#/active");
- /*
- пользователь выполняет переход на другой фильтр - не через открытие урла,
- а через клик на нужной линке
- и если мы это действие тестируем (а мы его тестируем = это важная функциональность)
- то и мы должны делать клик на линке
- */
- assertTasks("5");
- /*
- вспомни нашу переписку в слеке сегодня
- было в списке - таска "5"
- перешли на другой фильтр
- стало в списке - таска 5
- то ли ок переход на фильтр работает, то ли вообще ничего не делает
- обеспечь - чтобы было-стало - отличалось
- */
- delete("5");
- /*
- поторопился)
- можно было под конец это сделать )
- понимаю, хотелось дальше работать со списком,
- в котором только одна таска
- т к проверки через действия только так и получится применять...
- но есть и другой способ
- вот закомплитил бы таску еще на all фильтре - на этом фильтре получил бы пустой список тасок
- да, вижу - ниже уже покрывал complete
- а complete all - вообще не покрыл
- вот и решение
- после delete - нет проверки
- следующая операция не проверяет delete
- */
- add("2");
- editCanceled("2", "333");
- /*
- тут тоже можно было бы
- editCanceled("2", "2 edit cancelled");
- чтобы и тестовые данные поясняли код
- */
- toggle("2"); //complete
- /*
- нет проверки
- */
- open("https://todomvc4tasj.herokuapp.com/#/completed");
- /*
- тут тоже переход на фильтр надо реализовать
- через клик на линке
- */
- assertTasks("2");
- toggleAll(); //reopen all
- /*
- лучше в е2е покрой reopen, а не reopen all
- т к у reopen - приоритет выше, чем у reopen all
- прежде всего потому - что операция reopen более востребована
- нет проверки после действия
- */
- open("https://todomvc4tasj.herokuapp.com/#/");
- /*
- тут тоже переход на фильтр надо реализовать
- через клик на линке
- */
- assertTasks("2");
- toggle("2"); //complete
- /*
- если прислушаешься к советам - и покроешь complete all выше по сценарию
- и delete не будешь делать раньше времени
- то сможешь обойтись без второго использования complete
- в рамках smoke - нужно покрыть высокоприоритетные операции лишь единожды
- с add так не выйдет
- но вот с остальными операциями - точно выйдет
- еще в рамках этого е2е - стоит единожды покрыть проверку счетчика активных тасок
- т к этот счетчик - работает всегда и должен после любой операции отражать реальное положение дел
- не смотря на его не высокий приоритет - с учетом того, что он работает всегда -
- раз стоит покрыть в е2е сценарии, реализующем smoke покрытие
- */
- clearCompleted();
- assertNoTasks();
- }
- /*
- анализируем покрытие
- all
- add
- edit
- active
- delete
- add
- editCanceled
- complete
- completed
- reopen all
- all
- complete
- clearCompleted
- complete - можно было бы покрыть единожды
- вместо reopen all - покрыть reopen - как более высокоприоритетную операцию
- где-то единожды покрыть проверку счетчика активных тасок
- а в целом - да, верно выделил - что стоит покрывать
- и неплохо использовал неявные проверки через действия
- стоит равномернее распределить операции между фильтрами
- такое равномерное распределение улучшит вероятности по нахождению таких проблем -
- когда на одном из фильтров операции над тасками выполняются с ошибками
- в данном случае
- на all - покрыли 4 операции
- на active - тоже 4
- а на completed - лишь одну
- возможно, идеально распределить операции не получится
- но точно можно равномернее
- */
- *****************************
- private void assertNoTasks() {
- tasks.shouldBe(empty);
- }
- /*
- то, что в коде тест-класса сначала расположил тест-метод, а уже затем вспомогательные методы - это ОК
- можно было бы еще более упорядочить код
- и тем самым облегчить его восприятие
- идем от общего к частному
- сначала - static initialization block
- потом - тест-метод
- потом - переменная tasks (поторая будет использоваться во многих вспомогательных методах)
- потом - вспомогательные тест-методы
- и они идут в определенном порядке
- отдельно - ассерты
- отдельно - действия
- сначала - базовые, затем - остальные
- рядом - похожие или противоположные штуки
- и тогда код будет читаться максимально просто - при том же наборе методов и переменных
- изучая такой код - не придется бегать туда-сюда
- просто прочитал код и все
- хотя технически - это не имеет значения - что в каком порядке
- */
- ***********************************
- private void edit(String e1, String e2) {
- tasks.find(exactText(e1)).doubleClick();
- tasks.find(cssClass("editing")).find(".edit").setValue(e2).pressEnter();
- }
- private void editCanceled(String e1, String e2) {
- tasks.find(exactText(e1)).doubleClick();
- tasks.find(cssClass("editing")).find(".edit").setValue(e2).pressEscape();
- }
- /*
- Имена параметров методов e1 & e2
- Мы уже применяем терминологию - taskText
- и тут - для обозначения текста таски применим эту же терминологию
- часто для обозначения было-стало - применяют old & new
- oldTaskText & newTaskText - будет ОК
- придерживайся правила - одно понятие - один термин
- чтобы переименовать класс/метод/переменную/параметр
- https://docs.google.com/document/d/13dNyFGbI7mV22UUhH8E0LJ7SzabAmX7Bw7VCHScYfiU/edit#heading=h.vwuqi54t6fyg
- Еще важный момент
- Методы очень похожи
- фактически отличие - pressEnter() или pressEscape()
- реализуй метод xxx
- который будет выполнять весь одинаковый код
- tasks.find(exactText(e1)).doubleClick();
- tasks.find(cssClass("editing")).find(".edit").setValue(e2)
- и возвращать SelenideElement = элемент, для которого вызывали setValue
- чтобы далее вызывать xxx(...).pressEnter()
- подумай над именем этого метода
- оно должно точно отражать - что делает метод
- а делает он - старт/начало редактирования
- */
- ************************
- private void assertTasks(String... taskTexts) { tasks.shouldHave(exactTexts(taskTexts)); }
- /*
- используй стандартное форматирование
- это тоже важно
- вырабатывай привычку - отдаешь код - отформатируй его
- кстати - и ты сможешь больше увидеть в хорошо отформатированном и организованном коде
- это позволяет его лучше рефакторить
- в IntelIJ Idea выдели код, и с меню code->reformat code
- запомни горячие клавиши и используй
- обрати внимание - что изменится
- */
- **************************
- private ElementsCollection tasks = $$("#todo-list li");
- /*
- можно быть точнее в селекторе "#todo-list>li"
- иногда это будет важно
- в нашем простом приложении - можно и так оставить)
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement