Сфера дэйстыння і падняцье змян у JavaScript для інжынераў автаматызаціі тэставання
Частка 8 для тых, хто вучыцца QA: глобальны, функцыйнальны і блакетны дыяхронум; var vs let vs const; падняцье змэнных; тэмпаральная мертвая зона; і як гэтыя правілы запобегаюць вытэканню дадзейнаў тэстаў.
Крыніцы: JavaScript For QA Engineers: My Learning Journey — Part 8
Іноды JavaScript не выдаёт ошыбок не там, ўжо калі логіка некорэктная. Ён выдаёт ошыбку тады, калі зменная недоступна там, дзе яе чакаюць.
Што ўжо вядома
Тыповы падход да автаматызаціі тэстав у JavaScript пачынаецца з выбору мовы, а потым ідуць зменныя, тыпы, масівы, об’екты, аператары, цыклы і функціі. Кантэкст выканання і механізм паднесення змэнных — гэта тые аспекты, якія пояснююць, чаму значэнне працюе ў однам месцы, а выдаёт ошыбку ў іншам, а таксама чаму двайчык выглядае, што ён “бачыць” заявленняя ранейш, чым яны запісуюцца.
Шта такое кантэкст выканання?
Кантэкст выканання адпавядае на просты вопыт: дзе ўіднае гэтая зменная чы функція?
let browser = "Chrome";
console.log(browser);
//Output: Chrome
Тут browser ўіднае ў тым кантэксце, дзе яна была заявлена.
Замест таго заявіце яе ўнутрь функцыі:
function runTest() {
let browser = "Chrome";
console.log(browser);
}
runTest();
Цяпер browser існуе толькі ўнутрь той функцыі. Якшо чытаць яе званаўні:
console.log(browser);
Яны выклікаюцца там, дзе знаходзіцца іх імя, тое ў значэнні, што імя належыць да сферы дасягнення функцыі. Самэй гэтай разніцы сорты глобальных сфер дасягнення маюць значэнне ў кодзе для тэставання.
Тыпы сфер дасягнення ў JavaScript
Найчым болей зустрэчаюцыяся формы сфер дасягнення ў автаматызацыі ёсць:
- Глобальная сфера дасягнення
- Сфера дасягнення функцыі
- Сфера дасягнення блока
- Лексычная сфера дасягнення
1. Глобальная сфера дасягнення
Зменны, адклараваны за межамі кожной функцыі і блока, знаходзяцца ў глобальной сферэ дасягнення.
const environment = "staging";
function runTest() {
console.log(`Running on: ${environment}`); // Works ✅
}
runTest();
console.log(environment); // Works ✅
Глобальныя зменны падходзяць для спільных значэнняў, такіх як базовыя URL-адрэсы, назвы сераўнаў і настройкі. Іх трэба вжываць астатожна: калі багато памочных функцый мутуюць тую ж глобальную зменную, стае важка выявіць прычыны бягункоў.
2. Сфера дасягнення функцыі
Імены, адклараваны ўнутрь функцыі, зазвычай відкрываюцца толькі ў межах ціеў функцыі.
function login() {
const password = "Admin@123";
console.log(`Logging in with: ${password}`); // Works ✅
}
login();
console.log(password); // ❌ Error — password is not defined
Гэтае обмежэння запобегае вытэканню або перазапісву крэдытнаў інфармацыі і дадзейк, спецыяльных для кожнага тэсту, паўстанням ад неканектных памочных функцый.
Просты спосаб пры запамятаванні
Заявлены ўнутрь функцыі → доступны ўнутрь той функцыі.
Памяткі для заходу ў сістэму чы рулівання, якія можна вікорыстоўваць знову, апыягаюцца гэтым межам.
3. Дыяхронія блока
Блак — гэта ўсё, што знаходзіцца межа { }. За дапамогою let чы const імя, заявленае ў блаку, жыве толькі ўнутрь таго блаку.
if (true) {
let browser = "Chrome";
console.log(browser);
}
//Output:Chrome
Даступ за межамі блака:
console.log(browser);
немагчыма, таму што let чы const маюць дыяхронію блака. Гэта якосць мае значэнне ў умовных выразах чы ціклах у тэстах.
Прыклад з ціклам
for (let i = 1; i <= 3; i++) {
console.log(i);
}
//Output:
1
2
3
Зв’язак let кожнай ітэрацыі застаецца ў блаку той ітэрацыі, што запобегае класычнай проблеме спяльвання var, калі дадаюцца асінхронныя обрабнікі ў ціклах.
var проты let проты const і дыяхронія
var мае дыячнае прастора (або глобальны, калі яго адзначаюць за межамі функцыі). let і const маюць блаковое прастора. За звычайнае выкарыстоўванне лепш выбіраць const, let — калі патрэбна перазначэнне, а ў сучасным кодзе тэстаў трэба утрымацца ад новых var. У большых праектах Playwright або Cypress гэтае правіле сама по сабе усунеўша цэлы клас проблем тыпу “вучыцца на маймашыне”, калі адна спефікацыя перазапісвае стан іншай праз спакульнае var.
if (true) {
var browser = "Chrome";
let version = "Latest";
const environment = "QA";
}
console.log(browser);
//Output:Chrome
console.log(version);
console.log(environment);
const baseURL = "https://myapp.com"; // Global — shared everywhere
Што такое хоўстынг?
Хоўстынг — гэта прычына, за якой двайчорак адзначэнняя перадаюцца на пачатак функцыі раней, чым яе тэла выконваюцца зверху вярх. Адзначэнняя рэгіструюцца зусім спачатку; перазначэнняя ж выконваюцца тады, калі прыходзіць час да выканання відпаведных рэчэй.
Хоўстынг з var
function loginTest() {
const username = "admin"; // Function scope — only here
const password = "Admin@123"; // Function scope — only here if (username === "admin") {
let accessLevel = "full"; // Block scope — only in this if block
console.log(`Access: ${accessLevel}`);
} console.log(`${baseURL}/login`); // Global still accessible ✅
}
Імя var існуе з самага пачатку функцыі/глобальнага прастору імен (ініцыязавана як undefined) пакуль не будзе выканана лінія прызначэння.
Паднятчы эфект з let
let browser = "Chrome";
function runTest() {
console.log(browser);
}
runTest();
//Output:Chrome
let таксама рэгіструецца з самага пачатку, але яго нельга чытаць да лініі яго адзначэння. Гэты прыемак — гэта тэмпаральная мертва зона.
Што такое тэмпаральная мертва зона?
Тэмпаральная мертва зона — гэта перыяд часу ад момента входу ў прастор імен да выканання адзначэння let/const. Аксес у гэтай зоне выклікае адказку працоўнай каштоўнасці, а не вяртае undefined.
let environment = "QA";
function runTest() {
let browser = "Chrome";
if (true) {
let testName = "Login Test";
console.log(environment);
console.log(browser);
console.log(testName);
}
}
runTest();
Просты спосаб прыгадаць
Ранній аксес да
var→undefined. Ранній аксес даlet/const→ адказка працоўнай каштоўнасці (тэмпаральная мертва зона).
Паднятчы эфект з адзначэннямі функцый
Адыяванні функцыйяў ўсё паднімаецца: яны можна вызваць раней, чым яны з’являюцца ў файле.
console.log(browser);
var browser = "Chrome";
// Output:undefined
Выраз функцыі і падніманне
Выразы функцыйяў, прызначаныя для const/let, паводліваюць правілам даўальных змэнных: ўзаемнае прыязначэнне відбываецца ў TDZ пакуль не будзе адбыта прызначэнне.
var browser;
console.log(browser);
browser = "Chrome";
Адыяванне функцыйі
undefined
Цяперыце для дапаможных функцыйяў, якія трэба можна было вызваць будзь-дзе ў межах дыяпазона пасля яго запуску.
Выраз функцыі
console.log(browser);
let browser = "Chrome";
Бяспечней, калі трэба контролаваць момент, калі будзе адкрытыя значэнне функцыі, часта з const.
Прыклад автаматызаціі тэстав
Памылкі ў дыяпазоне чытна праявляюцца ў кодзе Page Object і fixture-аў.
ReferenceError
{
console.log(testName);
let testName = "Login Test";
}
Зберагчы селектары і аутантыфікацыйныя даныя ўнутрь функцыйяў або блакоў, якія іх маюць, можна запобець занесенню памылак між тэстамі.
Чаму значэнне дыямэнту ў автаматызацыі
Спяльныя, зменныя глобальныя зместы прыводзяць да таго, што паралельныя або перасортаваныя тэсты стаюць ненадзеянымі. Дыямэнт функцыі і блока дазволяе заставаць даныя кожнага тэсту локальнымі. Лексычны дыямэнт памагае вкладзеным падпрацоўнікам выкарыстоваць настройкі без паўтарачнага перадавання кожнага аргумента.
let testName = "Login Test";
Лексычны дыямэнт у практыцы
Внутршнія функцыі бачаюць значэнні з внешняях дыямэнтаў, таму яны былі занесены, а не таму, дзе яны былі вызваны.
ReferenceError
runTest();
function runTest() {
console.log("Test started");
}
//Output:Test started
Самэй таго кале-бэк, занесеный унутрь тэсту, все ўсё можа чытаць зместы page або user гэтага тэсту. Закрыцці — гэта спосаб, якім фікстуры перадаюць кантэкст у вкладзеныя падпрацоўнікі без вікорыстання глобальных зместоў.
Пашырэныя памылкі
Чытанне зместу let ранейш, чым яго занесенне:
runTest();
const runTest = function() {
console.log("Test started");
};
Прыпуск, што var мае дыямэнт блока ўнутрь if:
ReferenceError
Забываючы, што цікл з var аднае адносныя значэння ўсіх ітэрацый:
runTest();
function runTest() {
console.log("Test started");
}
Адліквідацыя проблем с функцыйнальным дзеянням
Калі ReferenceError паказвае зменную, якую вы “толькі задаўшы”, пераканайцеся, якая { } або функцыя яе володзіць, чы вы вжылі var чы let, і чы доступ да яе адбываецца раней за ўказванне (TDZ).
runTest();
const runTest = function() {
console.log("Test started");
};
Практычныя правілы для набора тэстаў
- Для сторанак, селектараў і об’ектаў налаштавання лепей вжываць
const. - Вжывайце
letтолькі для значэнняў, якія павінны зменіцца. - Утрымайцеся ад новых
var. - Зберагаюце секрэты ў межах функцыі.
- Не пакладайцеся на віпадковыя глобальныя зменныя, створаныя праз неадказвальныя указванні.
const browser = "Chrome";
function runTest() {
const testName = "Login Test";
console.log(`Running ${testName}`);
console.log(`Browser: ${browser}`);
}
runTest();
//Output:
Running Login Test
Browser: Chrome
let testStatus = "Passed";
function testOne() {
testStatus = "Failed";
}
function testTwo() {
console.log(testStatus);
}
Кораткая ментальная модэль
Сфера дасягнення = месца, дзе відобразаецца імя. Паднятчык = момент, калі рэгламентацыя заносіцца. TDZ = забраная зона даўнае рэгламентацыі перад ініцыялізацыёй за дапамою let/const.
const testCases = ["Login", "Search", "Checkout"];
function executeTests() {
for (const testCase of testCases) {
console.log(`Executing: ${testCase}`);
}
}
executeTests();
//Output:
Executing: Login
Executing: Search
Executing: Checkout
Адналожэнне ў маленькім тэстовым дапаможным працэсе
let username;
let password;
let browser;
let testStatus;
function login() {
const username = "qa_user";
const password = "Password@123"; console.log(`Logging in as ${username}`);}
Калі гэтыя месца для падставы ўжо заполнены, локальныя зменныкі дапаможнага працэсу застаюцца ў яго межах, настройкі на рэвэле застаюцца цярпячымі, а памілкі ранньага доступу стаюць зрозумелымі, а не таёмнымі. Сфера дасягнення і паднятчык перастаюць быць дробнымі дэталямі і становяцца ўседзённымі інструментамі для стабільной автаматызацыі JavaScript.
Ланцюгі сфер дасягнення пад час асінхронных крокаў тэста
Автаматызацыя рэдка калі застаецца сінхронной. Калі async тэст чакае на клік, а пасля чытае зменную, прыяўленне яе даесяць з лексычнага дыялекту, дзе была задана функцыя. Перамешчэнне выразоў праз await не адбываецца; яно толькі вплывае на спосаб рэгістрацыі заявленняў, калі пачынаецца тэла функцыі. Зберагчы даны фікстураў у прыяўленнях const у верхней часты тэстовай функцыі, легча следзіць за гэтым ментальным мадэляваннем, калі стакі распакоўваюцца пасля тайма-аутаў.
Чаму падачкі TDZ здаюцца жорсткімі — і чаму яны дапамагаюць
Паводзіны ReferenceError замест undefined можу прыкантаваць інжынераў, якія працавалі з кодам на var. У наборэ тэстаў такая жорсткасць ёсць корыстной: тэст быстра паводзіцца неудачна, калі дапаможны код размешчаецца вышэй за свою настройку let. Спрыяйце падачкам TDZ як багам у парадку размешчэння коду ў тэстовым файле, а не як нестабільнай працэздатнасі продукту.
Міграцыя старэйшых набораў var
Падчас аптэльнавання застарэлых сістэм автоматызацыі заменяйце var на const або let паэтапна, запускайце набор тэстаў і старанна сачыце за проблемамі сферы дасягнення ў тэле оператараў if/for, якія ранейш выклікалі вытэкі. Спаруйце гэту міграцыю з правіламі лінт-перагляду, якія забараняюць вжытак var, каб новыя тэсты не ввелі зноў проблему вытэкаў у всій функцыі.
Шэдау-змены ў вярнутых памочных функціях
Внутрэшны const browser = „Firefox“ усерэдзіны ў памагальным функцыяле скрывае зовнішній browser на час выканання тагу. Гэта ўзгалінне лексычных імен, а не іх падняцье. У об’ектах сторанкі такое узгалінне можа прычыніць тое, што тэст будзе чытаць некарэктны базовы URL, калі внутранній памагальны функцыял занова прызначыць вядома імя. Пры нараджэнні вялікага калеку лепш выбіраць разныя імены (overrideBrowser, tempBrowser) або перадаваць значэння як параметры, замест таго кіравацца і занову прызначаць тое ж імя.