Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Заострю твое внимание на нескольких моментах, потом в коде их более подробно рассмотрим
- According to the Draft Test Plan choose main use cases to be covered
- У тебя есть Use Case List
- Там есть названия - лаконичные
- (про add, кстати, меня не послушался, ну ОК - определись с используемыми терминами)
- Почему тут применяешь другие варианты? remove вместо delete?
- for efficiency of “smoke approach”, don’t cover all use cases per filter -
- cover some actions at all filter, others - at active, etc.
- But definitely - cover all CRUD actions
- Имеется в виду - не нужно одно действие покрывать в сценарии более одного раза
- Дальше важный момент
- Мы реализуем е2е сценарий для smoke покрытия
- это значит - что достаточно покрыть высокоприоритетный юз кейс лишь единожды, на одном из контекстов
- т е - покрыли edit на active - все, этого достаточно
- конечно, с добавлением таски так не получится )
- но - и того количества тасок, что ты создал - не нужно
- но с остальными операциями - это получится вполне
- задача smoke покрытия - быстро дать нам фидбек = все высокоприоритетные операции работают
- не - все высокоприоритетные операции работают на всех контекстах
- а - именно вот так - что они работоспособны
- дальше - если smoke тестирование пройдено - можно глубже тестировать приложение
- а если нет - так нет смысла продолжать тестировать - есть серьезные проблемы и надо их устранять
- Приоритет действия высокий если
- - нерабочее действие не позволяет использовать приложение
- - у действия нет альтернативы
- - действие - часто используемое
- - действие - стандартное для многих приложений
- Примеры высокоприоритетного
- - добавление задачи - высокоприоритетная штука, потому что если отвалится - приложение не работает
- - отмена редактирования с помощью esc - во-первых, стандартное поведение, во-вторых - нет альтернативы
- - закомпличивание/раскомпличивание одной задачи - часто используемое и критично чтоб работало - важный функционал
- Так вот - низкоприоритетные вещи - в smoke-тесте не нужно покрывать.
- Чтобы оставить smoke тест эффективным
- А вот Reopen All - уже имеет приоритет пониже - т к реже будет использоваться, чем тот же reopen
- потому - reopen - стоит покрыть, а Reopen All - уже не стоит
- Проверку счетчика Items left - стоит покрыть лишь единожды.
- В общем-то - это не высокоприоритетная штука.
- Т к даже если это не будет работать - приложение будет все равно функционально.
- С другой стороны, на состояние этого счетчика влияет любая выполненная операция.
- Ввиду этого - в рамках е2е покроем его лишь единожды.
- про использование неявных проверок через действие
- вариант 1
- add("task1"");
- edit("task1", "task1 edited");
- delete("task1 edited");
- вариант 2
- add("task1", "task2");
- edit("task2", "task2 edited");
- delete("task2 edited");
- Вариант 1 = правильное использование таких проверок через действие
- Вариант2 = не правильное использование
- Т к последующие действия не проверяют состояние ВСЕХ тасок в списке
- Таким образом - ты сможешь эффективно использовать неявные проверки через действия только в случае,
- если в списке тасок будет видима лишь одна таска
- Также не забывай - после каждого действия должна быть выполнена проверка
- Сразу (!!!)
- Не получается использовать неявную проверку через следующее действие - используй явную
- Но - действие должно быть обязательно проверено сразу
- исключения - бывают )
- но - это исключения
- в норме - каждое действие должно быть проверено
- давай уже и про исключения тут поговорим, чтоб картина была полнее
- на самом деле - тут важнее помнить - что проверять надо сразу)
- когда стоит или можно откладывать проверку, не делать ее сразу после действия
- в целом = правило такое = каждое действие должно быть проверено сразу
- это нужно для того, чтобы знать не только, что действие выполнено
- но и то, что действие (каждое) выполнено с ожидаемым нами результатом
- и если тест упал - нам важно знать
- какая конкретно операция этому была виной
- суть проверки - не только проверить сущность, над которой выполнялось действие
- но и общую картину
- в нашем случае могло быть так
- добавляем таску - а добавляется 2 одинаковые
- проверка - что перава таска имеет такой-то текст - пройдет
- и об ошибке мы не узнаем
- а это плохо)
- потому правильнее - проверять общую картину
- а не состояние сущности, над которой было совершено действие
- если это возможно, конечно)
- и если мы оперируем именно списком однотипных сущностей
- почему и когда мы можем отложить проверку
- первый пример - проверить первый раз список тасок уже после добавления всех 4-ех тасок
- т к операции однотипные в общем-то
- можно быть чуть точнее
- проверить список тасок после добавления первой таски и после добавления последней таски
- если посчитать - что это 2 разные ситуации = добавление первой и добавление последующих тасок
- второй пример - для цепочки операций на all фильтре (complete + clear completed)
- не делать проверки списка тасок после закомпличивания
- а уже делать проверку после следующей операции - clear completed
- тут логика следующая
- после закомпличивания таска все равно отображается в списке
- и то, что она закомпличена - мы поймем уже после выполнения clear completed
- но, с другой стороны,
- то, что закомпличивания таска все равно отображается в списке - это
- как раз часть логики....
- и из этих соображений - стоило бы тут добавить проверку
- пример - при закомпличивании таска удаляется
- если проверим аж после clear completed -
- такую ошибку не поймаем
- так что по поводу проверки после закомпличивания -
- ее нужно использовать, если операция закомпличивания нестабильна
- или ее можно отложить - если мы не ждем сюрпризов от этой операции
- такой баланс - эффективность vs точность
- */
- public class TodoMVCTest {
- @Test
- public void testTasksOperations(){
- open("https://todomvc4tasj.herokuapp.com/");
- add("1", "2", "3", "4");
- /*
- не торопись добавлять сразу несколько тасок
- так ты забираешь у себя возможность использовать неявные проверки
- */
- assertTasksAre("1", "2", "3", "4");
- edit("1", "1_new");
- /*
- лучше edit("1", "1 edited");
- точнее отразит происходящее
- да и далее по кодо легче будет понимать - что за таска
- следующая операция delete("2") - не проверяет операцию edit("1", "1_new");
- во-первых - работаешь с другой таской - это не проверит состояние отредактированной
- во-вторых - проверка должна нам рассказывать о состоянии всех тасок
- была бы у тебя всего одна таска в списке - мог бы использовать
- delete для проверки edit
- */
- delete("2");
- assertTasksAre("1_new", "3", "4");
- /*
- не торопись удалять таску
- чем позже ты это сделаешь, тем меньше тасок придется добавить
- мы же стараемся не делать ни одного лишнего движения
- */
- toggle("4");
- clearCompleted();
- assertTasksAre("1_new", "3");
- /*
- ну, можно и так, конечно
- только мы опять - раньше времени удаляем таску (при вызове clearCompleted())
- ну и выгоднее эти операции разбросать по сценарию -
- можно воспользоваться тем, что у тебя есть закомпличеная таска
- не только для работы с clearCompleted()
- например - хорошая идея
- перед переходом на Active - закомплитить таску
- проверить тексты в списке тасок (=все таски вне зависимости от статуса видны на олле
- - это тоже часть логики)
- перейти на Active и снова проверить список тасок
- так ты проверишь точно - и переход на другой фильтр, и закомпличивание допроверишь
- такой способ проверки перехода на фильтр - наиболее точный -
- т к было-стало разное у списка
- + стало=отвечает требованиям фильтра
- т е - состояние списка изменилось и изменилось правильно
- */
- toggleAll();
- toggleAll();
- toggleAll();
- clearCompleted();
- /*
- проверка только после 4-ой операции - перебор)
- слишком надолго отложил проверку
- глядя на трижды повторяющийся вызов toggleAll() -
- я, признаться, на какое-то время задусываюсь - что есть что
- лучше перед вызовами toggleAll или toggle - используй поясняющий комментарий -
- complete / complete all / reopen / reopen all
- */
- assertAreNoTasks();
- /*
- подводим промежуточные итоги
- 4 добавленные таски благополучно уничтожены
- покрыто *сколько раз покрыто
- add *4
- edit *1
- delete *1
- complete *1
- complete all *2
- reopen all *1
- clear completed *2
- осталось совсем немного не покрытых действий
- да и повторений многовато
- reopen all - вообще не стоило покрыватт
- реально написать такой сценарий, в котором только add будет повторяться
- */
- add("1");
- /*
- снова добавили таску с текстом 1
- не очень удачная идея - добавлять таски с такими же именами
- которые использовались для других тасок в рамках этого же сценария
- причина проста - далее по сценарию ты смотришь на таску 1 и не сразу понимаешь -
- что это за таска 1 - которая добавлена в самом начале или попозже
- зачем тебе сложности лишние?
- результат добавления - не проверен
- следующая операция openTab("Active");
- не проверит операцию add("1")
- */
- openTab("Active");
- /*
- и тут не хватает проверки
- более того - тут не выгодная тествая ситуация
- писала выше - было-стало при переходе на другой фильтр должно отличаться
- так ты проверишь - что переход на фильтр работает + работает правильно
- про реализацию метода перехода по фильтрам - ниже напишу
- */
- add("2", "3", "4");
- assertTasksAre("1", "2", "3", "4");
- /*
- эххх)
- и снова надобавлял тасок раньше времени
- не торопись)
- */
- ...
- toggle("4");
- /*
- мы complete уже покрывали All фильтре
- далее уже не пишу про повторения
- почитай тексты вначале ревью - если мы реализуем smoke покрытие
- нам достаточно один раз на одном из контекстов покрыть операцию
- повторять - не нужно
- */
- assertTasksAre("1", "2_new", ""); // Или отобрать только с классом .сompleted? А то смахлювал получается... :)
- /*
- вариант с отбором только .сompleted - тоже не очень-то хорош
- в прошлой лекции примерно на 59-ой минуте было про это
- тут - посмотри повнимательнее
- http://joxi.ru/l2ZNaR0F83gJv2
- если отфильтруешь таски по кондишену visible и уже у этой коллекции проверишь тексты -
- придешь к нормальному набору параметров
- вместо ("1", "2_new", "")
- получишь ("1", "2_new")
- (текст не видимого элемента коллекции считается пустым - юзер же его не видит)
- мало того - проверки отфильтрованного по visible списка тасок тебе подойдут
- и на completed фильтре
- чтобы по этому поводу картинка сложилась полностью - посмотри
- https://drive.google.com/file/d/0B8hgIBw8-V-AdGxxU1R3enl1RzQ/view?ts=567ab8d7
- и прими окончательное решение по набору проверок
- */
- toggleAll();
- /*
- ну допустим, на all-е - действительно, были причины отложить проверку
- тут - таких причин нету)
- */
- clearCompleted();
- assertAreNoTasks();
- add("1", "2", "3", "4");
- toggleAll();
- /*
- снова повторяемся)
- и снова - не проверяем результаты выполненного действия
- */
- openTab("Completed");
- /*
- проверки - нет
- было-стало - да, разное
- но ни было, ни стало - не проверены)
- проверка могла быть точной, но ее нет совсем
- */
- ...
- /*
- еще из того, чего не хватает
- - переход на all фильтр - лучше в конце сценария проверить и это
- вернуться на all и удалить последнюю таску (вот что я имела в виду -
- когда говорила отложить удаление на потом))
- - cancel edit - тоже вісокоприоритетная операция, и ее надо бы покрыть
- - items left - писала в самом начале - почему стоит покрыть (единожды)
- в остальном - многое покрыто по нескольку раз - это надо оптимизировать
- низкоприоритетное можно не покрывать вовсе - reopen all, например
- распредели покрытие действия поравномернее по фильтрам - так тест лучше
- будет отлавливать проблемы - когда на каком-то из фильтров операции над
- тасками корректно не выполняются
- */
- *****************************************
- ElementsCollection tabs = $$("#filters>li");
- private void openTab(String tabText) {
- tabs.findBy(exactText(tabText)).click();
- }
- /*
- почитай про KISS principle
- https://docs.google.com/document/d/13dNyFGbI7mV22UUhH8E0LJ7SzabAmX7Bw7VCHScYfiU/edit#heading=h.w4krdzi2dr1j
- и про вот это в особенности
- https://docs.google.com/document/d/13dNyFGbI7mV22UUhH8E0LJ7SzabAmX7Bw7VCHScYfiU/edit#bookmark=id.8bflixemdgfw
- переделай)
- */
- **********************************************************
- public void edit(String taskText, String newTaskText){
- /*
- для состояний было-стало - часто применяют old & new from & to
- oldTaskText & newTaskText
- fromTaskText & toTaskText
- */
- $(".editing")
- /*
- вот этот кусочек улучшим
- в сущности, что мы ищем - таску из списка тасок с классом editing
- из кода - это не ясно
- было бы нагляднее
- если вместо $(".editing")
- использовать tasks.findBy(...)
- будет понятно - что ищем некую таску по такому-то признаку
- вообще - єто более общее правило
- если у тебя есть переменная для некого элемента/коллекции
- и тебе надо доступиться до чего-то внутри этого элемента/коллекции
- то - не используй новый независимый селектор
- а - оттолкнись от уже используемой переменной
- получишь более наглядный и более DRY код
- */
- *****************************************
Advertisement
Add Comment
Please, Sign In to add comment