Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public class OpenTodoMVCAndClearData extends BaseTest {
- /*
- Предков тест-класса - называй по тем же конвеншенсам что и сами тест-классы -
- имя класса должно заканчиваться на Test
- На видео Якова - было более удачное название для этого класса
- Ну то пока не исправляй)
- От этого класса избавимся в итоге)
- */
- protected TaskPage page = new TaskPage();
- /*
- Прятать создание пейджей в предке тест-класса - не хорошая практика,
- особенно в общем случае - когда у нас несколько пейджей
- На самом деле - для разных тест-классов - может понадобиться разный набор пейджей
- Потому - создавать весь набор инструментов - вроде как перебор
- Да и скрываем мы это - в тест-классе не ясно - что за пейдж и откуда он берется
- Вот если использовать некую одну точку входа - тут создавать некий объект
- с помощью которого можно будет получить доступ к любым пейджам - так оно будет более оправдано
- Если, конечно, пейджей больше одного)
- Да и создание такой точки входа - лучше вынести в отдельный предок тест-класса
- тк - Single Responsibility principle
- Почитай вот тут - диалог Якова и студента, который аналогичное решение применял
- http://pastebin.com/qP85P1SP
- думаю, вопросы должны отпасть
- Далее - когда мы с виджетами будем разбираться - как раз вариант с единой точкой входа проработаем
- */
- @Before
- public void openPage() {
- page.visit();
- getWebDriver().navigate().refresh();
- /*
- про рефреш - писала
- просто - refresh()
- */
- }
- @After
- public void clearData() {
- clearLocalStorage();
- }
- /*
- тут - ты тоже не послушался)
- нет смысла выносить код отдельно в Helpers.clearLocalStorage
- ведь только здесь это и нужно
- и это - только одна строка кода
- имхо, слишком много суеты вокруг одной строки кода)
- ну то еще на твои вопросы с комментариями посмотрю
- */
- }
- ******************************************************************************
- @Attachment(value = "Page-screenshot", type = "image/png")
- private byte[] publishScreenshot() {
- File screenshot = Screenshots.takeScreenShotAsFile();
- try {
- byte[] arr = readAllBytes(Paths.get(screenshot.toURI()));
- screenshot.delete();
- return arr;
- } catch (IOException | NullPointerException e) {
- System.err.println("Exception occurred while trying to read from screenshot file." +
- "\n cause: " + e.getCause());
- }
- return new byte[0];
- }
- /*
- я вижу - что сейчас этот код ты не используешь
- все равно прокомментирую
- ловить NullPointerException - считается bad practice
- правильнее - делать проверки и обходить
- http://stackoverflow.com/questions/15146339/catching-nullpointerexception-in-java
- https://examples.javacodegeeks.com/java-basics/exceptions/java-lang-nullpointerexception-how-to-handle-null-pointer-exception/
- http://howtodoinjava.com/core-java/exception-handling/how-to-effectively-handle-nullpointerexception-in-java/
- вот это - горячо рекомендую
- http://www.yegor256.com/2014/05/13/why-null-is-bad.html
- особенно вот это http://joxi.ru/5md7jYwtvV5k8r
- почему самому не стоит вызывать NPE
- http://stackoverflow.com/questions/4715492/best-practise-in-catching-and-throwing-nullpointerexception
- на самом деле - таких проблем с Screenshots.takeScreenShotAsFile() - и не должно быть
- это с getLastScreenshot такое запросто может случиться - если нет автоматически сделанного скриншота - именно нуллл метод и вернет
- про это есть в faq
- https://docs.google.com/document/d/13dNyFGbI7mV22UUhH8E0LJ7SzabAmX7Bw7VCHScYfiU/edit#heading=h.c6yq8ne03bpo
- см соответствующий раздел
- */
- **********************************
- public class AllureScreenPublisher extends TestWatcher {
- private final Logger log = Logger.getLogger(getClass().getName());
- private boolean onFail = false;
- private boolean onSuccess = false;
- private AllureScreenPublisher() {
- }
- public static AllureScreenPublisher getInstance() {
- return new AllureScreenPublisher();
- }
- public AllureScreenPublisher onFail() {
- this.onFail = true;
- return this;
- }
- public AllureScreenPublisher onSuccess() {
- this.onSuccess = true;
- return this;
- }
- public AllureScreenPublisher always() {
- this.onSuccess = true;
- this.onFail = true;
- return this;
- }
- /*
- можно было и тут сделать объект не мутабельным
- реализовав
- private-конструктор с этими 2-мя параметрами - onFail и onSuccess
- и публичные статические методы onFail()/onSuccess()/always()
- которые фактически - и будут создавать объект с нжной тебе комбинацией свойств
- и вместо вызова - AllureScreenPublisher.getInstance().always();
- будет - AllureScreenPublisher.always();
- названия для методов onFail()/onSuccess()/always() - можешь подобрать точнее
- если хочешь отразить - что мы объект создаем
- мне кажется - и так будет очень ок
- */
- *************************
- if (onSuccess) publish();
- /*
- согласно conventions - фигурные скобки и в таких случаях нужно применять
- https://google.github.io/styleguide/javaguide.html#s4.1.1-braces-always-used
- тоже - этот документ рекомендую, дельный
- */
- ****************************
- Attachment(value = "Page-screenshot", type = "image/png")
- public byte[] publish() {
- String path = screenshot();
- log.info(path);
- // skip 'Screenshot: file:/'
- path = path.substring(19, path.length());
- File screenshot = new File(path);
- try {
- byte[] arr = readAllBytes(Paths.get(screenshot.toURI()));
- System.err.println("Delete screenshot: " + clean(path));
- return arr;
- } catch (IOException | NullPointerException e) {
- System.err.println("Exception occurred while trying to read from screenshot file." +
- "\n cause: " + e.getCause());
- }
- return new byte[0];
- }
- /*
- не могу понять - зачем столько сложностей
- почему не использовать Screenshots.takeScreenShotAsFile();
- зачем удалять файлы - если - mvn clean - прекрасно зачищает все это
- про эксепшены - читай выше
- и я бы - не использовала catch-секцию
- а указала для метода - throws IOException
- если будет проблема - пусть будут кишки наружу
- сообщение мы можем спокойно пропустить
- и так и не узначем - что там у нас было
- */
- ***********************************
- public boolean clean(String pathToPng) {
- String pathToHrml = pathToPng.substring(0, pathToPng.lastIndexOf('.')).concat(".html");
- return new File(pathToHrml).delete() & new File(pathToPng).delete();
- }
- /*
- из практики совет
- раз уже разрыл - что и html с таким же именем может быть)
- иногда - вот этот html - тоже очень полезная штука
- париться с его удалением - точно не стоит
- а вот и его приаттачить, вместе с картинкой - может быть очень полезно)
- лучшего способа - чем ты реализовал - для доступа к html - я не знаю
- может он и есть, конечно
- но - имей в виду - из этих лимонов - можно надавить лимонад)
- что я хочу сказать)
- clean - лишнее
- т к mvn clean - вполне справляется с задачей
- это надо убивать
- стоит использовать Screenshots.takeScreenShotAsFile();
- так проще код будет
- а если понравилась идея про - аттачить html
- то
- переименуй этот класс - т к речь не только про скриншот
- и аттачь - и скриншот и html (2 метода аннотированные как Attachment)
- это - не обязательно
- да и я тебе не скажу - формируется ли html - если мы вызываем метод для формирования скриншота
- возможно - это пара для getLastScreenshot - при падениях тестов - точно и скриншот и html формируется
- в оригинальном задании - нужно было аттачить скриншот всегда к тесту
- это уже ты сделал, причем разными способами
- на практике - мне пригождалось 2 режима
- аттачить скриншот вообще к степу (бывают такие степы - что горошо бы и картинку увидеть)
- аттачить скриншот если тест упал - по финишу
- можно вот эти все фантазии - не реализовывать
- просто помни - что иногда это полезно может быть
- минимально к ревью
- - упрости решение
- - не лови null pointer exception
- - уйди от мутабельности
- - не убивай файлы
- - не лови IOException
- максимально к ревью (можно не делать, это только если видишь практическую пользу для себя)
- - аттачить как скриншот так и ???html - если он сформировался)
- - возможность аттачить на любом степе теста (это не сложно - вызывай в степ-методе - метод с аннотацией Attachment)
- */
- *****************************************************************
- *****************************************************************
- public enum FilterType {
- ALL,
- ACTIVE,
- COMPLETED
- }
- public enum TaskType {
- ACTIVE,
- COMPLETED
- }
- public class Helpers {
- public static void waitUntilAjaxComplete() {
- public static void waitUntilAjaxComplete(long timeoutMills) {
- public static void clearLocalStorage() {
- public static PreConditionsBuilder givenAtTodoMvc() {
- public static class PreConditionsBuilder {
- }
- }
- /*
- смешались в пекедже - src/main/java/com/alexautomician/todomvc/api вообще
- и в классе - Helpers - в частости
- кони и люди) мухи и котлеты)
- я бы не сказала - что нужное нам для реализации гивенов - относится к src/main/java/com/alexautomician/todomvc/api
- выдели для этого - отдельный пекедж - src/main/java/com/alexautomician/todomvc/givenhelpers к примеру
- и там расположи - FilterType, TaskType и класс givenHelpers
- поскольку - и FilterType и TaskType - нужны только для гивен-методов
- я бы и их запихнула как иннер-классы в givenHelpers
- но то такое, не настаиваю
- просто - придерживайся одной линии
- или все аккуратненько держи в givenHelpers
- или все аккуратненько разложи в src/main/java/com/alexautomician/todomvc/givenhelpers
- вопрос - что есть для тебя - аккуратненько)
- */
- *********************************************************
- public static class PreConditionsBuilder {
- /*
- твой вариант - это не Builder pattern
- там же вся соль в том - что один объект = который мы строим = не мутабельный
- мы его собираем с помощью билдера
- и потом - работаем с ним
- и есть объект = билдер - он мутабельный
- он только и делает - что собирает нужные свойства для будущего объекта
- и затем - строит этот объект - разово отдавая ему все собранные свойства
- каждый объект - выполняет свою роль
- один - строит
- второй - используется
- стоит переделать - т к такая реализация будет правильнее
- такой код - проще в итоге сопровождать, развивать и дорабатывать
- (хотя, когда его пишешь с нуля - согласна - так не кажется, хочется вот так сэкономить)
- вернись к
- http://enterprisecraftsmanship.com/2016/09/29/law-of-demeter-and-immutability/
- http://enterprisecraftsmanship.com/2016/05/12/immutable-architecture/
- */
- ********************************************
- public PreConditionsBuilder tasks(TaskType taskType, String... taskNames) {
- /*
- при такой реализации метода - не получишь цепочки тасок
- закомпличеная а
- активная b
- закомпличеная с
- а это - серьезное ограничение
- особенно - с учетом уровня сложности
- который используется в реализации
- да и switch - не знаю
- мне кажется - решение было бы аккуратнее внутри и проще снаружи
- если бы мы могли вызывать
- ...comlpeledTasks("a", "b").activeTasks("c", "d").completedTasks("e", "f")
- и получать таски - в нужном нам состоянии и именно в такой последовательности
- т е - снаружи - у каждого вызываемого метода - предельно простые параметры - тексты тасок
- и - изнутри - каждый из методов не оперирует никакими switch
- да и в таком случае - от юзера - вообще можно спрятать TaskType
- этот тип будет лишь для внутреннего пользования
- */
- *********************************
- public PreConditionsBuilder filter(FilterType filterType) {
- /*
- лучше - 3 метода без параметра
- чем один с параметром)
- будь KISS )
- https://docs.google.com/document/d/13dNyFGbI7mV22UUhH8E0LJ7SzabAmX7Bw7VCHScYfiU/edit#bookmark=id.8bflixemdgfw
- */
- *******************************************************
- private void openFilterPage()
- /*
- тут вместо switch -
- можно было бы заюзать
- open(filterType.getUrl())
- если бы FilterType - такой метод имел
- см пример ниже
- советую именно так реализовать
- и я советую назвать enum не FilterType
- а просто - Filter
- мы ничего из важного - не потеряем
- */
- public enum Day {
- MONDAY("понедельник"),
- TUESDAY("вторник"),
- WEDNESDAY("среда"),
- THURSDAY("четверг"),//<<----------------------для каждого значения enum - вызов конструктора, фактически значение = объект класса
- FRIDAY("пятница"),
- SATURDAY("суббота"),
- SUNDAY("воскресенье");
- String description;//<<---------------------------поле для хранения описания дня недели
- public Day(String description) {
- this.description = description;//<<---------------------------логика конструктора - запомнить для объекта его описание
- }
- @Override
- public String toString() {
- return description;//<<---------------------------логика - вывести для объекта - то что для него заполнили
- }
- }
- *******************************************************************
- public void buildPreConditions() {
- openFilterPage();
- clearLocalStorage();
- /*
- локалсторидж чистить не нужно
- ведь далее - присваивается заново - значение его итему
- который отвечает за список тасок
- этого хватит с головой
- да и - раз так - то и в афтер-методе - не нужно ничего чистить
- если принять - что в каждом тест-методе - мы будем готовить тестовую ситуацию с помощью гивен-методов
- и выше - уже есть код который обеспечивает открытие урла
- значит - и бифор метод для открытия урла - не нужен
- значит - и класс OpenTodoMVCAndClearData - в целом не нужен
- убирай его из проекта
- еще насчет openFilterPage();
- можно реализовать ensureopenFilterPage();
- в нем - проверяем
- если у нас уже нужный урл
- то и ничего не надо открывать
- */
- addTasksToLocalStorage();
- getWebDriver().navigate().refresh();
- /*
- рефреш кстати - не всегда помогает - если работать вот так с фильтрами
- возможно - тебе понадобится выполнение JavaScript команды location.reload()
- вместо рефреша (см выше - его можно выполнить проще)
- http://www.w3schools.com/jsref/met_loc_reload.asp
- */
- ********************************************
- private void addTasksToLocalStorage() {
- /*
- тут - только вопрос - который уже выше озвучивала
- как нам задать таски а разных статусах - идущие вразнобой - одна такая, следующая другая и т д
- */
- *************************
- public class SmokeTodoMVCTest
- /*
- объединять тесты для Smoke покрытия в одном тест-классе - не свегда удачная идея
- часто - удобнее - когда тесты собраны по тест-классам тематически
- и некоторые из них - составляют смоук покрытие
- это скоро научимся делать
- так что - да - важное заметил - нам надо уметь запускать только тесты для такого-то покрытия
- но реализовывать это нужно по-другому
- этот тест-класс - оставь как тест-класс для интеграционных тестов
- фиче-тесты - расположи в соответствующих фильтру тест-классах
- в каждом тест-методе - используй гивен-методы
- хм....
- смотрю на другие тест-классы - похоже ты так и сделал
- а это - с прошлого задания тест-класс
- если так - все равно переименуй тест-класс в TodoMVCTest
- и расположи в правильном пекедже - где ты предыдущие задания собираешь
- как для предыдущего задания - с ним все ок
- */
- ****************************************
- //сравни
- givenAtTodoMvc()
- .tasks(TaskType.COMPLETED, "compl1")
- .filter(FilterType.ALL)
- .buildPreConditions();
- //или
- given()
- .completedTasks("compl1")
- .atAllFilter()
- .build();
- //или даже вот так
- givenTasks()
- .completed("compl1")
- .atAll()
- .build();
- /*
- упрости сигнатуру у методов
- для фильтров - проще оперировать тремя методами без параметров, а не одним с параметром
- для тасок - проще оперировать двумя методами с просыми параметрами - чем еще одним параметром - типом таски
- в результате - того кто пишет тест-методы -
- вообще не будет волновать существование типов - для типа таски или фильтра
- все это будет под капотом
- поскольку мы работаем с TodoMvc и это сказано в имени тест-классов
- уже тут - AtTodoMvc - не нужно писать
- givens и preconditions - синонимы
- потому - начни с given() и заканчивая - уже не надо писать про PreConditions
- наверное - мой первій предложенный вариант - наименее радикальный)
- второй - порадикальнее)
- какой ты выберешь - дело твое)
- но - подупростить и подсократить надо бы)
- */
- *************************************
- @Test
- public void clearCompleted() {
- givenAtTodoMvc()
- .tasks(TaskType.ACTIVE, "1")
- .tasks(TaskType.COMPLETED, "compl2")
- .filter(FilterType.ACTIVE)
- .buildPreConditions();
- page.clearCompleted();
- // TODO how to check it with existing functional ?
- }
- /*
- проверь тексты тасок и итемс лефт
- этого будет достаточно
- уже разбирали в слеке -
- у нас же должен быть тест - когда мы с какого-то фильтра переключаемся на эктив
- и в списке - у нас видимы только активные таски + итемс лефт - именно их и отражает
- (по-моему - не все 6 переходов с фильтра на фильтр покрыты тестами - это высокоприоритетное
- с комплитеда на эктив - нету вроде бы)
- в нашем случае - количество видимых тасок в списке (мы проверили тексты)
- равно количеству итемс лефт (мы проверили итемс лефт)
- косвенно - мы можем сделать вывод - что все ок - если эти 2 проверки прошли
- если не нравится идея
- можно монизить приоритет clearCompleted на эктив фильтре до среднего и не покрывать
- или - придумать - как реализовать маленький е2е
- в котором что-то еще проверить
- и уточнить то - что нам нужно
- я за первый вариант
- то же касается и других твоих похожих вопросов (то что ты оранжевым в тест-плане выделил)
- */
- ************************************************************************
- ==================================================================================================
- 1. " @After
- public void afterMethod() {
- clearLS();
- getWebDriver().navigate().refresh();
- }
- /*
- спорно - стоило ли выносить в отельный метод clearLS() - очистку локалсториджа
- да еще и в имени метода - сокращать слова"
- >>>>>>>> ну по поводу отдельного метода, разве мы не стараемся сделать наши тесты
- как можно более простыми и читабельными? а @Before и @After это же часть
- тестов, в них тоже описана тестовая логика (pre-conditions, post-conditions),
- почему мы в тесты стараемся писать чуть ли не человеко-понятный текст, а в
- бифор и афтер прямо какие то JS комманды? это из серии переменные создавать
- тогда, когда ты переиспользуешь значение в нескольких местах, или когда их
- можно описать простым и понятным языком) вместо тех. деталей)
- по поводу сокращения - возможно неправ, можно было написать полностью, мы просто
- в рабочем проекте плотно работаем с ЛС, и эта аббревиатура как то прижилась
- и всем понятна, привычка)
- /*
- так тут - одна строчка )
- причем - очень похожая на clearLocalStorage )
- если б там были километры кода - да, надо было бы спрятать
- а так - имхо, перебор
- в нескольких местах - этот метод не использовался
- а теперь и вовсе не будет нужен) - с появлением гивенов
- аббревиатура - да
- от проекта к проекту - допускаю - что какая-то приживается
- но общее правило - новую не придумывай)
- юзай только стандартную
- */
- ==================================================================================================
- 2. "насчет рефреша
- в selenide - есть метод refresh()
- технически - то же самое
- просто лаконичнее"
- >>>>>>>> видел метод, пробовал. он инкапсулирует в себе open(), который у меня на
- selenide 3.11 & ff 47.0.1 не работает (не перегружает страницу), поэтому вручную
- вызвал рефреш у драйвера
- и по методу open() в пейдже тоже страница не перегружается
- /*
- ясно
- я писала выше - тут вообще стоит location.reload() делать
- после таких открытий - сразу на урле фильтра
- как показал опыт - самое надежное решение
- */
- ==================================================================================================
- 3. " идеально наверное, вообще вот так -
- page.itemsLeft().shouldBe(...)
- ну то потом так напишем)
- щас - не буду спорить"
- >>>>>>>> я не силен в ООП в джаве пока, ума хватило только на такую реализацию.
- посмотри пожалуйста, так нормально реализовано?
- /*
- все ок в общем-то
- стоило ли делать иннер-классом - а не знаю)
- может в данном случае и стоило)
- оставляй
- молодец)
- */
- ==================================================================================================
- 4. "ну и варианты тут есть для additional edit operations
- confirmEditByPressTab
- confirmEditByClickOutside
- deleteByEmptyingText"
- >>>>>>>> пока исправил editEnter на edit (раз мы считаем это дефолтной ситуацией)
- могу попробовать сделать что то типа
- page.edit("1", "edited1").confirmEnter();
- page.edit("1", "notedited1").discardEsc();
- нужно?
- /*
- то уже перебор
- имхо)
- виджеты - будем разбирать отдельно
- и не на таком примитиве как тудуэмвиси - тут действительно примеры из пальца высасываем)
- */
- ==================================================================================================
- 5. "
- проверяя - $("#todo-count>strong").shouldHave(exactText(...
- мы косвенно проверяем - что футер видим
- а вот стоит ли проверять - что футер не видим....
- я б не стала
- в виду невысокого приоритета такой фичи
- "
- >>>>>>>> я имею ввиду если например есть 1 закомпличенная задача и 0 активных - футер есть,
- и в нем нужно проверять itemsCount - 0, а если нет вообще задач - то и футера нет,
- и не надо ничего в нем искать, можно взамен проверить что он невидим
- /*
- я поняла твою идею
- лучше - быть точным
- если хотим проверить - что футера нет - знач надо именно это и проверять
- а не прятать внутри проверки итемс лефта варианты
- перечитай прошлый пассаж
- он про то - что не надо прятать внутри вспомогательных методов какую-то тестовую логику
- */
- ===================================================================================================
- 6. "https://www.youtube.com/watch?v=w_rPX9TwDkA
- http://spirogov.github.io/video-recorder-intieghratsiia-s-jenkins-i-allure-rieportami/"
- >>>>>>>> попробовал, но чет у меня нормально не получилось, я не совсем понимаю
- чем отличается @Rule от @Before, и как с ними работать, и у меня он постоянно
- падал на методе
- @Attachment(value = "video", type = "video/mp4")
- private byte[] attachment() throws InterruptedException {
- try {
- File video = VideoRecorder.getLastRecording();
- await().atMost(5, TimeUnit.SECONDS)
- .pollDelay(1, TimeUnit.SECONDS)
- .ignoreExceptions()
- .until(() -> video != null);
- return Files.readAllBytes(Paths.get(video.getAbsolutePath()));
- } catch (IOException e) {
- log.warning("Allure listener exception" + e);
- return new byte[0];
- }
- }
- на await(). и видео перекошенное писалось, еще и видео перекошено, жуть кароче)
- на этом моменте писал тут вопрос по поводу где почитать за JUnit, а как дошел до
- след пункта как раз ты дала офигенную статью, спасибо! стало намного понятней,
- зачем нужны все эти рулы, бифоры, и чем они друг от друга отличаются)
- я так понял, что по идеологии JUnit "дешевые ресурсы" должны создаватся\удалятся
- в @Before and @After, дорогие в @BeforeClass, @AfterClass, а что то обобщенное,
- в зависимости от места где нужно это в @Rule and @ClassRule.
- только теперь у меня такой вопрос, разве скриншоты\видео не то самое, глобальное,
- что нужно делать всегда? почему бы тогда не вынести в @Rule PublishScreenAllure
- /*
- рада, что статья понравилась)
- еще что-то было про перекошенность видео и аллюр-репорты
- http://spirogov.github.io/video-recorder-intieghratsiia-s-jenkins-i-allure-rieportami/
- может, не давала линку
- там есть про эти моменты
- честно говоря - я сапожник без сапог - руки не доходят поиграться как следует)
- когда удалять-создавать - я решаю исходя из целей и обстоятельств
- если что-то можно сделать разово - перед запуском всех тестов - так почему нет)
- рулы - разумно использовать - когда тебе недостаточно бифоров-афтеров
- типа - надо обработать отдельно - ситуацию с фейлом, например
- я - сторонник простых решений)
- если можно делать просто - надо делать просто)
- насчет - надо делать всегда - про скриншоты - не знаю)
- не для всех проектов это так)
- и для простого случая - когда нужен лишь скриншот на конец каждого теста - афтер метод куда проще)
- и это - можно объяснить и новичку
- если это цель - то афтер-метод лучше)
- хотя - с рулой - можно избавиться от предка тест-класса вообще
- что тоже приятный бонус)
- может и красивее такое в рулу спрятать, соглашусь с тобой
- */
- *********************************************************
- public class BaseTest {
- public final static String ROOT_REPORT = "target" + separator + "site" + separator + "allure-maven-plugin" + separator;
- @Rule
- public ExternalResource resource = new PublishScreenAllure();
- @BeforeClass
- public static void baseBeforeClass() {
- Configuration.browser = "firefox";
- }
- static class PublishScreenAllure extends ExternalResource {
- PublishScreenAllure() {
- Configuration.screenshots = false;
- Configuration.reportsFolder = ROOT_REPORT + "screenshots";
- }
- @Override
- protected void after() {
- }
- @Override
- protected void before() throws Throwable {
- publishScreenshot();
- }
- @Attachment(value = "Page-screenshot", type = "image/png")
- protected byte[] publishScreenshot() {
- File screenshot = Screenshots.takeScreenShotAsFile();
- try {
- return readAllBytes(Paths.get(screenshot.toURI()));
- } catch (IOException | NullPointerException e) {
- System.err.println("Exception occurred while trying to read from screenshot file." +
- "\n cause: " + e.getCause());
- return new byte[0];
- }
- }
- }
- }
- получится что скриншоты для аллюра это просто типа как сервис, хош включай, не хош не включай
- /*
- а вот внутрь предка тест-класса - впихивать реализацию рулы - не надо)
- отдельный класс
- и просто юзай для тест-классов - уже вообще предок не нужен
- пара строк - на создание рулы
- одна - на создание пейджа
- не думаю - что ради такого стоит городить предка для тест-класса
- папки переназначать или фф прописывать - я б на стала)
- */
- ===================================================================================================
- 7. вопрос по скринам селенида.
- получается есть флаг
- Configuration.screenshots = true;
- который вроде как означает что мол делай скрины если тест упал - ок.
- если я хочу не только когда упал, а всегда, то надо пользоватся
- @Rule
- public ScreenShooter makeScreenshotOnFailure = ScreenShooter.failedTests().succeededTests();
- но рулы исполняются до @Before и после @After, т.е. даже если я включу на успешных тестах скрины,
- в своем @After я его не увижу.
- теперь вопрос, можно ли не переопределяя селенидовский рул, сделать нормальные скриншоты
- (чтоб были их списки, то да се, всякие удобные селенидовские штуки) ?
- пока варианта у меня 2 (не геморных):
- 1 - publishScreenshot() из BaseTest (плюсы - просто относительно, минусы - при fail дублируются
- скрины, создается в Users/user/....)
- 2 - AllureScreenPublisher.class в api (плюсы - скриншоты не дублируются, создаются в проекте в
- соотв. папочке, после того как скрин отправлен аллюру - чистятся (мы их потом смотреть не
- будем руками, они в аллюре уже сохранены), минусы - хз, попахивает костылем, но пока вроде
- работает))
- /*
- нормально подрубиться к ScreenShooter - не выйдет)
- причину - ты хорошо описал)
- возможно - можно отнаследоваться от ScreenShooter
- и что-то там дописать в потомке
- но я не вижу острой необходимости так делать
- твои 2 варианта - ок
- насчет не чистятся - я писала про это
- костыля - не вижу
- особенно - если код немного поравнять)
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement