Донецкий техникум промышленной автоматики

Ефективні методи автоматизації тестування в Rational Functional Tester

  1. Альтернативні способи пошуку об'єктів і їх властивостей
  2. Запит і настройка значень властивостей об'єктів
  3. Лістинг 1: Використання методу getProperty
  4. Малюнок 1. Властивості в карті тестових об'єктів
  5. Способи пошуку тестових об'єктів
  6. Рішення проблеми неточного розпізнавання об'єктів
  7. Лістинг 2: Використання ProcessTestObject для прив'язки додатки
  8. Виконуємо прибирання-видалення реєстрації тестових об'єктів
  9. Способи вирішення поширених проблем з браузерами
  10. Усунення небажаної поведінки за допомогою методу .readystate
  11. Значення readyState в Rational Functional Tester
  12. Лістинг 3. Перевірка стану готовності readyState
  13. Поліпшення виконання тесту за допомогою методу waitForExistence
  14. Обробка незапланованих активних вікон
  15. Лістинг 4. Очікування спливаючого діалогового вікна
  16. Подумайте про використання нетрадиційних точок верифікації
  17. Точки верифікації, що додаються вручну
  18. Лістинг 5. Використання методу vpManual
  19. Динамічні точки верифікації
  20. Лістинг 6. Використання методу vpDynamic
  21. Детально про використання низькорівневих команд
  22. Малюнок 2: Емулятор VTech Helio Emulator
  23. Лістинг 7. Використання низькорівневих сценаріїв в Rational Functional Tester
  24. Малюнок 3: Малювання с помощью Microsoft Paint в емуляторі Helio
  25. Поліпшення сценаріїв за допомогою допоміжного суперкласу
  26. Ресурси для скачування

Якщо ви часто використовуєте інструменти автоматизації тестування, то, ймовірно, вже знайомі з концепцією інфраструктури автоматизації тестування. Тестировщики часто просять дати їм рекомендації, консультації та вирішення по інфраструктурі, але інфраструктура - це тільки половина того, що необхідно мати на увазі. Ваш підхід до структурування тестового коду з метою поліпшення тестування додатків - це другий крок на шляху до ефективної автоматизації.

У цій статті ми розглянемо перший крок, який полягає в розумінні того, як ефективно використовувати наявні інструменти тестування. Це крок можна розділити на кілька тем:

  • Об'єкти і властивості;
  • Поширені проблеми, пов'язані з браузерами;
  • Точки верифікації;
  • Низькорівневі команди;
  • Допоміжний суперклас сценарію.

По кожній з цих тем є посилання на додаткову інформацію, які можна знайти в розділі ресурси в кінці цієї статті.

Примітка:
При написанні цієї статті автор використовував такі програми та

  • IBM® Rational® Functional Tester версії 7.0.0;
  • Microsoft® Internet Explorer® версії 6.0.2900.2180, SP2;
  • Операційну систему Microsoft® Windows® XP Professional, SP2;

Альтернативні способи пошуку об'єктів і їх властивостей

Такі компоненти, як діалогові вікна, кнопки команд і мітки, мають пов'язані з ними фрагменти інформації, які називаються властивостями. Властивості мають імена і значення. Нам часто бувають потрібні різні властивості тестованих об'єктів для того, щоб можна було виконати будь-який вид верифікації або програмним способом визначити подальші дії сценарію тестування. У цьому розділі розповідається про об'єкти, їх властивості та способи, що дозволяють взаємодіяти з ними в рамках сценарію.

Запит і настройка значень властивостей об'єктів

Чи виникало у вас коли-небудь бажання динамічно в процесі виконання програми порівняти попередній варіант значення з поточним значенням? А може бути, вам хотілося додати в сценарій Rational Functional Tester перехід, заснований на поточному значенні властивості, що міститься в будь-якому об'єкті? Витягти значення властивості можна програмним шляхом за допомогою виклику методу getProperty.

У прикладі з лістингу 1 метод getProperty використовується для того, щоб визначити, чи містить мітка повідомлення про успішне виконання. Якщо містить, то буде натиснута кнопка OK. Якщо немає, то буде натиснута кнопка Cancel.

Лістинг 1: Використання методу getProperty

if ( "SUCCESS" .equals (dialog_htmlDialogStatic (). getProperty ( ". text"))) {dialog_htmlDialogButtonOK (). click (); } Else {dialog_htmlDialogButtonCancel (). Click (); }

