msenyk / sf-practicum-2022

Виробнича практика на платформі Salesforce
0 stars 0 forks source link

Створити Apex тести для коду генерації турів #11

Open foxxua opened 2 years ago

foxxua commented 2 years ago

Це дуже гарна можливісь попрактикуватися в тестах та TDD підході. Потрібно продумати вхідні та вихідні дані, та різні кейси які б на Вашу думку потрібно протестувати. Для кожного кейсу створити окремий тестовий метод. Для кожного класу створити окремий тестовий клас. Як найбільш абстрагуватися від конкретної реалізації сервісу та контролеру.

msenyk commented 2 years ago

@Rifleborn Тести виконуються вірно, але вони прив'язані до даних, які існують в пісочниці. Варто писати тести, що самі створюють тестові дані. Для поліпшення якості теста треба зробити наступне:

Rifleborn commented 2 years ago

Виправив недоліки в ExcursionControllerTest (аналогічно виправив і BookingEditorTest); Створив метод testGenerateToursInAdvance для ExcursionControllerTest (метод для перевірки створення турів у яких розклад на деіклька днів у тиждень); Створив метод makeNewTour в класі ExcursionController (потрібен для testGenerateToursInAdvance).

msenyk commented 2 years ago

@Rifleborn Зміни виглядають гарно. Але два останні пункти не виконані. Поясніть призначення методу makeNewTour з класу ExcursionController.

Rifleborn commented 2 years ago

@Rifleborn Зміни виглядають гарно. Але два останні пункти не виконані. Поясніть призначення методу makeNewTour з класу ExcursionController. (cacheable=true) здається прибрав З приводу методу, наскільки я зрозумів Сергію Грудіну порекомендували створити клас ExcursionController, в якому він створив метод generateTours який викликається також при тестуванні. Метод makeNewTour аналогічно використовується при тестуванні; я розумію що можна обійтись без нього і протестувати оригінальний метод makeNewTour викликавши його напряму, але я додав його в ExcursionController щоб він доповнював generateTours.

msenyk commented 2 years ago

@Rifleborn В нас є LWC компонент gen_Tour (назву треба буде змінити, але не зараз), серверний контролер ExcursionController та сервіс клас ToursGeneratorService. Зараз компонент напряму викликає метод сервісного класу ToursGeneratorService.generateTours. Так робити не рекомендується. Компоненти мають викликати лише методи контролерів. Ваша задача:

  1. Використати в компоненті метод контролеру ExcursionController.generateTours
  2. Видалити зайвий метод makeNewTour з контролеру
  3. Прибрати анотацію '@AuraEnabled' з сервісного класу
  4. Попросити колег стягнути ваші зміни з орги, щоб вони не перезатирали ваші зміни.
  5. Перевірити чи правильно працюють тести і виправити їх у разі чого
  6. Я не побачив який тестовий метод перевіряє ситацію, коли в нас кілька турів в одному тижні. Там має бути екскурсія яка запланована хоча б на 2 дні, наприклад, середу та суботу.
ViktorNosenko commented 2 years ago

1) Наразі загальне покриття сягає 68%. Варто підняти покриття тестів мінімум до 75%. 2) В багатьох тестових класах все ще є зустрічається аннонація (SeeAllData=true). Використовуйте для тестування данні згенеровані в методі з анотацією @TestSetup. 3) Частина класів не покрита тестами на 100%. Це повязано з:

В інтернеті описано декілька способів яким чином ми можемо покрити і ці ділянки коду.

Корисні посилання: Testing Best Practices Using Test Setup Methods Isolation of Test Data from Organization Data in Unit Tests Test Coverage For Try-Catch Blocks In Apex Classes

Rifleborn commented 2 years ago

Покриття тестами - 92%

ViktorNosenko commented 2 years ago

Покриття тестами - 92%

Тести виглядають гарно, але є речі які можна покращити.

Питання до роздумів: 1) Чи потрібні в тестовому класі ExcursionControllerTest статичні змінні testExn та testMultiExn? 2) Чи можливо щось покращити в тест сетапі для цього тестового класу? 3) Чи можна якось модифікувати метод getExcId() для того щоб він був більш універсальний? 4) Методи startTest() і stopTest() використовуються для того щоб прослідкувати за СФ лімітами. Тобто будь-якому коду, який виконується після виклику startTest і до stopTest, призначається новий набір СФ лімітів. Тому бажано:

Більше про це тут - Using Limits, startTest, and stopTest

Rifleborn commented 2 years ago
             Id excId = getExcId('TestExcursion');
     Test.startTest();
        Integer result = ExcursionController.generateTours(date.parse('20/01/2022'), date.parse('30/01/2022'), excId);
        Test.stopTest();
Rifleborn commented 2 years ago

Все переписав/дописав, тільки питання ось це лишилось

  • виклик методу що тестується вже з підготовленим набором данних Тобто якщо в мене є ось така конструкція:
    Test.startTest();
       Integer result = ExcursionController.generateTours(date.parse('20/01/2022'), date.parse('30/01/2022'), getExcId('TestExcursion'));
       Test.stopTest();
    То чи варто її переписати ось так? 
             Id excId = getExcId('TestExcursion');
     Test.startTest();
        Integer result = ExcursionController.generateTours(date.parse('20/01/2022'), date.parse('30/01/2022'), excId);
        Test.stopTest();
ViktorNosenko commented 2 years ago

Так. Паттерн +- такий:

@IsTest
static void someTestMethod() {
        // підготовка данних для тестування 
        // отримання записів з БД, зміна налаштувань якщо потрібно, створення додаткових тестових данних і тд.

        Test.startTest();
        // виклик логіки що буде тестуватись (виклик методу, запуск батчу і тд.)
        // перевірка результатів (assert) (опціонально, краще винести в блок нижче)
        Test.stopTest();

        // перевірка результатів (assert) 
        // виконання перевірок саме тут робить читання простішим а код більш структурованим
}
Rifleborn commented 2 years ago

Ок, здається всюди переписав

Rifleborn commented 2 years ago

Треба переробити тест через правки в Booking Editor, в телеграм скинув скріншоти з проблемою.

Rifleborn commented 2 years ago

Переробив трохи BookingEditorTest. Наразі повне покриття 95%, Сергій Грудін дописує тестовий клас для TourNameTriggerHandler

ViktorNosenko commented 2 years ago
ViktorNosenko commented 2 years ago

Вже набагато краще!!! Але ще є що покращувати.

1) Цей та схожі блоки коду можна спростити.

System.debug(e.getMessage());
Boolean exceptionThrown = e.getMessage().contains('There are no avaliable tickets') ? true : false;
System.AssertEquals(exceptionThrown, true);

2) Чи потрібен нам блок catch в позитивних сценаріях тестування? Як приклад метод testCancelBooking.

Rifleborn commented 2 years ago

Переглянув код, здається все виправив

Rifleborn commented 2 years ago

Перекинув в in progress, якась помилка з тестовими методами, дивлюся

Rifleborn commented 2 years ago

Здається все дописав в BookingEditorTest.