понеділок, 28 грудня 2015 р.

Що таке "добрі локатори" на web-сторінках

Писання автоматизованих тестів для web GUI складається, великою мірою, не тільки з логіки перевірок та вигадування моделі тестових даних, як під час тестування API, а ще й із прив’язування логіки тесту до правильних елементів на сторінці, тобто - побудови локаторів.
Окрім усім очевидних методів пошуку елемента за id чи ім’ям класу (class name), іноді у нагоді стають css-selector'и та xpath'и, що дозволяють вкласти певну логіку у спосіб пошуку, та значно полегшити код самої перевірки, звівши її до простої присутності елемента за зазначеним локатором. Але який локатор вважати добрим?


Існує чимало довідкових сайтів і про xpath, і про css-селектори, наприклад:
Примеры XPath - MSDN - Microsoft
XPath | MDN - Mozilla
І знову основи CSS | CSS Для Початківців
ну і звичайно http://automated-testing.info/ та google допоможуть із будь-чим.

До локаторів, не залежно від методу, існують явні та очевидні вимоги:
  1. Постійне спрацьовування, тобто вибраний спосіб пошуку має працювати завжди.
  2. Унікальність на сторінці - пов’язано із попереднім, знайдений елемент не переплутається із схожим/батьком/нащадком.
На цьому закінчується список явних вимог.

Як і з кодом користувацьких додатків, діє закон: "Працює - не чіпай!"
У цьому законі немає нічого поганого, і я сам є його палким адептом. Але слабина його в тому, що він говорить про зміни всередині системи, не враховуючи зміни зовнішніх чинників. Тобто, коли щось зміниться на UI, чи це буде баг, чи не баг, наш тест впаде, і ми все одно змушені будемо його виправляти. І у той веселий час глибокого дебагу краще нам розуміти, що той чи інший локатор шукає.
Приклад:
Ми написали тест, він ганявся півроку, і от, після зміни у незв’язаних із ним модулях, він впав із передсмертним криком "Element not found." Автор тесту недоступний, бо вже у відпустці/Польщі/декреті, і вам терміново треба все пофіксити. Ви пробуєте пройти той самий сценарій руками, але тест лише перевіряє, чи видний на сторінці елемент із наступним локатором:

"abcd_locator" => ".medium-12.large-12"
Сторінка має 100500 видимих елементів, і який із них є той "abcd", вже всі забули.

Рішення: Щоб такого не було, треба розповсюджувати на локатори правила семантичної наповненості коду, а саме:
Код має бути легким до читання людиною. (human readable code)


Тобто, назви класів, методів, змінних - і локатори теж - мусять мати сенс для читача, бо компілятору все одно, а людина буде скаржитись.
Тому, ще одна вимога до локаторів, яку ніхто прямо не виявляє, але всі неявно очікують:
     3. Читаність локатора - читач коду, не зазираючи у код сторінки, має розуміти куди йому в браўзері дивитись.
Звідси випливає така ж сама вимога до розробників web GUI:
Код сторінки має бути семантично наповненим. 
І якщо це не так - то це вже проблема розробників - додати сенсу в опис елементів, а не тестерів - знайти сенс там, де його нема.

На останок, додаю кілька показових прикладів.

1. Це сторінка продукту з бек-офісу Magento.
 <p class="content-buttons form-buttons">...  
     <button id="id_756ccb06ce3707375862bef2fe26698f" title="Save" type="button" class="scalable save" onclick="productForm.submit()" style=""><span><span><span>Save</span></span></span></button>  
     <button id="id_a749f555cabcf443c4aba1a5ad79166d" title="Save and Continue Edit" type="button" class="scalable save" onclick="saveAndContinueEdit('http://mag.example.com/index.php/admin/catalog_product/save/back/edit/tab/{{tab_id}}/id/904/key/7ef15788f09e4f3c2551d9ac7177e4e9/')" style=""><span><span><span>Save and Continue Edit</span></span></span></button>  
 </p>  

 Крім як по додаткових атрибутах типу onclick, тут потрібну кнопку Save and Continue Edit не дуже і дістанеш:
 //button[@class="scalable save" and contains(@onclick,"saveAndContinueEdit")]  

2. Поганий локатор, бо довгий, і рахувати треба:
 //tr[@class='scope']//div[contains(text(),'abc')]/../../../../../..//a[@class='title']  
    Добрий локатор:
 //tr[@class='scope'][td//div[contains(text(),'abc')]]//a[@class='title']