Якщо потрібно дізнатися, якими властивостями володіє деякий об'єкт, можна відкрити карту тестових об'єктів Test Object Map і переглянути перераховані в ній властивості. (Див. Рисунок 1.)

Малюнок 1. Властивості в карті тестових об'єктів
Якщо ви часто використовуєте інструменти автоматизації тестування, то, ймовірно, вже знайомі з концепцією інфраструктури автоматизації тестування

Крім того, можна переглянути доступні властивості, записавши тимчасову точку верифікації (verification point, VP) властивостей об'єкта або вставивши команду для вилучення значення властивості в змінну за допомогою майстра VP and Actions.

Примітка:
Rational Functional Tester також підтримує метод setProperty. Однак цей метод не дає гарантії результату: Чи не користуйтеся ним, якщо не впевнені в результаті. Причина полягає в тому, що метод setProperty викликає внутрішні методи, які можуть порушити цілісність тестованого програми.

Тепер, коли ви знаєте, як отримати властивості об'єктів, ви можете задати питання: "А як можна знайти сам об'єкт?" Гарне питання.

Способи пошуку тестових об'єктів

Основний компоновочне блок сценарію Rational Functional Tester - це постійно використовується тестовий об'єкт, TestObject .TestObject є точкою з'єднання між відтвореним сценарієм і тестованим додатком. Кожному TestObject в створеному сценарії тестування відповідає об'єкт в додатку, на базі якого ведеться запис сценарію, і цей об'єкт тепер присутня і в карті тестових об'єктів Test Object Map.

Швидше за все, ви зазвичай взаємодієте з тестовими об'єктами TestObject з використанням карти об'єктів. Однак Rational Functional Tester підтримує також кошти для програмного пошуку TestObject. Пошук ведеться по парі ім'я-значення, що визначає властивості TestObject або TestObjects, які потрібно знайти. Пошук може бути глобальним або обмежуватися нащадками батьківського вузла TestObject.

Rational Functional Tester використовує об'єкт з ім'ям RootTestObject для глобального уявлення тестованого програми.

  • Якщо ви хочете виконати пошук по всьому додатком, викличте пошуковий метод для RootTestObject.
  • Якщо потрібно знайти конкретний об'єкт, просто викличте пошук для цього TestObject. Пошук по конкретному TestObject знайде тільки дочірні об'єкти цього TestObject

Марк Новацький (Mark Nowacki) і Ліза Нодвелл (Lisa Nodwell) написали статтю про правильне розуміння і використання методу TestObject.find (див. Другий лістинг в розділі ресурси ). Я не наводжу свої приклади коду, щоб ви могли познайомитися з кодом, написаним цими авторами. Вони виконали велику роботу, пояснивши і проілюструвавши теоретичні принципи на практичних прикладах.

Рішення проблеми неточного розпізнавання об'єктів

Час від часу Rational Functional Tester не може розрізнити два об'єкти, які вели себе схожим чином при відтворенні сценарію. Найчастіше це відбувається в тому випадку, якщо одночасно відкрито два браузера або два примірники однієї програми. Якщо запущені два Web-браузера, то Rational Functional Tester намагається вирішити неоднозначність, використовуючи якір для визначення цільового об'єкта. Тепер ви знаєте, як використовувати пошуковий метод, і можете ідентифікувати екземпляри браузера або програми за допомогою посилання на TestObject.

Одночасний запуск декількох примірників додатки під час відтворення сценарію веде до неоднозначності визначення мети таких команд, як object () або click (). Щоб вирішити цю неоднозначність, можна скористатися ProcessTestObject при виклику команди startApp. У прикладі з лістингу 2 ProcessTestObject діє як якір, який допомагає знайти потрібну програму.

Лістинг 2: Використання ProcessTestObject для прив'язки додатки

ProcessTestObject pto1 = startApp ( "ApplicationOne"); ProcessTestObject pto2 = startApp ( "ApplicationTwo"); object (pto1, DEFAULT) .click ();

Виконуємо прибирання-видалення реєстрації тестових об'єктів

