Пташки тут наспівали, що не всім очевидно навіщо і як використовувати Optional в програмуванні і чому «чисті null це зло»... Давай же розберемось та ще й порівняємо підходи в різних мовах – #java, #typescript, #csharp, #python – аби зрозуміти основоположні принципи та механізми 😉
Почнемо з Java, в якій підхід – якраз самий класичний, простий і надійний.
Припустимо ми робимо якусь операцію - «зберегти файл» і хочемо запам'ятати результат (власне збережений файл), але ж результату може і не бути, бо наприклад полетить помилка:
Код скомпілюється, все ймовірно запрацює, а потім – одного дня, коли по якійсь причині, наприклад не буде права на запис - код грохнеться з чимось типу
Ну... ми поколупаємось, розберемось і підправимо код:
Так от, давні коДаóси помітили :), що коли ми працюємо з нулами то постійно вилазять такого роду проблеми, і краще щось робити для того, щоб «не забувати обробляти нули одразу».
Саме просте, що іноді (наприклад у версіях джави до 9-тої) – я роблю коли під рукою немає спеціального засобу типу Optional (про який буде мова далі) – це просто міняю назву змінної в якій може бути
Але все ще, це такий собі лайфхак – все залежить від моєї уважності 🙂
Ідеальний же варіант, це коли сам компілятор мені допомагатиме не забути перевірити на відсутність результату... Класичне вирішення проблеми - це використання типу
Зверни увагу чим останній код відрізняються від варіанту з
Виходить з Optional – та ж сама логіка, тільки більше задроства – суть якого в тому, щоб ми не забули що треба перевірити, і саме щоб нагадував нам про це – сам компілятор ще на стадії коли ми пишемо код;)
Що там в інших мовах? – гортай далі 😉 ⬇️
Почнемо з Java, в якій підхід – якраз самий класичний, простий і надійний.
Припустимо ми робимо якусь операцію - «зберегти файл» і хочемо запам'ятати результат (власне збережений файл), але ж результату може і не бути, бо наприклад полетить помилка:
File storedFile = null;
try {
storedFile = storeFile("~/tmp/temp.txt");
} catch (Exception error) {
// що завгодно, можемо залогувати помилку чи ще що...
}
// далі щось може відбуватись ...
// і в кінці, ми повертаємось до нашого файлу...
// наприклад, щоб запам'ятати його ім'я...
// чи просто надрукувати:
System.out.printLine(storedFile.getName());
Код скомпілюється, все ймовірно запрацює, а потім – одного дня, коли по якійсь причині, наприклад не буде права на запис - код грохнеться з чимось типу
NullPointerException
і з повідомлення про помилку – ми ох як довго не зрозуміємо у чому справа 🙂Ну... ми поколупаємось, розберемось і підправимо код:
File storedFile = null;
try {
storedFile = storeFile("~/tmp/temp.txt");
} catch (Exception error) {
// ...
}
// ...
System.out.printLine(storedFile != null ? storedFile.getName() : "file was not stored!");
Так от, давні коДаóси помітили :), що коли ми працюємо з нулами то постійно вилазять такого роду проблеми, і краще щось робити для того, щоб «не забувати обробляти нули одразу».
Саме просте, що іноді (наприклад у версіях джави до 9-тої) – я роблю коли під рукою немає спеціального засобу типу Optional (про який буде мова далі) – це просто міняю назву змінної в якій може бути
null
(себто відсутність результату, пустота):
File maybeStoredFile = null;
try {
maybeStoredFile = storeFile("~/tmp/temp.txt");
} catch (Exception error) {
// ...
}
// ...
/*
// тепер нижче у мене руки не повернуться написати:
System.out.printLine(maybeStoredFile.getName());
// тому що прямим же текстом написано MAYBE stored file!
// тобто може він і є, а може і нема,
// значить перед тим як на ньому викликати якийсь get* треба спочатку перевірити на нулл:
*/
System.out.printLine(maybeStoredFile != null ? storedFile.getName() : "file was not stored!");
Але все ще, це такий собі лайфхак – все залежить від моєї уважності 🙂
Ідеальний же варіант, це коли сам компілятор мені допомагатиме не забути перевірити на відсутність результату... Класичне вирішення проблеми - це використання типу
Optional
(в деяких мовах програмування його називають Maybe по аналогії з моїм префіксом вище, але не суть):
Optional<File> storedFile = Optional.empty();
try {
storedFile = Optional.of(storeFile("~/tmp/temp.txt"));
} catch (Exception error) {
// ...
}
// ...
/*
// тепер нижче якщо ми забудемо,
// що вище не обов'язково файл був збережений,
// то сам компілятор не дозволить нам написати:
System.out.printLine(storedFile.getName());
// тепер єдиний спосіб отримати що ми хочемо це витягнути його з "коробки optional"
// а раз будемо витягувати то ясно що треба спочатку перевірити чи в коробкі щось є:
*/
System.out.printLine(storedFile.isPresent() ? storedFile.get().getName() : "file was not stored!");
Зверни увагу чим останній код відрізняються від варіанту з
null
:
System.out.printLine(maybeStoredFile != null ? storedFile.getName() : "file was not stored!");
Виходить з Optional – та ж сама логіка, тільки більше задроства – суть якого в тому, щоб ми не забули що треба перевірити, і саме щоб нагадував нам про це – сам компілятор ще на стадії коли ми пишемо код;)
Що там в інших мовах? – гортай далі 😉 ⬇️
❤4🔥2✍1👍1🎉1
Отже, ми встигли розібрати ⬆️ що null-и (в Python – None) можуть бути болючими бо приводять до незрозумілих помилок. В #java та і в принципі у більшості мов програмування існує простий механізм – тип Optional (іноді називають його Maybe, іноді ще й обзивають особливим словом Монада...). Це універсальний, масимально простий і надійний механізм, тому якщо ти не джавіст, все одно проскроль вище і почитай;)
При цьому у інших мовах програмування є більш легкі механізми, і зараз ми поглянемо їх на прикладі #typescript, #csharp та #python, і подумаємо чи кращі вони за Optional у Java.
У мовах типу TypeScript чи C# за допомогою спеціальних опцій компілятора, можна включити режим "строгості нуллів" (`--strictNullChecks` чи
В C# працюватиме все точно так само:
В Python та ж історія що і в TypeScript чи C#, тільки треба додатково встановлювати mypy та плагін до нього:
Тепер питання - чи пощастило TS, C# та частково Python більше ніж Java з його Optional замість спеціального синтаксису? А ось цієї відповіді почекаємо в наступному пості, стей тюнд 😉
P.S.
Діліться в коментарях доповненнями до прикладів вище (вони доволі чорнові), і є повно цікавих нюансів, які не хотілось поки впихувати в сам пост. Також цікаво хто ще що використовував, і в джава і в інших мовах є куча альтернативних способів ;)
При цьому у інших мовах програмування є більш легкі механізми, і зараз ми поглянемо їх на прикладі #typescript, #csharp та #python, і подумаємо чи кращі вони за Optional у Java.
У мовах типу TypeScript чи C# за допомогою спеціальних опцій компілятора, можна включити режим "строгості нуллів" (`--strictNullChecks` чи
"strictNullChecks": true
для tsconfig.json в TS; <Nullable>enable</Nullable>
в C#), і тоді тої ж самої цілі можна досягти навіть з нулами:
// код на TypeScript
let storedFile: File | null = null;
try {
storedFile = storeFile("~/tmp/temp.txt");
} catch (error) {
// ...
}
// ...
/*
// тепер нижче компілятор не дасть написати:
console.log(storedFile.name);
// ми будемо змушені або свідомо звернутись до name через синтаксис !.
console.log(storedFile!.name);
// або ж спочатку перевірити на null:
*/
console.log(storedFile != null ? storedFile.name : "file was not stored!");
В C# працюватиме все точно так само:
// тільки оголошуємо тип як nullable через синтаксис знаку питання
FileStream? storedFile = null;
try {
storedFile = storeFile("~/tmp/temp.txt");
} catch (Exception error) {
// ...
}
/*
// тепер нижче компілятор не дасть написати:
System.Console.WriteLine(storedFile.Name);
// ми будемо змушені або свідомо звернутись до Name через синтаксис !.
System.Console.WriteLine(storedFile!.Name);
// або ж спочатку перевірити на null:
*/
System.Console.WriteLine(storedFile != null ? storedFile.Name : "file was not stored!");
В Python та ж історія що і в TypeScript чи C#, тільки треба додатково встановлювати mypy та плагін до нього:
stored_file: Optional[TextIO] = None
try:
stored_file = store_file("~/tmp/temp.txt")
except Exception as e:
...
# ...
'''
# тепер якщо встановлений додатковий пакет mypy
# та опційно налаштований плагін для нього в редакторі
# то тайп чекер mypy не дасть написати:
print(stored_file.name)
# ми будемо змушені або свідомо через коментар ігнорувати помилку:
print(stored_file.name) # type: ignore)
# або ж спочатку перевірити на None:
'''
print(stored_file.name if stored_file is not None else "file was not stored!")
Тепер питання - чи пощастило TS, C# та частково Python більше ніж Java з його Optional замість спеціального синтаксису? А ось цієї відповіді почекаємо в наступному пості, стей тюнд 😉
P.S.
Діліться в коментарях доповненнями до прикладів вище (вони доволі чорнові), і є повно цікавих нюансів, які не хотілось поки впихувати в сам пост. Також цікаво хто ще що використовував, і в джава і в інших мовах є куча альтернативних способів ;)
Telegram
AutotestЯк
Пташки тут наспівали, що не всім очевидно навіщо і як використовувати Optional в програмуванні і чому «чисті null це зло»... Давай же розберемось та ще й порівняємо підходи в різних мовах – #java, #typescript, #csharp, #python – аби зрозуміти основоположні…
❤7👍7
Продовжуємо роз-null-ятись... Optional vs Null Safety: коротка відповідь:)
Отже, прості null-и – ніби як зло (як класично у #java до 9-тої версії, або ж в #cs до 8.0), тому що:
☝🏻 сигнатури методів/функцій, що можуть отримувати
☝🏻 через те що
Альтернативою ж null-ам є
💡 тип
💡 «спеціальний синтаксис» для Strict Nulls чи Safe Nulls який найчастіше називають – «Null-Safety», як у #typescript, #cs, #python, і так далі...
Так от, короткою відповіддю на питання – що краще – Optional чи Null-Safety, і кому там більше пощастило – буде така: «Для задач автоматизації – пофіг:)». По-перше, в мовах типу Java, особливо то й альтернатив немає, null-и то все одно гірше. І хоч для простих задач Null-safety може виглядати «лаконічніше» і красивіше, зате механіка Optional більш проста і нюансів базового синтаксису – банально менше. А в простоті сила;). Різниця то, насправді, у підходах є, і вона типу важлива, але навіть в контексті розробки ПО – вона проявиться тільки в надскладних задачах на достатньо складних проджектах. А оскільки автоматизація тестування – по складності на порядок простіша за розробку, а SDET – просто простіше (без порядків) – то слід просто використовувати той механізм який за умовчанням є у мові ідіоматичним і просто бачити позитив у тому що маємо ☯️.
Тому, наприклад, попри те, що є класні бібліотеки для Optional у #typescript, типу fp-ts – все одно краще не випендрюватись, а використовувати ідіоматичнe Null-Safety з strictNullChecks як більш прагматичне рішення для ринку де більшість автоматизаторів навряд будуть знайомі з «вищою математикою» Optional з ліби fp-ts, яка просто не буде актуальною на практиці задач автоматизації...
P.S.
вищою математикою о_О ? – ги, так-так – (спойлер) саме деякі доволі складні математичні концепції дозволяють для певних задач бути механізму Optional більш ефективним. Відповідними поясненнями (все ще на пальцях), з ціллю – не стільки зануритись у науку, а, зробивши ретроспективу, – краще зрозуміти механіку роботи обох альтернатив null-ам – ми і займемось в наступному пості, stay tuned 😉
Отже, прості null-и – ніби як зло (як класично у #java до 9-тої версії, або ж в #cs до 8.0), тому що:
☝🏻 сигнатури методів/функцій, що можуть отримувати
null
на місці аргументів чи повернути null
як результат – не попереджають про це (що суперечить принципу Self-Documented Code) а компілятор не страхує і як результат – користувач функції може не врахувати деякі нюанси роботи з null-ами й отримати NullPointerException
☝🏻 через те що
null
виникає в одному місці коду, і може бути відповідно одразу не обробленим, то коли зрештою станеться NullPointerException
– дуже важко буде знайти місце, де ж була першопричинно пропущена ця обробка null-аАльтернативою ж null-ам є
💡 тип
Optional
(або Option
або Maybe
в залежності від мови...), як у #java💡 «спеціальний синтаксис» для Strict Nulls чи Safe Nulls який найчастіше називають – «Null-Safety», як у #typescript, #cs, #python, і так далі...
Так от, короткою відповіддю на питання – що краще – Optional чи Null-Safety, і кому там більше пощастило – буде така: «Для задач автоматизації – пофіг:)». По-перше, в мовах типу Java, особливо то й альтернатив немає, null-и то все одно гірше. І хоч для простих задач Null-safety може виглядати «лаконічніше» і красивіше, зате механіка Optional більш проста і нюансів базового синтаксису – банально менше. А в простоті сила;). Різниця то, насправді, у підходах є, і вона типу важлива, але навіть в контексті розробки ПО – вона проявиться тільки в надскладних задачах на достатньо складних проджектах. А оскільки автоматизація тестування – по складності на порядок простіша за розробку, а SDET – просто простіше (без порядків) – то слід просто використовувати той механізм який за умовчанням є у мові ідіоматичним і просто бачити позитив у тому що маємо ☯️.
Тому, наприклад, попри те, що є класні бібліотеки для Optional у #typescript, типу fp-ts – все одно краще не випендрюватись, а використовувати ідіоматичнe Null-Safety з strictNullChecks як більш прагматичне рішення для ринку де більшість автоматизаторів навряд будуть знайомі з «вищою математикою» Optional з ліби fp-ts, яка просто не буде актуальною на практиці задач автоматизації...
P.S.
вищою математикою о_О ? – ги, так-так – (спойлер) саме деякі доволі складні математичні концепції дозволяють для певних задач бути механізму Optional більш ефективним. Відповідними поясненнями (все ще на пальцях), з ціллю – не стільки зануритись у науку, а, зробивши ретроспективу, – краще зрозуміти механіку роботи обох альтернатив null-ам – ми і займемось в наступному пості, stay tuned 😉
fp-ts
Option.ts
Functional programming in TypeScript
👍9👌2
Хех, Можна було б поставити крапку над усіма null-ами ще в попередньому пості, але... Як можна жити у світі так, щоб око не тіпалось від коду на скріні праворуч? І це ще я вибрав простіший варіант (прийшлось здублювати процесинг plus1(age)), могло б бути і коду більше і закрученіше логіка... Ох, ну звісно жити з цим я таки навчився, і навіть себе змушую писати такий код, в тому числі й у своїх оупенсорс лібах:) – Саме через певну прагматичність і практичність... Дійсно, якщо для контексту проекту лиш де-інде потрібні будуть подібної складності трансформації (а в автоматизації тестування так і є), то краще не тягнути «красу» туди, де після цього прийдеться перенавчати всю команду, та й усю спільноту інженерів на ринку, щоб, раптом що, було ким команду розширяти :)
То чому ж мені таки хочеться доколупати цю тему, і пояснити чому те, що на скріні праворуч (Null Safety) не можна звести до того що ліворуч, і чому те що ліворуч працює саме завдяки Optional? Хех, мабуть, через те, що хоч ми і на практиці використовуємо лиш обмежене коло інструментів, та все ж час від часу, трапляються ситуації, де саме навички та досвід з чимось «за межами буденного» – допомагає нам оптимізувати процеси та зробити суттєвий прорив. По суті це і є відповідь на те «навіщо теорія», якщо на ділі використовуємо лиш «практику»? Це ж стосується вивчення інших мов програмування, в незалежності від того що основна на проекті - одна. Все це допомагає нам виходити за межі, і у найважливіший момент, стрибнути вище голови ;)
Тому я таки продовжу цю історію з нулами ще трошки. Але дайте відгук в коментарях, чи не занадто складно стає як для телеграм блогінгу з автоматизації тестування? Чи може краще було б додатково заглиблюватись в окремих статтях а тут давати лиш посилання? Не факт, що я буду дуже слухняним, але так чи інакше, ваш відгук вплине на цю нашу пісочницю;)
P.S.
Пояснення до скріну – в коментарях до посту;)
То чому ж мені таки хочеться доколупати цю тему, і пояснити чому те, що на скріні праворуч (Null Safety) не можна звести до того що ліворуч, і чому те що ліворуч працює саме завдяки Optional? Хех, мабуть, через те, що хоч ми і на практиці використовуємо лиш обмежене коло інструментів, та все ж час від часу, трапляються ситуації, де саме навички та досвід з чимось «за межами буденного» – допомагає нам оптимізувати процеси та зробити суттєвий прорив. По суті це і є відповідь на те «навіщо теорія», якщо на ділі використовуємо лиш «практику»? Це ж стосується вивчення інших мов програмування, в незалежності від того що основна на проекті - одна. Все це допомагає нам виходити за межі, і у найважливіший момент, стрибнути вище голови ;)
Тому я таки продовжу цю історію з нулами ще трошки. Але дайте відгук в коментарях, чи не занадто складно стає як для телеграм блогінгу з автоматизації тестування? Чи може краще було б додатково заглиблюватись в окремих статтях а тут давати лиш посилання? Не факт, що я буду дуже слухняним, але так чи інакше, ваш відгук вплине на цю нашу пісочницю;)
P.S.
Пояснення до скріну – в коментарях до посту;)
❤3
Резюмуємо – виходить, якщо «прості null-и» це –
> все що завгодно може бути null і я не можу прослідкувати де МАНnull'ЯК вискочить і відрубає мені щось... десь... і я ще й одразу не зрозумію де саме...
А «альтернатива null-aм» це –
> тепер за умовченням null не може бути ніде, а там де може – треба явно це вказати, щоб потім при використанні ми були змушені ОДРАЗУ ПЕРЕВІРИТИ (найпримітивніше – через if або тернарний оператор)
То для механізму Optional цією вказівкою є:
* тип
а для механізму «Null Safety» цією вказівкою є:
* тип
З цікавого...
🧐 – у #python замість знаку питання використовується тип
🧐 А ще дивніше... – у #swift, де знак питання
Так от☝🏻– Ось це
Які висновки ми можемо зробити з цього? Що випливає з того що Optional це саме коробка?
1. Раз це коробка під щось конкретне, то ми можемо розрізняти пусті коробки! Пуста коробка для сірників і пуста коробка для телефону – це зовсім різні коробки!
2. Раз це коробка, то значить можна вкласти одну коробку в іншу;)
Розберемо ці висновки детальніше в наступних постах...
> все що завгодно може бути null і я не можу прослідкувати де МАНnull'ЯК вискочить і відрубає мені щось... десь... і я ще й одразу не зрозумію де саме...
А «альтернатива null-aм» це –
> тепер за умовченням null не може бути ніде, а там де може – треба явно це вказати, щоб потім при використанні ми були змушені ОДРАЗУ ПЕРЕВІРИТИ (найпримітивніше – через if або тернарний оператор)
То для механізму Optional цією вказівкою є:
* тип
Коробка з МОЖЛИВО ЩОСЬ в середині
(в мовах зазвичай записується як Optional<ЩОСЬ>
чи Option<ЩОСЬ>
чи Maybe<ЩОСЬ>
чи Maybe ЩОСЬ),
що відповідно може дати два представника такого типу – або Коробка з чимось типу ЩОСЬ
(як то в #java – Optional<String> maybeText = Optioinal.of("some real text")`)
або поки Коробка з нічим
(Optional<String> maybeText = Optional.empty()
)а для механізму «Null Safety» цією вказівкою є:
* тип
ЩОСЬ або null
(найчастіше в мовах це записується як ЩОСЬ | null
чи ЩОСЬ?
, де, насправді, знак питання ?
, зазвичай, є просто синтаксичним цукором ака шорткатом для `| null`)З цікавого...
🧐 – у #python замість знаку питання використовується тип
Optional[ЩОСЬ]
, але насправді це не повноцінний тип, а лише «позначка» для тайп-чекерів, щоб вони застосували саме механізм Null-Safety (а не Optional!), тобто все ще мається на увазі випадок ЩОСЬ | None
(в #python замість null
використовується `None`)?
є синтаксичним цукором не для ЩОСЬ | null
, а для Optional(ЩОСЬ)
о_О. Тобто в мові під капотом живе якраз механізм Optional але синтаксис як у Null Safety 😄Так от☝🏻– Ось це
Коробка з МОЖЛИВО ЩОСЬ в середині
vs ЩОСЬ або null
– і є ключовою відмінністю, яка і визначає потенціал і можливості кожного з підходів... Які висновки ми можемо зробити з цього? Що випливає з того що Optional це саме коробка?
2. Раз це коробка, то значить можна вкласти одну коробку в іншу;)
Розберемо ці висновки детальніше в наступних постах...
Please open Telegram to view this post
VIEW IN TELEGRAM
Висновок 1: Optional<User>.empty() не те ж саме що Optional<Address>.empty()
... в той час як
Хех... Ну... ключове слово «потенційно» і воно ще й залежить віж того про яку мову програмування мова йде...
У #java от – доволі жорстка система типів і вона буде страхувати нас у таких випадках...
Наприклад, якщо у нас є метод
Але у більш реалістичній ситуації – не пропустить, якщо ми переплутаємо таки юзера з адресою:
Тобто на практиці #java все таки вміє розрізняти null-и для змінних різного типу.
Але не всі такі розумні... – #typescript от не завжди вміє:) У тій же ситуації код в #typescript скомпілюється без помилок:
а от з Optional такого б точно не було:
І це були тільки квіточки... Далі буде найцікавіший раунд, де Optional таки надає «Null Safety» тумаків, який все ще пропускатиме потенційні баги з нуллами.
to be continued...
... в той час як
null
один і той самий що в User | null
що в Address | null
. А раз той самий, то потенційно, чисто випадково, навіть при «Null Safety» можна передати отриманий null
від функції що повертає нулабл адресу до функції що очікує нулабл юзера o_OХех... Ну... ключове слово «потенційно» і воно ще й залежить віж того про яку мову програмування мова йде...
У #java от – доволі жорстка система типів і вона буде страхувати нас у таких випадках...
Наприклад, якщо у нас є метод
@Nullable String getStreetFrom(@Nullable User user)
, що витягує з юзера адресу (якщо вона не null) а потім витягує з адреси вулицю, то #java хоч і дозволить скомпілювати//java
System.out.println(getStreetFrom(null));
Але у більш реалістичній ситуації – не пропустить, якщо ми переплутаємо таки юзера з адресою:
//java
Address adressToBeInitLater = null;
// ... і якщо ми забудемо ініціалізувати змінну, залишивши там null,
// то все одно отримаємо
System.out.println(getStreet(adressToBeInitLater)); // COMPILE ERROR!
Тобто на практиці #java все таки вміє розрізняти null-и для змінних різного типу.
Але не всі такі розумні... – #typescript от не завжди вміє:) У тій же ситуації код в #typescript скомпілюється без помилок:
//typescript
function getStreetFrom(user?: User): string | undefined {/*...*/}
// ...
let adressToBeInitLater: Address | null = null
// ... і якщо ми забудемо ініціалізувати змінну, залишивши там null,
// то ніхто нас не попередить про це...
getStreetFrom(adressToBeInitLater) // <- COMPILED OK o_O
а от з Optional такого б точно не було:
//typescript
import { Option } from 'prelude-ts';
// ...
function getStreetFrom(user: Option<User>): Optional<string> {/*...*/}
//...
let adressToBeInitLater: Option<Address> = Option.none()
// ... і якщо ми забудемо ініціалізувати змінну,
getStreetFrom(adressToBeInitLater) // <- COMPILE ERROR 🙂
І це були тільки квіточки... Далі буде найцікавіший раунд, де Optional таки надає «Null Safety» тумаків, який все ще пропускатиме потенційні баги з нуллами.
to be continued...
Йо! Поки я дописую статтю по Optional вже більше місяця 🙈, давайте допоможемо Миколі зібрати на бандаж для 71-шої окремої єгерської бригади 🦾
🎯Ціль: 25 000.00 ₴
🔗Посилання на банку
https://send.monobank.ua/jar/3ftMx9cUQ9
💳Номер картки банки
5375 4112 0936 1141
🎯Ціль: 25 000.00 ₴
🔗Посилання на банку
https://send.monobank.ua/jar/3ftMx9cUQ9
💳Номер картки банки
5375 4112 0936 1141
Linkedin
Sign Up | LinkedIn
500 million+ members | Manage your professional identity. Build and engage with your professional network. Access knowledge, insights and opportunities.
👍9
Чи прям так playwright 🎭 швидше за SElenium ⚛️? 🤔
Ми 🎭 використовуємо на деяких проектах вже давно, але я так ніразу і недобігав реально зрівняти швидкість. І от – припекло🤡 А то Рома от останнім часом «кричить» що «селеніум тепер тільки для бабуїнів» (це моя дуууже вільно-перекручена інтерпретація сенсу, ги) а я якось для себе ще крапок над і не розставив... ну бо 🎭 тільки під web, бо API все ще формувався, до сих пір доволі не консистентний місцями, часом радикально стрибав у інший бік (слава богу що правильний – це я про page.locator замість усього іншого). І от я вже почав переживати що я зовсім не в тренді... Не солідно 🙂
Так от, ми тут поки дуже простенький End-to-End на TodoMVC апку запустили, типу всі види операцій по черзі проробити у сценарії. На 10тьох ранах (так, так, знаю що мало, але грець з ним) – Мінімальна різниця в часі – 11% відсотків усього! Опа опа, такий вже прям і швидший? 🙂 ... Це я так інтригу тримаю... Ну ок, таки є стрибки і аж до 64%. І середня різниця виходить – 35%, що вже не так і мало...
Але тут є ще один цікавий нюанс...
Зрівнювали ми не з чистим SElenium а саме з SelenideJS, тобто селенідоподібним врапером обмазаним зсередини розумними неявними очікуваннями а ззовні лінивими елементами – що самі по собі давлять на гальма поверх чистого селеніуму (все заради добра, стабільності тестів, і все таке, але зараз не про це), і якраз от ця різниця десь приблизно і лежить в залежності від ситуації між 25 і 75 відсотками (це я знаю бо тестив не раз всі свої селени/селеніди в порівнянні з селеніумом). Виходить цікавий висновок – саме в порівнянні з чистим селеніумом ймовірно не на так багато плейврайт і швидше 🤡 Але якщо порівнювати його з чимось типу селенідів що = селеніум + окрім усього + вбудовані очікування на кожен чих, то отримуємо вже щось типу 35% на користь плейврайту... І дуже може бути що якраз ці 35 відсотків і пов'язані з тим що плейрвайт більш ефективно саме "неявно чекає", адже саме в цьому вся фішка його движку, який побудований на набагато ефективніших з точки зору "комунікації" вебсокетах а не http як селеніум...
Тепер питання – чи дійсно того як чекає плейврайт – достатньо? чи настільки ж він стабільний з коробки як селеніди? І якщо так, чи можемо ми на боці селенідів таки зменшити відставання від 35% до чогось хоча б близького до спостереженого мінімуму в 11% у наших тестах...?
P.S.
Далі буде ще серія постів про плейврайт та його порівнянь з селенідами, включно по нюансам синтаксису, тому stay tuned 😉 Для тих хто любить спойлери –по нашим останнім зрівнянням – 🎭 хоч і не так красиво і консистентно але по суті дублює синтаксис селенідів, що означає що навіть врапер довкола плейврайту не особливо то вже зараз і потрібен... Хоча у мене руки все ще чухаються його доробити 🙂
Ми 🎭 використовуємо на деяких проектах вже давно, але я так ніразу і недобігав реально зрівняти швидкість. І от – припекло🤡 А то Рома от останнім часом «кричить» що «селеніум тепер тільки для бабуїнів» (це моя дуууже вільно-перекручена інтерпретація сенсу, ги) а я якось для себе ще крапок над і не розставив... ну бо 🎭 тільки під web, бо API все ще формувався, до сих пір доволі не консистентний місцями, часом радикально стрибав у інший бік (слава богу що правильний – це я про page.locator замість усього іншого). І от я вже почав переживати що я зовсім не в тренді... Не солідно 🙂
Так от, ми тут поки дуже простенький End-to-End на TodoMVC апку запустили, типу всі види операцій по черзі проробити у сценарії. На 10тьох ранах (так, так, знаю що мало, але грець з ним) – Мінімальна різниця в часі – 11% відсотків усього! Опа опа, такий вже прям і швидший? 🙂 ... Це я так інтригу тримаю... Ну ок, таки є стрибки і аж до 64%. І середня різниця виходить – 35%, що вже не так і мало...
Але тут є ще один цікавий нюанс...
Зрівнювали ми не з чистим SElenium а саме з SelenideJS, тобто селенідоподібним врапером обмазаним зсередини розумними неявними очікуваннями а ззовні лінивими елементами – що самі по собі давлять на гальма поверх чистого селеніуму (все заради добра, стабільності тестів, і все таке, але зараз не про це), і якраз от ця різниця десь приблизно і лежить в залежності від ситуації між 25 і 75 відсотками (це я знаю бо тестив не раз всі свої селени/селеніди в порівнянні з селеніумом). Виходить цікавий висновок – саме в порівнянні з чистим селеніумом ймовірно не на так багато плейврайт і швидше 🤡 Але якщо порівнювати його з чимось типу селенідів що = селеніум + окрім усього + вбудовані очікування на кожен чих, то отримуємо вже щось типу 35% на користь плейврайту... І дуже може бути що якраз ці 35 відсотків і пов'язані з тим що плейрвайт більш ефективно саме "неявно чекає", адже саме в цьому вся фішка його движку, який побудований на набагато ефективніших з точки зору "комунікації" вебсокетах а не http як селеніум...
Тепер питання – чи дійсно того як чекає плейврайт – достатньо? чи настільки ж він стабільний з коробки як селеніди? І якщо так, чи можемо ми на боці селенідів таки зменшити відставання від 35% до чогось хоча б близького до спостереженого мінімуму в 11% у наших тестах...?
P.S.
Далі буде ще серія постів про плейврайт та його порівнянь з селенідами, включно по нюансам синтаксису, тому stay tuned 😉 Для тих хто любить спойлери –
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🔥6
Ще 14го листопада мій хороший товариш та продакт менеджер (довоєнний бо з початку доброволець) оголошував збір з ціллю в 250к. За десяток днів, хлопцям ще не вистачає біля 70к на очі в небі. Давайте допоможемо чим зможемо 🎯
🔗Посилання на банку
https://send.monobank.ua/jar/7xUq6azYSD
💳Номер картки банки
5375411210427436
🔗Посилання на банку
https://send.monobank.ua/jar/7xUq6azYSD
💳Номер картки банки
5375411210427436
👍8❤4😁1
«А хто лідує цей проект? В плані якості... 🤔 Ніхто? А, ну самі розбирайтесь, знаю я ваші ці стартапи, коли звалюють усе на одного джуна чи мідла»
От не один раз я вже чув таке від тестувальників в контексті вибору нового проекту для роботи. Чомусь багатьох умовно молодих по досвіду інженерів – лякає «повна организація процесу QA з нуля, та ще й коли ти один»... Мені це завжди було важко зрозуміти, бо у самого завжди слина текла на такі проекти – це ж скільки простору для само-розвитку і головне «зробити все саме так як хочеться, і щоб ніхто зверху палки в колеса не вставляв»😇 А ще – не пам'ятаю щоб коли потрапляв у такі ситуації (а на відсотків 90 лиш в такі я і потрапляв) – то я використовував для власне налаштування процесу щось інше окрім здорового глузду та відкритої структурної комунікації з розробниками для спільного вирішення ключових питань. Раптом дивним чином виявляється, що достатньо взяти відповідальність, проаналізувати проблеми, щиро поділитись ними з іншими членами, сформувати потреби, набрейнстормити по ним варіанти вирішення і дуже швидко звичайна логіка допомагає знайти оптимальне рішення... Не читаючи 100500 книжок по QA, не залучаючи супер-мега консультантів, і так далі 🤡
нЄ?
Давайте от сходимо на TechMeetup від QArea і послухаємо що Артем Григоренко розкаже з цього приводу? Навіть так, саме ви (поки я навіть пости тут постити не встигаю) сходите послухаєте Артема, а тут у коментарях поділитесь зі мною інсайтами, і можливо подискутуєте зі мною по темі:)🙏🏻
Всі виручені кошти від даного заходу будуть передані на підтримку ЗСУ або інші благодійні цілі. 7 березня о 18:00 👉
https://tech-meetups.qarea.org/more-details-organization-of-the-quality-assurance-process
От не один раз я вже чув таке від тестувальників в контексті вибору нового проекту для роботи. Чомусь багатьох умовно молодих по досвіду інженерів – лякає «повна организація процесу QA з нуля, та ще й коли ти один»... Мені це завжди було важко зрозуміти, бо у самого завжди слина текла на такі проекти – це ж скільки простору для само-розвитку і головне «зробити все саме так як хочеться, і щоб ніхто зверху палки в колеса не вставляв»
нЄ?
Давайте от сходимо на TechMeetup від QArea і послухаємо що Артем Григоренко розкаже з цього приводу? Навіть так, саме ви (поки я навіть пости тут постити не встигаю) сходите послухаєте Артема, а тут у коментарях поділитесь зі мною інсайтами, і можливо подискутуєте зі мною по темі:)
Всі виручені кошти від даного заходу будуть передані на підтримку ЗСУ або інші благодійні цілі. 7 березня о 18:00 👉
https://tech-meetups.qarea.org/more-details-organization-of-the-quality-assurance-process
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤2😁1
AI-Powered Test Automation, це вам не півники смоктунці полизувать) У цю середу, 13го березня о 19:00, обскакаємо virtuoso.qa, і подивимось де він на шкалі між мустангом 🐴 і ... поні 🐎 (нехай всі поні мене пробачать... 😇 )
Посилання на live stream скину уже в середу десь там за годинку до старту... або підпишіться на канал у ютубі щоб не пропустити, канал зветься так само як цей, шукайте autotestyak😉
Посилання на live stream скину уже в середу десь там за годинку до старту... або підпишіться на канал у ютубі щоб не пропустити, канал зветься так само як цей, шукайте autotestyak
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥23👍7❤3
AutotestЯк
AI-Powered Test Automation, це вам не півники смоктунці полизувать) У цю середу, 13го березня о 19:00, обскакаємо virtuoso.qa, і подивимось де він на шкалі між мустангом 🐴 і ... поні 🐎 (нехай всі поні мене пробачать... 😇 ) Посилання на live stream скину уже…
Нагадую що сьогодні о 19:00 тестимо virtuoso.qa 😉 Посилання на стрім прилетить сюди ж перед початком.
❤14
Го тестити virtuoso.qa на стрім https://youtube.com/live/UqiuIw9AsL0 !!!
YouTube
Мустанг чи поні для для Web UI E2E Test Automation – тестимо Virtuoso
На що здатні сучасні no-programming інструменти автоматизації тестування на основі Штучного Інтелекту? Чи кращі вони за схему редактор коду + github copilot? Чи зручніші вони за BDD-фреймворки типу cucumber чи behave? Яша Крамаренко разом з Юльою пошукають…
🔥3
На стрімі промайнуло – як набиратись досвіду щоб знайти першу роботу, але здається там я не резюмував мій основний лайф хак: «шукати цікаві оупенсорс проекти чи альфа/бета-версій цікавих апок і гайда тестить, заводить баги». Можна самотужки, навіть в незалежностів від команди таких апок - пройти весь цикл, від декомпозиції функціоналу і побудови функціональної карти + чеклістів, написанню простого власного тест плану (що я буду тестить (скоуп)? як (принципи)? чим (інструменти)? коли?), і аж до автоматизації відповідних сценаріїв, власного прослідковування покриття, заведенню багів і спілкуванню з командою, перепровіркою фіксів, регресії на релізах... І ось вчора список таких апок для першого досвіду поповнився https://github.com/diia-open-source 😉
GitHub
Diia
Diia is an app with access to citizen’s digital documents and government services - Diia
🔥9
Який потрібен софт, щоб допомогти громаді самоорганізуватися та почати вирішувати свої проблеми?
Один з проектів, які можна обрати на Міському таборі для підлітків від школи Майбутні на весняних канікулах — це розробка таск-менеджера для громад.
Ми зберемо команду підлітків для розробки таск-менеджера, який зможе використовувати будь-яка політична спільнота — від шкільного самоврядування до об'єднаної територіальної громади. В режимі хакатону розробимо і запустимо продукт та почнемо тестувати його прямо на таборі.
Як громада може визначити свої проблеми і потреби? Хто в громаді може взятися за пошук рішення? До вирішення яких задач треба залучати державу, а з якими проблемами можна впоратися своїми силами? Який сервіс і софт потрібні, щоб громада самоорганізувалася? А що потрібно окрім софту? — це питання, над якими працюватимемо.
Проєкт будемо створювати за ментороством політологів, правників та власне мене, Яші Крамаренко 😇
🗓️ Міський табір триватиме на весняних канікулах з 25-29 березня в приміщенні школи на Подолі.
Опис інших проєктів і реєстрація на табір на сайті🕹️
Один з проектів, які можна обрати на Міському таборі для підлітків від школи Майбутні на весняних канікулах — це розробка таск-менеджера для громад.
Ми зберемо команду підлітків для розробки таск-менеджера, який зможе використовувати будь-яка політична спільнота — від шкільного самоврядування до об'єднаної територіальної громади. В режимі хакатону розробимо і запустимо продукт та почнемо тестувати його прямо на таборі.
Як громада може визначити свої проблеми і потреби? Хто в громаді може взятися за пошук рішення? До вирішення яких задач треба залучати державу, а з якими проблемами можна впоратися своїми силами? Який сервіс і софт потрібні, щоб громада самоорганізувалася? А що потрібно окрім софту? — це питання, над якими працюватимемо.
Проєкт будемо створювати за ментороством політологів, правників та власне мене, Яші Крамаренко 😇
🗓️ Міський табір триватиме на весняних канікулах з 25-29 березня в приміщенні школи на Подолі.
Опис інших проєктів і реєстрація на табір на сайті🕹️
❤6🔥5
Ми автоматизуємо тести не для тестувальників ✋🏻, а для розробників 🦾. Ціль не у тому щоб допомогти з мануальною рутиною тестувальникам на стадії тестування, а у тому щоб помогти розробникам не пропустити дефекти, які вони «тільки що наробили» і от от хочуть уже перевести таску в done чи ready for test... ну а далі «класичний пінг-понг» між тестерами і девами 🏓... Тут можна довго придиратись до формулювань, адже з якого це дива взагалі ділити на «це тестування» а це «ще не тестування». Так і є... Але тут трюк в акценті. Якщо трошки змінити кут зору, то можна почати бачити оптимізації там, де раніше вони були не очевидні. Якщо ми починаємо більше думати про розробників, максимально «ближче до них» впроваджувати автоматизацію і інтегрувати її саме у «життя девів», то починає виявлятись що навіть меншою кількістю покриття ми досягаємо більшого в плані якості. Деви тупо починають «менше робити багів».
І в цю ж тему відповідно до розгляду куча практик від розподілу покриття по піраміді до банального включання навіть end-to-end тестів у репу самої апки. Ясно що виключення є скрізь, але, можливо... і враховуючи принцип YAGNI - це «енд ту енд тести окремо від коду проекту є виключенням ніж навпаки». Раз уже наш клієнт - це деви, то чому б і тести не «тримати поближче до них»... Про от це «ближче до того де воно використовується» – ось ця гарна стаття https://kentcdodds.com/blog/colocation😉 Цікавий термін co-location... Вперше почув) Зазвичай це cohesion-ом обзиваю, та й оригінально з появою React-у саме цей термін і використовули як селлінг поїнт його підходу «вью та логіка вью разом», але щось є у ко-локації - якось більш прямо говорить про що воно 😎
І в цю ж тему відповідно до розгляду куча практик від розподілу покриття по піраміді до банального включання навіть end-to-end тестів у репу самої апки. Ясно що виключення є скрізь, але, можливо... і враховуючи принцип YAGNI - це «енд ту енд тести окремо від коду проекту є виключенням ніж навпаки». Раз уже наш клієнт - це деви, то чому б і тести не «тримати поближче до них»... Про от це «ближче до того де воно використовується» – ось ця гарна стаття https://kentcdodds.com/blog/colocation
Please open Telegram to view this post
VIEW IN TELEGRAM
Kentcdodds
Colocation
Maintainability through colocation
❤13
AutotestЯк
Го тестити virtuoso.qa на стрім https://youtube.com/live/UqiuIw9AsL0 !!!
Нарешті розтаймкодили стрім про Virtuoso, найцікавіше ось:
19:58 чи вміє virtuoso автоматично записати тест
32:31 virtuoso vs python у pycharm
37:00 користь від AI у Virtuoso
37:18 чи не краще copilot?
47:34 нема assert-ів? писати extensions на js о_О?
58:51 очікування vs реальність
1:05:48 Як підтримує API і чи воно треба? (Про те як правильно покривати API тестами)
1:09:20 як функіонал є базовим для таких фреймворків і чи є він тут?
1:11:24 про тестування CRM систем і чому virtuoso тут теж програє
1:12:19 модель конструктора як альтернатива
1:14:18 альтернатива з cucumber
1:19:33 великі проблеми класних фіч virtuoso
1:19:46 про AI testing в codeceptJS
1:20:59 про дебагінг в playwright
1:21:28 сумнівна перевага використання людськоподібної мови
1:23:17 codeceptJS - недоліки дизайну для рефакторингу
1:40:43 скільки часу потрібно, щоб вивчитись і лідувати проект з нуля?
1:43:58 кейс однієї студентки
1:45:20 про важливу навичку в навчанні і як її качати
1:53:47 градація рівнів спеціаліста від джуна до ліда
1:55:47 чи можна і варто всіх залучати до автоматизації?
2:02:03 чому Яша не активний у соц мережах
2:03:39 чим Яша займається?
2:13:50 про мрію в автоматизації
19:58 чи вміє virtuoso автоматично записати тест
32:31 virtuoso vs python у pycharm
37:00 користь від AI у Virtuoso
37:18 чи не краще copilot?
47:34 нема assert-ів? писати extensions на js о_О?
58:51 очікування vs реальність
1:05:48 Як підтримує API і чи воно треба? (Про те як правильно покривати API тестами)
1:09:20 як функіонал є базовим для таких фреймворків і чи є він тут?
1:11:24 про тестування CRM систем і чому virtuoso тут теж програє
1:12:19 модель конструктора як альтернатива
1:14:18 альтернатива з cucumber
1:19:33 великі проблеми класних фіч virtuoso
1:19:46 про AI testing в codeceptJS
1:20:59 про дебагінг в playwright
1:21:28 сумнівна перевага використання людськоподібної мови
1:23:17 codeceptJS - недоліки дизайну для рефакторингу
1:40:43 скільки часу потрібно, щоб вивчитись і лідувати проект з нуля?
1:43:58 кейс однієї студентки
1:45:20 про важливу навичку в навчанні і як її качати
1:53:47 градація рівнів спеціаліста від джуна до ліда
1:55:47 чи можна і варто всіх залучати до автоматизації?
2:02:03 чому Яша не активний у соц мережах
2:03:39 чим Яша займається?
2:13:50 про мрію в автоматизації
❤12🔥8👍1
Тільки помітив cyborg тести @xotabu4-a 😇. Ще не закопувався, але вже пахне тим напрямком про який я фантазував весь свій час у тестуванні. Попросив свою команду швиденько глянути, і чекнути що там і як, враховуючи те що ми наразі на прикладі тестомата студентам своїм синхронізацію автотестів з ТМС показуємо. Нижче репорт по кіборг-тестам з легким порівнянням на тестомат від Олени Долженко. А свої коментарі/короткі-враження залишу в коментарі до посту.
===============
"ТMS не потрібні" — ніби поки занадто гучно сказано, як можна зробити висновок з цієї презентації...
Є в Тестоматі, наприклад, зручні можливості, які не покриваються цією новою "кіборг"-тест-лібою:
- UI для зручного менеджменту тестів, клікаючи по кнопках — фільтрувати, сортувати, присвоювати теги, прив’язувати Jira-тікети, і потім ці теги прилетять і в код автотестів при синхронізації.
- створювати тест-плани за тегами, фільтрами і запускати їх з UI на віддаленому CI-сервері.
- Тестомат підтримує багато мов і тестових фреймворків, а ця нова ліба поки тільки JS+Playwright.
Це в рамках порівняння лише того функціоналу Тестомату, який був нам потрібен у рамках курсу, і відповідно досліджувався. Можливо, у Тестомату ще є багато фіч, якими ми ще не користувалися...
Щодо мануальних тестів — "кіборг"-варіант особисто мені на підставі власного досвіду з менеджменту мануальних тестів сподобався тим, що:
- всі тести — і мануальні, і автоматизовані — зможуть жити в одному проєкті під гітом. Писати, редагувати, рефакторити мануальні можна в улюбленій IDE з усіма її зручностями і фішками. Можна виносити мануальні степи в змінні, методи, робити з ними PO, щоб зручно перевикористовувати тощо.
- можна міксувати степи в одному тесті — автоматизовані, наприклад, прекондішени, посткондішени або самі деякі степи, плюс мануальні степи, де виконання скрипта призупиняється і керування браузером передається тестувальнику, який вручну робить те, що неможливо автоматизувати (наприклад, перевірка якості відеодзвінків, де логін, початок дзвінка можна автоматизувати, а степ, де треба перевірити, як чутно та видно відео, — вже мануальний, або щоб вручну пройти капчу).
Що варто було б прояснити на практиці згодом, коли буде вже реліз:
- для комплексного репортингу (і мануальні, і автоматизовані — в одному репорті) використовується окремий сервер — його треба піднімати та обслуговувати самостійно. І, мабуть, знадобляться значні ресурси, адже записується відео кожного рану, стан браузера на кожному степі, логи консолі...
- ніби ліба буде опенсорсною, тільки AI (за бажанням) платно, поки без подробиць. На сайті лише форма запису у вейт-лист.
Окремо зауважено в подкасті - не "злетить" з мобільними тестами, не буде повного крос-браузер, крос-ОС, обмежена версіями браузерів самого Playwright.
UPDATE від @xotabu4: «Доречі, після підкасту вже поінвестигейтив - з мобільними тестами взлетить, просто не буде такого класного репортингу»
🫶🏻
===============
"ТMS не потрібні" — ніби поки занадто гучно сказано, як можна зробити висновок з цієї презентації...
Є в Тестоматі, наприклад, зручні можливості, які не покриваються цією новою "кіборг"-тест-лібою:
- UI для зручного менеджменту тестів, клікаючи по кнопках — фільтрувати, сортувати, присвоювати теги, прив’язувати Jira-тікети, і потім ці теги прилетять і в код автотестів при синхронізації.
- створювати тест-плани за тегами, фільтрами і запускати їх з UI на віддаленому CI-сервері.
- Тестомат підтримує багато мов і тестових фреймворків, а ця нова ліба поки тільки JS+Playwright.
Це в рамках порівняння лише того функціоналу Тестомату, який був нам потрібен у рамках курсу, і відповідно досліджувався. Можливо, у Тестомату ще є багато фіч, якими ми ще не користувалися...
Щодо мануальних тестів — "кіборг"-варіант особисто мені на підставі власного досвіду з менеджменту мануальних тестів сподобався тим, що:
- всі тести — і мануальні, і автоматизовані — зможуть жити в одному проєкті під гітом. Писати, редагувати, рефакторити мануальні можна в улюбленій IDE з усіма її зручностями і фішками. Можна виносити мануальні степи в змінні, методи, робити з ними PO, щоб зручно перевикористовувати тощо.
- можна міксувати степи в одному тесті — автоматизовані, наприклад, прекондішени, посткондішени або самі деякі степи, плюс мануальні степи, де виконання скрипта призупиняється і керування браузером передається тестувальнику, який вручну робить те, що неможливо автоматизувати (наприклад, перевірка якості відеодзвінків, де логін, початок дзвінка можна автоматизувати, а степ, де треба перевірити, як чутно та видно відео, — вже мануальний, або щоб вручну пройти капчу).
Що варто було б прояснити на практиці згодом, коли буде вже реліз:
- для комплексного репортингу (і мануальні, і автоматизовані — в одному репорті) використовується окремий сервер — його треба піднімати та обслуговувати самостійно. І, мабуть, знадобляться значні ресурси, адже записується відео кожного рану, стан браузера на кожному степі, логи консолі...
- ніби ліба буде опенсорсною, тільки AI (за бажанням) платно, поки без подробиць. На сайті лише форма запису у вейт-лист.
Окремо зауважено в подкасті - не "злетить" з мобільними тестами, не буде повного крос-браузер, крос-ОС, обмежена версіями браузерів самого Playwright.
UPDATE від @xotabu4: «Доречі, після підкасту вже поінвестигейтив - з мобільними тестами взлетить, просто не буде такого класного репортингу»
🫶🏻
YouTube
Хотемський про кіборг тести та DOU Day #подкаст
Говорили про DOU Day і новий підхід у ведені тестової документації від Олександра Хотемського, TMS вже не будуть вам потрібні... треба лише.... .
HOT Testing https://t.me/js_for_testing @HOTtesting
Гена Міщевський: https://linktr.ee/HennadiiMishchevskyi…
HOT Testing https://t.me/js_for_testing @HOTtesting
Гена Міщевський: https://linktr.ee/HennadiiMishchevskyi…
❤15🔥1
Forwarded from Hot testing Channel (roman marinsky)
#діскорд 18:00 сьогодні буде остаточний розйоб Playwright MCP сервера
Та порівняємо Windsurf/Cursor з JetBrains IDEs + Julia
https://discord.gg/JeeAakd5?event=1364312617640001657
Та порівняємо Windsurf/Cursor з JetBrains IDEs + Julia
https://discord.gg/JeeAakd5?event=1364312617640001657
❤5
Треба допомога:) Ми з командою час від часу проводимо співбесіди для наших клієнтів, і я люблю понадавати якихось реальних задачок на співбесіді, наприклад, провести повноцінне код рев'ю якогось фреймворку з тестами на Web UI. І от у мене є такі приклади проектів на веб, але немає на апі :). Треба такий проект щоб якби не все там було "ідеально", щоб було що порев'ювити. Може хтось може поділитись своїм, чи "друга" проектом на гітхабі з апі-тестами? Той проект який мені найбільше сподобається – тому ще й прийшлю відповідне код-рев'ю персонально від себе :)
❤6