#java #automation
Хозяке java-автоматизаторам на заметку:
Периодически вижу подобные вопросы (и подобный код) тут и там:
Я не могу найти ни одной причины “модельным” классам (точнее, объектам) не быть immutable, уж во всяком случае, в тестах.
А начиная с Java 16 у нас есть ключевое слово record (на самом деле уже с 14, но там это была preview feature). Если вы его еще совсем не использовали, то о том, что это такое, советую послушать Тагира Валеева.
Тот же самый класс без всякого Lombok может выглядеть так:
Да, иногда можно придумать (хотя, в действительности, с трудом) поводы менять состояние объекта, но для этого мы вправе написать метод внутри нашего рекорда:
И пользоваться новым объектом. Ну, все как в любимом нами иммутабельном классе String.
Собственно, в учебном проекте моего курса qa.guru advanced все модели как на бэкендах, так и в тестах существуют в виде record. Чего и вам всем желаю и рекомендую. Вы же не на java 8? Selenide вот требует 17 🙂
Периодически вижу подобные вопросы (и подобный код) тут и там:
Схема ответа:
{
"users": [ 0 ],
"groups": [ 0 ]
}И класс для его маппинга
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserDataRegisterModel {
private Integer type;
private String name;
private String data;
private List<Integer> users;
private List<Integer> groups;
}
Я не могу найти ни одной причины “модельным” классам (точнее, объектам) не быть immutable, уж во всяком случае, в тестах.
А начиная с Java 16 у нас есть ключевое слово record (на самом деле уже с 14, но там это была preview feature). Если вы его еще совсем не использовали, то о том, что это такое, советую послушать Тагира Валеева.
Тот же самый класс без всякого Lombok может выглядеть так:
public record UserDataRegisterModel (
Integer type,
String name,
String data,
List<Integer> users,
List<Integer> groups
) {}
Да, иногда можно придумать (хотя, в действительности, с трудом) поводы менять состояние объекта, но для этого мы вправе написать метод внутри нашего рекорда:
public UserDataRegisterModel addType(int type) {
return new UserDataRegisterModel(type, name, data, users, groups);
}И пользоваться новым объектом. Ну, все как в любимом нами иммутабельном классе String.
Собственно, в учебном проекте моего курса qa.guru advanced все модели как на бэкендах, так и в тестах существуют в виде record. Чего и вам всем желаю и рекомендую. Вы же не на java 8? Selenide вот требует 17 🙂
YouTube
Тагир Валеев — Java 17 для тех, кто в танке
Подробнее о фестивале TechTrain: https://jrg.su/YR8JKw
— —
Не успели передохнуть от перехода на Java 11, а уже вот-вот выйдет Java 17! Кошмар, куда столько Джав! У вас не было времени следить, что там интересного произошло в трёх или пяти последних версиях?…
— —
Не успели передохнуть от перехода на Java 11, а уже вот-вот выйдет Java 17! Кошмар, куда столько Джав! У вас не было времени следить, что там интересного произошло в трёх или пяти последних версиях?…
❤21👍5🔥5
#Java #gradle #automation
Вчера один из моих студентов задал вопрос -
Ну и скрин с этой ошибкой.
Опыт не пропьешь - я сразу сказал, что, видимо, gradle в проекте / системе не той версии, которая нужна для Java 17 (это версии 7.6 и выше). Студент стал разбираться и - конец немного предсказуем - дело было действительно в старой версии gradle (6.7). Обновили и все заработало.
И тут у меня один вопрос - неужели невозможно, если уж вы делаете разбивки по версиям, которые совместимы с той или иной JDK, неужели совсем невозможно вывести понятное сообщение об ошибке - "Дружище, у тебя несовместимые версии". Как новичок должен разбираться в
?
У меня нет ответа.
Вчера один из моих студентов задал вопрос -
Добрый день! Кто может подсказать какой JDK 17 версии нужно поставить чтобы не было конфликтов и можно было использовать selenide 7? Если выбираю JDK 17 версии , то ловлю ошибку "Could not initialize class org.codehaus.groovy.reflection.ReflectionCache"
Ну и скрин с этой ошибкой.
Опыт не пропьешь - я сразу сказал, что, видимо, gradle в проекте / системе не той версии, которая нужна для Java 17 (это версии 7.6 и выше). Студент стал разбираться и - конец немного предсказуем - дело было действительно в старой версии gradle (6.7). Обновили и все заработало.
И тут у меня один вопрос - неужели невозможно, если уж вы делаете разбивки по версиям, которые совместимы с той или иной JDK, неужели совсем невозможно вывести понятное сообщение об ошибке - "Дружище, у тебя несовместимые версии". Как новичок должен разбираться в
Could not initialize class org.codehaus.groovy.reflection.ReflectionCache
?
У меня нет ответа.
👍34🔥8❤3❤🔥2
#обучение #java #qaguru
А еще сегодня стартую 4 поток своего авторского курса Advanced. Занятие отрытое для всех, так что приходите, даже если не хотите учиться. Ну а если вдруг думаете - надо оно вам или нет - посмотрите на один из лучших дипломов 3 потока от Миши Нестерова - проект Rococo
Фронтенд (rococo-client) к нему написан нашей командой, а именно Ириной из OZON fintech, но, каждая другая строка кода, каждый микросервис, каждая строчка тестов, и все-все все в этом репозитории - написал Миша, и это и есть наш диплом.
Мы даем front, остальное делают студенты.
На 4-м потоке мы будем давать целых два frontend-а на выбор (REST и GraphQL, совершенно разные проекты), а все бэкенды и тесты будут писать студенты. Будет очень 🚀 интересно 🚀. Промокод в закрепе 😁
А еще сегодня стартую 4 поток своего авторского курса Advanced. Занятие отрытое для всех, так что приходите, даже если не хотите учиться. Ну а если вдруг думаете - надо оно вам или нет - посмотрите на один из лучших дипломов 3 потока от Миши Нестерова - проект Rococo
Фронтенд (rococo-client) к нему написан нашей командой, а именно Ириной из OZON fintech, но, каждая другая строка кода, каждый микросервис, каждая строчка тестов, и все-все все в этом репозитории - написал Миша, и это и есть наш диплом.
Мы даем front, остальное делают студенты.
На 4-м потоке мы будем давать целых два frontend-а на выбор (REST и GraphQL, совершенно разные проекты), а все бэкенды и тесты будут писать студенты. Будет очень 🚀 интересно 🚀. Промокод в закрепе 😁
Telegram
QA.GURU in QA.GURU | Общий чат
🚀 Уже сегодня в 20:00 по Москве старт 4- го потока нашего мощнейшего курса!
Приглашаем всех желающих на бесплатное вводное занятие по Автоматизации тестирования для продвинутых инженеров Java Advanced
🗓 Добавить напоминание в календарь
⭐️ Курс разработан…
Приглашаем всех желающих на бесплатное вводное занятие по Автоматизации тестирования для продвинутых инженеров Java Advanced
🗓 Добавить напоминание в календарь
⭐️ Курс разработан…
🔥19👍3
#Java #Spring
Об обновлении зависимостей.
Обновил тут в одном из своих Spring пет-проектов одну зависимость.
Было 1.1.2, стало - 1.2.1. Поменял местами 2 цифры так сказать, что могло бы пойти не так?
У меня напрочь отвалился Oauth 2.0 code flow.
Запрос
В коде спрингового сервиса даже в DEBUG логгировании нет никаких ошибок и стэктрейсов, потому что эта ошибка и не логгируется при выбрасывании.
Что делать?
Смотреть гит блэйм, кто же и что же поменял в этом
Метод
The client makes a request to the token endpoint by sending the
following parameters using the "application/x-www-form-urlencoded"
То есть, еще месяц назад реализация OAUTH 2.0 в spring-authorization-server не соответсвовала RFC, принимая GET параметры! Так же ей не соответсвовал и мой код, отправляя GET параметры. Начав бомбить о том "да как так одна циферка зависимости ломает мой прекрасный код!" закончил философским "ошибаются все, и не боги горшки спринговые обжигают".
Тут есть и еще один вопрос, а почему я вообще изначально не прочитал нормально RFC и отправлял GET-параметры?
Потому, что до получения странной ошибки я просто думал, что мне будет достаточно посмотреть воркшоп автора книги Spring Security in Action - и в нем тоже показана отправка простых GET параметров. А значит, ошибаются не только контрибьюторы Spring, но и даже авторы книг о Spring.
Мои выводы
- ошибайтесь на здоровье;
- но, любите дебаг;
- и гитблэймы;
- и чтение спецификаций и RFC
Об обновлении зависимостей.
Обновил тут в одном из своих Spring пет-проектов одну зависимость.
Было 1.1.2, стало - 1.2.1. Поменял местами 2 цифры так сказать, что могло бы пойти не так?
У меня напрочь отвалился Oauth 2.0 code flow.
Запрос
/oauth2/token? отдает 400 BAD REQUEST. И говорит вот такое понятное сообщение об ошибке - UNSUPPORTED_GRANT_TYPE. Как же так, спрашиваю сам себя? Ведь я не менял grant_type=authorization_code в своем запросе;В коде спрингового сервиса даже в DEBUG логгировании нет никаких ошибок и стэктрейсов, потому что эта ошибка и не логгируется при выбрасывании.
Что делать?
Смотреть гит блэйм, кто же и что же поменял в этом
OAuth2TokenEndpointFilter, чудес же не бывает? А изменения кроются, на самом деле, внутри OAuth2AuthorizationCodeAuthenticationConverter. Метод
OAuth2EndpointUtils.getFormParameters раньше доставал из запроса и GET-параметры, и URL-encoded параметры, а теперь - только URL-encoded параметры. Как же так, почему раньше-то можно было? Иду в RFC Oauth 2.0 и вот ответ - following parameters using the "application/x-www-form-urlencoded"
То есть, еще месяц назад реализация OAUTH 2.0 в spring-authorization-server не соответсвовала RFC, принимая GET параметры! Так же ей не соответсвовал и мой код, отправляя GET параметры. Начав бомбить о том "да как так одна циферка зависимости ломает мой прекрасный код!" закончил философским "ошибаются все, и не боги горшки спринговые обжигают".
Тут есть и еще один вопрос, а почему я вообще изначально не прочитал нормально RFC и отправлял GET-параметры?
Потому, что до получения странной ошибки я просто думал, что мне будет достаточно посмотреть воркшоп автора книги Spring Security in Action - и в нем тоже показана отправка простых GET параметров. А значит, ошибаются не только контрибьюторы Spring, но и даже авторы книг о Spring.
Мои выводы
- ошибайтесь на здоровье;
- но, любите дебаг;
- и гитблэймы;
- и чтение спецификаций и RFC
GitHub
heisenbug-2023-autumn/rococo-auth/build.gradle at 55d71aef72ad0fd2cc2f59158e5da95142e7d067 · dtuchs/heisenbug-2023-autumn
Contribute to dtuchs/heisenbug-2023-autumn development by creating an account on GitHub.
🔥24👏4👍1😁1
#java #opensource
Сегодня я решил переписать allure-grpc.
Это маленькая библиотечка за моим авторством, которая создаёт красивый отчетик для gRPC тестов.
Но она изначально, как говорится, by design, не заточена под bidirectional streaming и на client-streaming - тоже. Стоит признать, что и в реальных проектах это самые редко используемые виды стриминга в gRPC. Она не то что бы совсем с ними не работает, но, если клиент отправляет несколько message, то в отчёте будет несколько steps - для каждого message. Не-кра-си-во.
Пришло время сделать так, чтоб работала одинаково хорошо с любым видом gRPC. Ну и заодно смахнуть пыль с ачивки open source контрибьютора😁
А вы создаете pullrequest-ы в opensource? Делитесь своим опытом🤟
Сегодня я решил переписать allure-grpc.
Это маленькая библиотечка за моим авторством, которая создаёт красивый отчетик для gRPC тестов.
Но она изначально, как говорится, by design, не заточена под bidirectional streaming и на client-streaming - тоже. Стоит признать, что и в реальных проектах это самые редко используемые виды стриминга в gRPC. Она не то что бы совсем с ними не работает, но, если клиент отправляет несколько message, то в отчёте будет несколько steps - для каждого message. Не-кра-си-во.
Пришло время сделать так, чтоб работала одинаково хорошо с любым видом gRPC. Ну и заодно смахнуть пыль с ачивки open source контрибьютора😁
А вы создаете pullrequest-ы в opensource? Делитесь своим опытом🤟
GitHub
allure-java/allure-grpc at main · allure-framework/allure-java
Allure integrations for Java test frameworks. Contribute to allure-framework/allure-java development by creating an account on GitHub.
🔥37
#java #opensource
Если вам интересно, что же получилось с Allure-grpc, а там есть, на что посмотреть (потоки, CountDownLatch-и вот это вот все 🥲 А еще unit-тесты!), то, короче говоря, вот PR. Я надеюсь, что это будет полезно всем QA, кто тестирует streaming gRPC.
Это же так радостно, когда есть проблема, и есть библиотека, которая ее решает, не правда ли?
Если вам интересно, что же получилось с Allure-grpc, а там есть, на что посмотреть (потоки, CountDownLatch-и вот это вот все 🥲 А еще unit-тесты!), то, короче говоря, вот PR. Я надеюсь, что это будет полезно всем QA, кто тестирует streaming gRPC.
Это же так радостно, когда есть проблема, и есть библиотека, которая ее решает, не правда ли?
GitHub
Improve AllureGrpc integartion for support non-blocking (streaming) stubs by dtuchs · Pull Request #1015 · allure-framework/allure…
Context
In gRPC, client streaming and bidirectional streaming require to use a non-blocking (async) Stubs. These stubs uses different threads for handling sendMessage(T message) and onClose(status,...
In gRPC, client streaming and bidirectional streaming require to use a non-blocking (async) Stubs. These stubs uses different threads for handling sendMessage(T message) and onClose(status,...
👍9❤5🔥2🏆2
#java #frameworks
Selenide - крутой.
Я думаю, что большинство из вас в этом и так не сильно сомневается (список пользователей говорит сам за себя), но вот пару дней назад произошло маленькое событие, которое могло бы вообще пройти незамеченным для меня, но не прошло: я обновил в одном из своих проектов Selenide c 6.х до последней версии 7.2.1. И у меня перестал компилироваться код🙂 Казалось бы, первая мысль поругаться, но я, наоборот, пишу пост похвалы.
А дело все в том, что разработчики Selenide радикально упростили жизнь всем, кто писал или планирует написать свои кастомные CollectionCondition. Если раньше надо было переопределять 3 метода:
Причем, что делает второй и для чего он нужен технически я даже не понимал и просто писал
А еще, надо было писать свои классы исключений:
А теперь все стало радикально просто, надо переопределить один метод :
Назначение и сигнатура которого понятны даже если вообще в первый раз слышать про
Респект всем библиотекам и фреймворкам, которые упрощают свои API и делают их чистыми для понимания и написания кода. Selenide с каждым релизом, обрастая все новым функционалом, становится проще для понимания и расширения. И это хорошо.
Selenide - крутой.
Selenide - крутой.
Я думаю, что большинство из вас в этом и так не сильно сомневается (список пользователей говорит сам за себя), но вот пару дней назад произошло маленькое событие, которое могло бы вообще пройти незамеченным для меня, но не прошло: я обновил в одном из своих проектов Selenide c 6.х до последней версии 7.2.1. И у меня перестал компилироваться код🙂 Казалось бы, первая мысль поругаться, но я, наоборот, пишу пост похвалы.
А дело все в том, что разработчики Selenide радикально упростили жизнь всем, кто писал или планирует написать свои кастомные CollectionCondition. Если раньше надо было переопределять 3 метода:
@Override
public void fail(CollectionSource collection, List<WebElement> elements, Exception lastError, long timeoutMs)
@Override
public boolean missingElementSatisfiesCondition()
@Override
public boolean test(List<WebElement> elements)
Причем, что делает второй и для чего он нужен технически я даже не понимал и просто писал
return false;🥲А еще, надо было писать свои классы исключений:
public class SpendsMismatch extends UIAssertionError А теперь все стало радикально просто, надо переопределить один метод :
@Override
public CheckResult check(Driver driver, List<WebElement> elements)
Назначение и сигнатура которого понятны даже если вообще в первый раз слышать про
CollectionCondition.Респект всем библиотекам и фреймворкам, которые упрощают свои API и делают их чистыми для понимания и написания кода. Selenide с каждым релизом, обрастая все новым функционалом, становится проще для понимания и расширения. И это хорошо.
Selenide - крутой.
selenide.org
Selenide users
🔥44🥰8👍1
#java #обучение #qaguru
Вчера провел первое занятие уже 5-го потока своего авторского курса Java Advanced в QA.GURU. Как и все предыдущие, курс будет глубоко погружать в разработку и тестирование вокруг Java.
Если вдруг кто-то из вас желает залететь в уходящий поезд 5-го потока, можете воспользоваться моим персональным промокодом DTUCHS10, который даст вам скидку 10% до 25 апреля включительно. Для активации промокода напишите в QA.GURU-SALES.
Вчера провел первое занятие уже 5-го потока своего авторского курса Java Advanced в QA.GURU. Как и все предыдущие, курс будет глубоко погружать в разработку и тестирование вокруг Java.
Если вдруг кто-то из вас желает залететь в уходящий поезд 5-го потока, можете воспользоваться моим персональным промокодом DTUCHS10, который даст вам скидку 10% до 25 апреля включительно. Для активации промокода напишите в QA.GURU-SALES.
qa.guru
Автоматизированное тестирование на Java для продвинутых | Онлайн-курс по написанию автотестов | QA.GURU
Продвинутый курс по автоматизации тестирования на Java. Курсы повышения квалификации на Java для тестировщиков уровня Middle и выше.
❤10
#java
Сегодня впервые воспользовался ключевым словом
Я такой - "о, а return из функции
Вывод - советую читать релиз ноуты того, что в вашем резюме, как бы банально это не казалось 🥲
Сегодня впервые воспользовался ключевым словом
yield в Java, описывая банальный switch-case: return switch (action) {
case ADD -> ...;
case ACCEPT -> ...;
case REJECT -> ...;
case DELETE -> {
userDataClient.remove(username, input.username());
yield ...;
}
};
Я такой - "о, а return из функции
-> {} тут уже не работает" и стал смутно вспоминать, что должен же быть какой-то иной способ. Решил погуглить, когда оно там появилось, оказалось что аж в 13 Java - вот так и живешь годами не используя целое ключевое слово.Вывод - советую читать релиз ноуты того, что в вашем резюме, как бы банально это не казалось 🥲
Oracle
JDK Release Notes
This document provides links to the release notes for all versions of the JDK.
👍15❤4💯2
#Java #qaguru
Скриншотные тесты - неизбежная необходимость во многих проектах, особенно где есть всякие красивые графики и диаграммы в canvas. Проверяется это только скриншотными тестами, и если мы используем Selenide, то понадобиться еще какая-нибудь библиотека-сравнивалка.
Самая известная из них - ashot от Яндекса.
Тогда наш код может выглядеть примерно так:
где
Этот код всем неплох (и даже прекрасно прячется внутрь PageObject), но у меня к нему есть вопросы:
1) В случае падения именно этого ассерта, нам нужен совершенно специфичный формат Allure Attachment:
2) Нам надо иметь возможность перезаписать expected изображения запустив тест со специальным флагом (например, у нас новый браузер и в нем canvas выглядит слегка по другому).
3) Задачи 1 и 2 хотелось бы делать где-то под капотом, что бы наш код тестов вообще ничего не знал об этих особенностях.
Все эти пункты можно изящно решить с помощью JUnit Extensions, и это один из практических примеров, которые я рассказываю на своем авторском курсе для java автоматизаторов, который стартует буквально на следующей неделе. Наши скриншотные тесты будут простыми, а все, что сложнее ассерта - будет жить в Extension.
Приходите послушать меня и Мишу Рубанова в 54 сериях, я гарантирую, что это будет интересно 🚀
Скриншотные тесты - неизбежная необходимость во многих проектах, особенно где есть всякие красивые графики и диаграммы в canvas. Проверяется это только скриншотными тестами, и если мы используем Selenide, то понадобиться еще какая-нибудь библиотека-сравнивалка.
Самая известная из них - ashot от Яндекса.
Тогда наш код может выглядеть примерно так:
assertFalse(
new ImageDiffer().makeDiff(
expectedImage,
ImageIO.read(requireNonNull($("canvas[role='img']").screenshot()))
).hasDiff()
);
где
ImageDiffer - класс из ashot, expectedImage - ожидаемое изображение, которое у вас где-то в ресурсах, завернутое в BufferedImage.Этот код всем неплох (и даже прекрасно прячется внутрь PageObject), но у меня к нему есть вопросы:
1) В случае падения именно этого ассерта, нам нужен совершенно специфичный формат Allure Attachment:
Allure.addAttachment(
"Screenshot diff",
"application/vnd.allure.image.diff",
objectMapper.writeValueAsString(screenDif)
);
2) Нам надо иметь возможность перезаписать expected изображения запустив тест со специальным флагом (например, у нас новый браузер и в нем canvas выглядит слегка по другому).
3) Задачи 1 и 2 хотелось бы делать где-то под капотом, что бы наш код тестов вообще ничего не знал об этих особенностях.
Все эти пункты можно изящно решить с помощью JUnit Extensions, и это один из практических примеров, которые я рассказываю на своем авторском курсе для java автоматизаторов, который стартует буквально на следующей неделе. Наши скриншотные тесты будут простыми, а все, что сложнее ассерта - будет жить в Extension.
Приходите послушать меня и Мишу Рубанова в 54 сериях, я гарантирую, что это будет интересно 🚀
GitHub
GitHub - pazone/ashot: WebDriver Screenshot utility. Take screenshots, crop, prettify, compare
WebDriver Screenshot utility. Take screenshots, crop, prettify, compare - pazone/ashot
👍25❤9