Заключний аспект використання методу пошуку стосується видалення реєстрації об'єктів. Метод TestObject.find повертає нову посилання на TestObject (яка іноді називається обмеженою посиланням, пошуковій посиланням або несопоставленние посиланням). Такі посилання утримують доступ до об'єкта доти, поки ви явно не скасуєте їх реєстрацію, а це значить, що вони можуть викликати проблеми, якщо залишити їх без уваги.

Rational Functional Tester видаляє реєстрацію обмежених посилань тільки після завершення виконання всього тесту, а не одного конкретного сценарію. Поки існує обмежена посилання на об'єкт, Rational Functional Tester може не допустити повного звільнення об'єкта в додатку. Наприклад, поки ви зберігаєте обмежену посилання на Java ™-об'єкт, цей Java-об'єкт не вважається які втратили актуальність і підлягають видаленню. Тому ми рекомендуємо явно видалити реєстрацію всіх створених пошукових посилань відразу після того, як вони стануть непотрібними.

Клас RationalTestScript містить кілька методів, що видаляють посилання на тестові об'єкти TestObjects:

  • com.rational.test.ft.script;
  • RationalTestScript.unregister;
  • unregisterAll.

застереження:
Якщо ви працюєте з TestObjects безпосередньо, то використання таких посилань може викликати нестабільність роботи вашого додатка. Намагайтеся не зволікати з видаленням реєстрації тестових об'єктів TestObjects.

Способи вирішення поширених проблем з браузерами

Нижче перераховані деякі поширені проблеми, з якими можна зустрітися при тестуванні HTML-додатків

Усунення небажаної поведінки за допомогою методу .readystate

Якщо стан вашого браузера або об'єктів в браузері не відповідає очікуваному, можна зіткнутися з небажаним (дивним, непередбачуваним) поведінкою при спробі взаємодії з браузером або об'єктами, особливо якщо багато взаємодій виконується не в рамках допоміжних методів. Саме тому перевірка стану готовності readyState Web-браузера або будь-якого з об'єктів повинна стати звичною справою.

Значення readyState в Rational Functional Tester

Значення Стан Опис 0 uninitializedObject Об'єкт инициализирован даними 1 loadingObject Об'єкт в стані завантаження даних 2 loadedObject Об'єкт завершив завантаження даних 3 interactiveUser Користувач може взаємодіяти з об'єктом, навіть якщо він завантажений не повністю 4 completeObject Ініціалізація об'єкта завершена

Якщо ви знаєте, що належить взаємодія з великою таблицею, деревом (каталогом файлів) або HTML-документом, варто перевірити стан цих об'єктів (Лістинг 3) до початку взаємодій.

Лістинг 3. Перевірка стану готовності readyState

while (Integer.parseInt (object.getProperty ( ". readyState"). toString ()) <4) {sleep (2); }

Поліпшення виконання тесту за допомогою методу waitForExistence

Можливо, ви також помітили, що при відтворенні сценаріїв тестування запуск браузера все ще триває в той час, як вікно відтворення сценарію очікує виконання першої команди. Така поведінка обумовлюється тим, що більш сучасні браузери працюють повільніше, можливо, через своїх додаткових елементів, наприклад, вкладок, які необхідно завантажити саме при запуску. Тому при запуску браузера рекомендується використовувати метод waitForExistence. Це можна зробити за допомогою точки верифікації Wait for Selected TestObject:

  1. В процесі запису сценарію запустіть додаток;
  2. Натисніть кнопку Insert Verification Point or Action Command на панелі інструментів Recording;
  3. На сторінці вибору об'єктів Select an Object майстра Verification Point and Action Wizard натисніть лівою кнопкою миші на значку Object Finder і перетягніть його на HTML-сторінку (не просто в область вікна браузера, а саме на сторінку);
  4. Натисніть кнопку Next;
  5. На сторінці вибору дій Select an Action майстра Verification Point and Action Wizard встановіть прапорець Wait for Selected TestObject;
  6. Якщо потрібно, зніміть прапорець для Use the defaults, щоб змінити параметри максимального часу очікування Maximum Wait Time і інтервалу перевірок Check Interval, які дорівнюють відповідно 2 хвилинах і 2 секундам;
  7. Натисніть кнопку Finish.

Однак вам, можливо буде простіше самостійно додати виклик після команди startApp. Все, що вам доведеться зробити - це додати посилання на тестовий об'єкт BrowserTestObject і виклик методу waitForExistence.

Обробка незапланованих активних вікон

З браузерами (і деякими Java-додатками) пов'язана ще одна поширена проблема - це численні спливаючі вікна. Незаплановані активні вікна найбільш часто зустрічаються, коли сценарії виконуються на різних машинах або з різними браузерами, або якщо браузери мають різні настройки.

Втім, в довідковій системі Rational Functional Tester описані два ефективних рішення (одне просте, інше складніше). Одне з рішень - скористатися класичною методикою try-and-catch (Лістинг 4) і дочекатися появи повідомлення. Якщо повідомлення не з'явиться, можна продовжувати.

Лістинг 4. Очікування спливаючого діалогового вікна

try {// Dialog_HtmlDialogButtonOK (). waitForExistence (5,1); Dialog_HtmlDialogButtonOK (). Click (); } Catch (ObjectNotFoundException e) {}

Порада:
Якщо очікування повинно тривати певний час, можна видалити з коду рядок після символу коментаря.

Ще одне рішення, яке вимагає трохи більше зусиль - це реалізація простої перевірки, аналогічної перевірки з виключення onObjectNotFound. Включивши цю реалізацію у допоміжний суперсценарій, можна обробляти події для будь-якого сценарію Rational Functional Tester, що є розширенням цього допоміжного суперкласу (докладніше про це далі в цій статті).

Подумайте про використання нетрадиційних точок верифікації

Крім точок верифікації, які визначаються під час запису, в сценарій тестування Rational Functional Tester можна включити і додаткові точки верифікації (і не тільки за допомогою команди Insert at Cursor). Включення в сценарій точок верифікації вручну і динамічно дозволяє визначити дані для порівняння по об'єкту, який не включений в карту тестових об'єктів.

Точки верифікації, що додаються вручну

Додавання точок верифікації вручну корисно при самостійному створенні даних для точок верифікації, коли потрібно порівняти дані. Наприклад, дані можуть бути результатом обчислень або відбуватися з зовнішнього джерела, наприклад, з таблиці, пулу даних, бази даних або призначеного для користувача обчислення.

Об'єкти додаються вручну точок верифікації створюються за допомогою методу vpManual, як показано в лістингу 5.

Лістинг 5. Використання методу vpManual

vpManual ( "ManualVP_01", "Check something manually."). performTest (); // або vpManual ( "ManualVP_01", "Check something manually.", "Check something manually."). PerformTest ();

При першому виконанні точки верифікації, доданої вручну, якщо об'єкт точки верифікації ще не існує, буде передано базове значення (яке потім можна переглянути і змінити в Rational Functional Tester, як і значення будь-який інший точки верифікації). У файлі журналу буде написано: Created verification point baseline.

Починаючи з цього моменту, всі наступні виклики методу vpManual для цієї точки верифікації будуть порівнювати актуальну точку з базовою. Як видно з лістингу 5, метод vpManual можна викликати, передавши йому обидва результату - базовий і актуальний. У цьому випадку об'єкт точки верифікації в Rational Functional Tester ігнорується.

Динамічні точки верифікації

Іноді виникає необхідність у виконанні точки верифікації в тестових об'єктах, які не включені в карту об'єктів. З цією метою можна використовувати динамічні точки верифікації за допомогою методу vpDynamic (лістинг 6). Динамічні точки верифікації відтворюють відповідний призначений для користувача інтерфейс при наступному прогоні сценарію. Можна вставити дані точки верифікації, протестовані для об'єкта, зазначеного сценарієм. В цьому випадку вам не доведеться вручну відтворювати тест до відповідного стану, перш ніж ви зможете записати точку верифікації.

Якщо ви передаєте сценарієм тільки ім'я точки верифікації, то при наступному відтворенні цього сценарію буде активований майстер записи точок верифікації Recording Verification Point and Action Wizard. За допомогою цього майстра можна задати тестові об'єкти TestObject і базові дані для наступних виконань тесту.

Лістинг 6. Використання методу vpDynamic

vpDynamic ( "DynamicVP_01"). performTest (); // або vpDynamic ( "DynamicVP_01", TestObjectHere ()). PerformTest ();

застереження:
Другий приклад з лістингу 6 вимагає передачі сценарієм актуального тестового об'єкта TestObject. Хоча вказаний TestObject не включений в карту тестових об'єктів, він постійно повинен бути одним і тим же об'єктом, щоб результати мали сенс. Тому ще раз повторюю: користуючись методом TestObjects, будьте уважні.

Поширеною помилкою при використанні цього методу є невикористання методу performTest. Це допустимо і виконується без попереджень, але при виконанні сценарію цікавить нас дія не виконується.

Детально про використання низькорівневих команд

Низькорівневе відтворення емулює точні переміщення миші і маніпуляції з клавіатурою, що виконуються користувачем. Таке відтворення сценаріїв дозволяє більш точно управляти окремими діями користувачів, наприклад, в програмах для векторного малювання (креслення), емуляторах PDA та інших нетрадиційних інструментах, які враховують властивості об'єктів, які зовсім не схожі на звичайні команди click і input.

Наприклад, припустимо, що ви тестируете розпізнавання ручного введення в емуляторі VTech Helio Emulator, який показаний на малюнку 2.

Малюнок 2: Емулятор VTech Helio Emulator

Традиційні сценарії Rational Functional Tester в додатках, подібних Helio Emulator, малоефективні. Фактично, як я писав у попередній статті про застосування низькорівневих сценаріїв в IBM® Rational® Robot (див. Розділ ресурси ), Майже єдиним вибором для таких додатків залишається низкоуровневая запис. Перейшовши на низький рівень, ви зможете відтворити окремі компоненти клацання мишею.

Клас RootTestObject містить два низькорівневих методу:

  • emitLowLevelEvent (LowLevelEvent)
  • emitLowEvent (LowLevelEvent [])

Нижче наводиться список методів для конструювання низькорівневих подій LowLevelEvents в фабриці SubitemFactory:

  • delay (int) Примітка: в мілісекундах
  • keyDown (string)
  • keyUp (string)
  • mouseMove (point)
  • mouseWheel (int)
  • leftMouseButtonDown ()
  • leftMouseButtonUp ()
  • rightMouseButtonDown ()
  • rightMouseButtonUp ()
  • middleMouseButtonDown ()
  • middleMouseButtonUp ()

Код сценарію, представлений в лістингу 7, малює на блокноті введення рукописного введення для Helio в Microsoft® Paint®.

Лістинг 7. Використання низькорівневих сценаріїв в Rational Functional Tester

afx10000008window (). click (atPoint (100,100)); LowLevelEvent llEvents [] = new LowLevelEvent [7]; llEvents [0] = mouseMove (atPoint (100,100)); llEvents [1] = leftMouseButtonDown (); llEvents [2] = delay (250); llEvents [3] = mouseMove (atPoint (105,120)); llEvents [4] = delay (250); llEvents [5] = mouseMove (atPoint (110,100)); llEvents [6] = leftMouseButtonUp (); getRootTestObject (). emitLowLevelEvent (llEvents);

Код, представлений в лістингу 7, генерує в вікні документа програми букву V як показано на малюнку 3.

Малюнок 3: Малювання с помощью Microsoft Paint в емуляторі Helio

Чи є Недоліки у Цій грандіозно ефектівної Функції? Наскільки я знаю, на Відміну Від Rational Robot, весь цею код вам придется писати вручну. Мені НЕ відомій способ перемикань на низкоуровневую записів у Rational Functional Tester. Альо и описаного Цілком достаточно. Якщо ви дійсно тестируете програму типу Helio, вам все одно доведеться створити методи багаторазового використання для написання букв. Тому, найімовірніше, вам потрібно буде розібратися з усіма літерами всього один раз.

У будь-якому випадку запам'ятайте цю функцію, тому що бувають моменти, коли ви просто не в змозі отримати комбінації типу click-drag в процесі запису сценарію. У таких випадках іноді може допомогти низкоуровневая запис.

Поліпшення сценаріїв за допомогою допоміжного суперкласу

Якщо ви не читали статтю Денніса Шульца (Dennis Schultz) "Creating a super helper class in IBM Rational Functional Tester," (Створення допоміжних суперкласів в IBM Rational Functional Tester), перейдіть до розділу ресурси і прочитайте її зараз. Ця стаття - найкращий ресурс для вивчення того, як працює суперклас, з усіх, які мені доводилося бачити. Допоміжні класи допомагають додати функціональності вашим сценаріями тестування.

За замовчуванням, всі сценарії Rational Functional Tester є розширення класу RationalTestScript і тому успадковують ряд методів (таких як callScript). Більш досвідчені тестувальники можуть віддати перевагу створення власних допоміжних суперкласів, щоб розширити клас RationalTestScript, додавши в RationalTestScript власні методи або замінивши існуючі.

Ви можете визначити допоміжний суперклас, який Rational Functional Tester буде використовувати при кожному створенні або запису сценарію в проекті. Цей допоміжний клас за замовчуванням вказується у властивостях проекту функціонального тесту. Крім того, у властивостях проекту функціонального тесту можна вказати допоміжний суперклас для окремого сценарію на сторінці властивостей сценарію. Після створення сценарій зберігає посилання на суперклас за замовчуванням як на власний допоміжний суперклас.

Допоміжні суперкласу корисні для спільного використання функцій декількома сценаріями. Саме під допоміжний суперклас можна помістити код, який ви хочете зробити доступним для кожного сценарію. Будь розміщений тут код буде успадковуватися будь-яким допоміжним класом, які розширюють ваш допоміжний суперклас.

Ресурси для скачування

Схожі тими

  • Оригінал статті: Effective test automation techniques for Rational Functional Tester (EN);
  • Якщо ви все ще не відчуваєте впевненості при використанні налагоджувальних функцій в Rational Functional Tester, прочитайте статтю Use the debugging feature of IBM Rational Functional Tester 6.1 to ensure application quality (EN) (Використання налагоджувальних функцій IBM Rational Functional Tester 6.1 для забезпечення якості додатків), автори Аллен Стокер (Allen Stoker) і Майкл Келлі (Michael Kelly) (developerWorks, червень 2005 року);
  • В якості додаткової інформації по використанню методу TestObject.find автор рекомендує статтю Using IBM Rational Functional Tester: Understanding and Using the TestObject.find Method (EN) (Робота з IBM Rational Functional Tester: метод TestObject.find і його використання), автори Марк Новацький (Mark Nowacki) і Ліза Нодвелл (Lisa Nodwell) (developerWorks, липень 2006);
  • Якщо ви ще не експериментували зі створенням допоміжних класів в Rational Functional Tester, прочитайте статтю Creating a super helper class in IBM Rational Functional Tester (EN) (Створення допоміжних суперкласів в IBM Ratioinal Functional Tester), автор Денніс Шульц (Dennis Schultz) (developerWorks, грудень 2003 г.);
  • прочитайте Introduction to NET Rational Functional Tester 6.1 (EN) (Введення в IBM Rational Functional Tester 6.1). Інструмент IBM Rational Functional Tester призначений для автоматизації процесу тестування додатків Java, .NET, а також додатків, що використовують Інтернет-технології. Зустрітися з функціями і інструментами даної програми;
  • відвідайте розділ Rational Functional Tester Web-сайту developerWorks, щоб отримати вичерпну інформацію по даній програмі; (EN)
  • відвідайте розділ Rational сайту developerWorks; тут ви знайдете технічні ресурси і передові методи для продуктів платформи Rational Software Delivery Platform;
  • Отримання дозволу на використання інформаційний бюлетень сайту IBM developerWorks , В щодня повідомляється про нові навчальних посібниках, статтях, завантажуються файли, що розміщуються на Web-сайті developerWorks, а також нові повідомлення членів спільноти і події; (EN)
  • Підпішіться на інформаційний бюлетень розділу Rational сайту developerWorks . Слідкуйте за розділом Rational сайту developerWorks. Щотижня ви будете отримувати інформацію про нові технічні ресурси і кращі методи роботи з Rational Software Delivery Platform; (EN)
  • попрацюйте з Rational Functional Tester 7.0 . Завантаження ознайомлювальної версії безкоштовна, але вимагає реєстрації на Web-сайті; (EN)
  • завантажте оціночні версії програмних продуктів IBM і попрацюйте з інструментами розробки додатків і сполучною ПО з DB2®, Lotus®, Rational®, Tivoli®і WebSphere®. (EN)

Підпішіть мене на ПОВІДОМЛЕННЯ до коментарів

А може бути, вам хотілося додати в сценарій Rational Functional Tester перехід, заснований на поточному значенні властивості, що міститься в будь-якому об'єкті?
Тепер, коли ви знаєте, як отримати властивості об'єктів, ви можете задати питання: "А як можна знайти сам об'єкт?