તે એક Slack મેસેજથી શરૂ થાય છે. બિલ્ડ લાલ (red) છે. તમે નિષ્ફળતાઓ તપાસો છો, ચિંતા કરો છો, અને તમારા લેપટોપ પર તે જ ટેસ્ટ ફરીથી ચલાવો છો. ગ્રીન (Green). તમે CI જોબ ફરીથી પ્રયાસ કરો છો. કદાચ તે કોઈ ક્ષણિક ખામી હતી. પણ નિષ્ફળતા પાછી આવે છે, સર્વર પર તે જિદ્દી અને વારંવાર આવતી છે, પરંતુ તમારા માટે તે અદ્રશ્ય છે.
એક બ્રાઉઝર ટેસ્ટ જે CI માં ફેલ થાય છે પરંતુ લોકલી પાસ થાય છે, તે માત્ર એક હેરાનગતિ કરતાં વધુ છે. તે અવિશ્વાસ પેદા કરે છે. ટીમો સમય (timing) ને દોષ આપવા લાગે છે. તેઓ એવા કામચલાઉ સુધારાઓ કરે છે જે ક્યારેય દૂર થતા નથી. અહીં એક setTimeout, ત્યાં એક .wait(5000). ટેસ્ટ સૂટ ધીમો પડી જાય છે. નિષ્ફળતાઓ વારંવાર આવતી રહે છે. તે અસ્થિર (flaky) ટેસ્ટ કાયમી સમસ્યા બની જાય છે, અને અંતે દરેક વ્યક્તિ લાલ પાઇપલાઇનને સામાન્ય બાબત તરીકે ગણવા લાગે છે.
તે જોખમી છે. તમે એવું ટેસ્ટ સૂટ નથી ઈચ્છતા જે ખોટી ચેતવણી આપતું હોય.
CI તૂટી નથી ગયું; તે ફક્ત અલગ છે
CI એન્વાયરમેન્ટ્સ અનિયમિત નથી હોતા. તેઓ નિશ્ચિત (deterministic) હોય છે. સમસ્યા એ છે કે તેઓ એવા સિસ્ટમ વિશે નિશ્ચિત છે જે તમારું MacBook અથવા તમારું Linux વર્કસ્ટેશન નથી. તમારું લોકલ સેટઅપ એવા તફાવતોને છુપાવે છે જે એક ક્લીન CI રનર તરત જ ખુલ્લા પાડે છે.
વિચારો કે કેટલા ઘટકો અલગ પડે છે. તમારું લોકલ મશીન હોટ મોડ્યુલ રીલોડિંગ (hot module reloading) સાથે ડેવલપમેન્ટ સર્વર ચલાવી શકે છે, જ્યારે CI ટ્રી શેકિંગ (tree shaking) અને મિનિફિકેશન (minification) સાથે પ્રોડક્શન આર્ટિફેક્ટ બનાવે છે. આ એકલું જ કોડ પાથને બદલી શકે છે અથવા એક્ઝેક્યુશનનો ક્રમ બદલી શકે છે. ડિપેન્ડન્સી ટ્રીઝ (Dependency trees) બદલાઈ જાય છે. એક લોકફાઇલ (lockfile) જે સમાન દેખાય છે તે અલગ રીતે રિઝોલ્વ થઈ શકે છે જો પેકેજ મેનેજરનું વર્ઝન માત્ર એક માઇનર રિલીઝથી અલગ હોય. નેટવર્ક સિક્વન્સ બદલાય છે. તમારું ઓફિસ Wi-Fi એક જ સ્ટેપમાં સ્ટેજિંગ API ને રિઝોલ્વ કરી શકે છે; CI રનર લોડ બેલેન્સર પાછળના અલગ ક્લસ્ટર પર પહોંચી શકે છે, જેનાથી એવી લેટન્સી (latency) પેદા થાય છે જે તમે ક્યારેય જોતા નથી.
બ્રાઉઝર્સ પોતે પણ વિવિધ એન્વાયરમેન્ટ્સમાં અલગ રીતે વર્તે છે. તમારા લોકલ Chrome માં એક્સ્ટેન્શન, કેશ કરેલા ક્રેડેન્શિયલ્સ, પર્સિસ્ટન્ટ લોકલ સ્ટોરેજ અને હાર્ડવેર એક્સિલરેશન સાથેનું GPU હોય છે. CI દરેક રન વખતે એક ખાલી પ્રોફાઇલથી શરૂ થાય છે. બ્રાઉઝર લાઇફસાયકલ અલગ પડે છે. રેન્ડરિંગ પાથ અલગ પડે છે. તમારા સિસ્ટમ પર રહેલા ફોન્ટ્સ CI માં બદલાઈ જાય છે. વ્યુપોર્ટ સાઈઝિંગ (Viewport sizing) અને ડિવાઇસ પિક્સેલ રેશિયો અલગ હોઈ શકે છે, જે રિસ્પોન્સિવ બ્રેકપોઈન્ટ્સને બદલી શકે છે અથવા લેઝી-લોડિંગ (lazy-loading) વર્તનને અસર કરી શકે છે.
આ તફાવતો વાસ્તવિક છે. તેઓ યાંત્રિક છે. તેઓને અનિયમિત ગણીને અવગણવાથી તેઓ દૂર થતા નથી.
પ્રિવ્યૂ એન્વાયરમેન્ટ્સ (Preview Environments) જૂઠું બોલે છે
પ્રિવ્યૂ એન્વાયરમેન્ટ્સ આ સમસ્યાને વધુ ગંભીર બનાવે છે. તેઓ માનવીય સમીક્ષા માટે ઉપયોગી છે, પરંતુ તેઓ પ્રોડક્શન નથી. તેઓ ઘણીવાર વાસ્તવિક API હોસ્ટને બદલે api-staging તરફ નિર્દેશ કરે છે. ફીચર ફ્લેગ્સ (Feature flags) દરેક પ્રયોગ માટે 'true' તરીકે મૂલ્યાંકન કરે છે, જે પ્રોડક્શનમાં ચાલતા શરતી લોજિકને છુપાવે છે. ઓથેન્ટિકેશન કદાચ એક સ્ટેપ છોડી શકે છે અથવા મોક ટોકન (mock token) ઇન્જેક્ટ કરી શકે છે. કૂકીઝ રિલેક્સ્ડ પોલિસીનો ઉપયોગ કરી શકે છે. ડેટાસેટ ખૂબ નાનો હોઈ શકે છે, દસ હજારને બદલે માત્ર દસ રો (rows), જેનો અર્થ છે કે પેજીનેશન, સર્ચ રેન્કિંગ અથવા વર્ચ્યુઅલાઈઝેશન લોજિક ક્યારેય ટેસ્ટ થતું નથી.
જો તમારો ટેસ્ટ પ્રિવ્યૂ URL પર પાસ થાય પરંતુ પ્રોડક્શનમાં ફેલ થાય, અથવા તેનાથી ઉલટું, તો ટેસ્ટમાં ભૂલ નથી. એન્વાયરમેન્ટમાં ભૂલ છે.
અનુમાન લગાવતા પહેલા લોગ (Log) કરો
જ્યારે પહેલીવાર નિષ્ફળતા દેખાય, ત્યારે ટેસ્ટમાં થોડો ફેરફાર કરીને આશા રાખવાની વૃત્તિનો વિરોધ કરો. અનુમાન કરવાનું બંધ કરો. તમારે સંદર્ભને (context) સ્થિર કરવાની જરૂર છે જેથી તમે સફળ રન અને નિષ્ફળ રનની સરખામણી કરી શકો.
સ્પષ્ટ શંકાસ્પદ કારણોનો લોગ કરો. નિષ્ફળતાના ક્ષણે પેજ URL, બિલ્ડ ID અને કમીટ SHA રેકોર્ડ કરો. સક્રિય ફીચર ફ્લેગ્સ નોંધો. API હોસ્ટ, બ્રાઉઝરનું ચોક્કસ વર્ઝન અને વ્યુપોર્ટ સાઈઝ કેપ્ચર કરો. આ વિગતો એક રહસ્યમય નિષ્ફળતાને ફરીથી પેદા કરી શકાય તેવી (reproducible) સ્થિતિમાં ફેરવી દે છે.
માત્ર સ્ક્રીનશોટ પર આધાર રાખશો નહીં. બે પેજ પિક્સેલ-સરખા દેખાઈ શકે છે જ્યારે તેઓ સંપૂર્ણપણે અલગ JavaScript ચલાવી રહ્યા હોય. સ્ક્રીનશોટ તમને એ નહીં કહે કે CI બંડલમાં વધારાનું પોલીફિલ (polyfill) સામેલ હતું અથવા લોકલ બંડલે કોઈ ચંક (chunk) છોડી દીધો હતો કારણ કે તે તમારા બ્રાઉઝર કેશમાં પહેલેથી જ હતો.
એ પણ યાદ રાખો કે DevTools ખોલવાથી ટાઈમિંગ બદલાય છે. DevTools ગાર્બેજ કલેક્શનને મોકૂફ રાખી શકે છે, નેટવર્ક પ્રાયોરિટીઝેશન બદલી શકે છે અને અમુક રેન્ડરિંગ ઓપ્ટિમાઇઝેશનને નિષ્ક્રિય કરી શકે છે. તમે જ્યારે DOM ની તપાસ કરી રહ્યા હોવ ત્યારે પાસ થતો ટેસ્ટ, પેનલ બંધ કરીને હેડલેસ (headless) મોડમાં ચલાવતા જ ફેલ થઈ શકે છે. ડિબગ્ગર એક ઉપયોગી સાધન છે, પરંતુ તે તટસ્થ અવલોકનકાર નથી.
ગુનાના સ્થળનું પુનઃનિર્માણ કરો
જો તમે નિષ્ફળતાને સચોટ રીતે ફરીથી પેદા કરવા માંગતા હોવ, તો તમે ફક્ત તમારા લોકલ ડેવલપમેન્ટ સર્વરને ચલાવીને આશા રાખી શકતા નથી. તમારે the_CI's_ ચોક્કસ પરિસ્થિતિઓનું પુનરાવર્તન કરવાની જરૂર છે.
CI એ જે આર્ટિફેક્ટ (artifact) બનાવ્યો હોય તે જ બરાબર બનાવો. જો જરૂર પડે તો તેને ડાઉનલોડ કરો. તે આર્ટિફેક્ટને Vite અથવા Webpack ડેવ મિડલવેરથી નહીં, પણ એક સાદા સ્ટેટિક ફાઇલ સર્વર સાથે લોકલી સર્વ કરો. CI એ જે એન્વાયરમેન્ટ વેરિયેબલ્સ ઇન્જેક્ટ કર્યા હોય તેનો જ ઉપયોગ કરો. બ્રાઉઝર વર્ઝન પણ બરાબર મેચ કરો. તેને તે જ મોડમાં ચલાવો, હેડેડ (headed) અથવા હેડલેસ (headless), કારણ કે ફોકસ ઇવેન્ટ્સ, મીડિયા ક્વેરીઝ અને ઓટોપ્લે પોલિસીઝ હજુ પણ બંને વચ્ચે સૂક્ષ્મ રીતે અલગ પડે છે. જો તમારું CI ડોકર કન્ટેનર (Docker container) વાપરતું હોય, તો તે જ ઇમેજ લોકલી ચલાવો. તમારી પર્સનલ બ્રાઉઝર પ્રોફાઇલ સંપૂર્ણપણે દૂર કરો.
જ્યારે લોકલ રિપ્રોડક્શન (local reproduction) અંતે નિષ્ફળ જાય, ત્યારે તમારી પાસે ખરેખર ડિબગિંગ સેશન હોય છે. ત્યાં સુધી, તમે માત્ર પડછાયાઓનો પીછો કરી રહ્યા છો.
ઊંઘવાનું બંધ કરો, રાહ જોવાનું શરૂ કરો
ફ્લેકી (flaky) બ્રાઉઝર ટેસ્ટ માટે સૌથી સામાન્ય પ્રતિસાદ ડિલે (delay) ઉમેરવાનો હોય છે. પાંચ સેકન્ડ રાહ જુઓ. દસ સેકન્ડ રાહ જુઓ. આ કોઈ ઉકેલ નથી. આ શરણાગતિ છે. મનસ્વી વિલંબ (arbitrary delays) તમારા ટેસ્ટ સ્યુટને ધીમો પાડે છે, ખોટો આત્મવિશ્વાસ પેદા કરે છે, અને નેટવર્કની અડચણો વખતે લોડ હેઠળ હજુ પણ નિષ્ફળ જાય છે.
તેના બદલે, સ્ટેટના પુરાવા માટે રાહ જુઓ. જો ફોર્મ સબમિશન પછી કોઈ નોટિફિકેશન દેખાવું જોઈએ, તો સમય પસાર થવાની રાહ ન જુઓ. DOM માં ચોક્કસ નોટિફિકેશન ID અસ્તિત્વ ધરાવે છે કે નહીં તેની રાહ જુઓ. જો કાઉન્ટર વધવું જોઈએ, તો ટેક્સ્ટની વેલ્યુ બદલાય ત્યાં સુધી રાહ જુઓ. જો લોડિંગ સ્ટેટ ઇન્ટરેક્શનને રોકે છે, તો લોડિંગ માર્કર અદૃશ્ય થાય ત્યાં સુધી રાહ જુઓ. જો તમે WebSocket અથવા server-sent events સાથે કામ કરી રહ્યા હોવ, તો નેટવર્ક સ્ટ્રીમ ચોક્કસ ઇવેન્ટ ઉત્પન્ન કરે ત્યાં સુધી રાહ જુઓ.
એક્સપ્લિસિટ વેઇટ્સ (Explicit waits) તમારા ટેસ્ટને અંદાજ લગાવવાની રમતમાંથી એક કરાર (contract) માં બદલી નાખે છે. ટેસ્ટ કહે છે: "એપ્લિકેશન તૈયાર છે તેની પુષ્ટિ કર્યા પછી જ હું આગળ વધીશ." આ કહેવું કે, "પૂરતા સેકન્ડો પસાર થઈ ગયા પછી હું આગળ વધીશ," તેના કરતા ઘણું વધારે મજબૂત છે.
હાઇડ્રેશન (Hydration) અને અદૃશ્ય થતું બટન
આધુનિક React એપ્લિકેશન્સમાં, હાઇડ્રેશન એવા નિષ્ફળતાના પ્રકારનું કારણ બને છે જેને લોકલ ડેવ સર્વર્સ ઘણીવાર છુપાવી દે છે. સર્વર HTML મોકલે છે. React બ્રાઉઝરમાં શરૂ થાય છે અને ઇવેન્ટ લિસનર્સ (event listeners) જોડે છે. તે સમય દરમિયાન, તમારો ટેસ્ટ કદાચ કોઈ બટન પર ક્લિક કરી શકે છે. ત્યારબાદ React હાઇડ્રેશન દરમિયાન તે DOM નોડને બદલી નાખે છે અથવા તેનું માળખું ફરીથી બનાવે છે. તમારું ટેસ્ટ ફ્રેમવર્ક જે એલિમેન્ટ હેન્ડલ પકડી રાખ્યું હતું તે હવે એક અલગ થયેલ (detached) નોડ તરફ નિર્દેશ કરે છે, અને તમને દૂર કરાયેલ એલિમેન્ટ સાથે ઇન્ટરેક્ટ કરવા વિશે ભૂલ મળે છે.
ઉકેલ એ વધુ જટિલ સિલેક્ટર (selector) લખવાનો નથી જે કમ્પોનન્ટ ટ્રીમાં ઊંડે સુધી જાય. ઉકેલ એ તૈયાર હોવાના સંકેતો (readiness signals) શોધવાનો છે. જ્યાં સુધી રૂટ એલિમેન્ટ હાઇડ્રેટેડ એટ્રિબ્યુટ અથવા જાણીતી ડેટા પ્રોપર્ટી મેળવે નહીં ત્યાં સુધી રાહ જુઓ. સ્કેલેટન લોડર અદૃશ્ય થાય ત્યાં સુધી રાહ જુઓ. ક્લાયન્ટ-સાઇડ ઇવેન્ટ હેન્ડલર સક્રિય થાય ત્યાં સુધી રાહ જુઓ. તમે ક્લિક્સ કરવા તે પહેલાં એપ્લિકેશન જાતે જાહેર કરે કે તે સ્થિર છે.
છુપા દોષિતો: ડિપેન્ડન્સીઝ અને થર્ડ-પાર્ટી સ્ક્રિપ્ટ્સ
ક્યારેક એન્વાયરમેન્ટ બદલાઈ જાય છે ભલે તમારી એપ્લિકેશન કોડમાં કોઈ ફેરફાર ન થયો હોય. તમારા node_modules માં ત્રણ લેવલ ઊંડે રહેલી નાની યુટિલિટી લાઇબ્રેરીનું ટ્રાન્ઝિટિવ અપડેટ બ્રાઉઝરના વર્તનને બદલી શકે છે. તે પ્રોમિસ (promises) કેવી રીતે રિઝોલ્વ થાય છે, સ્ટાઇલ્સ કેવી રીતે ઇન્જેક્ટ થાય છે, અથવા મોક્સ (mocks) કેવી રીતે રિક્વેસ્ટ્સને ઇન્ટરસેપ્ટ કરે છે તે બદલી શકે છે. જ્યારે રૂટિન ડિપેન્ડન્સી અપડેટ પછી ટેસ્ટ નિષ્ફળ જવાનું શરૂ થાય, ત્યારે તમારા પેકેજ મેનેજરનું વર્ઝન અને લોકફાઇલ ચેકસમ (lockfile checksum) રેકોર્ડ કરો. તમારે એ જાણવાની જરૂર છે કે તમે ગયા અઠવાડિયે જે ટ્રી જોઈ રહ્યા હતા તે જ જોઈ રહ્યા છો કે નહીં.
થર્ડ-પાર્ટી સ્ક્રિપ્ટ્સ બીજા વારંવાર થતા તોડફોડ કરનાર છે. એનાલિટિક્સ ટ્રેકર્સ, પેમેન્ટ SDKs અને ચેટ વિજેટ્સ અસિંક્રોનસલી (asynchronously) લોડ થાય છે. તેઓ ઇફ્રેમ્સ (iframes) ઇન્જેક્ટ કરે છે, લેઆઉટ બદલે છે, અથવા એવા ક્ષણોમાં ફોકસ ચોરી લે છે જેની તમારા ટેસ્ટને અપેક્ષા નથી. CI માં, આ સ્ક્રિપ્ટ્સ વધુ ધીમેથી લોડ થઈ શકે છે, અથવા નેટવર્ક પ્રતિબંધોને કારણે તે લોડ થવામાં સંપૂર્ણપણે નિષ્ફળ જઈ શકે છે, જેના કારણે તમારી એપ્લિકેશન અલગ એરર-હેન્ડલિંગ પાથ અનુસરે છે. કયા થર્ડ-પાર્ટી રિસોર્સિસ લોડ થયા અને તેમનો HTTP સ્ટેટસ શું હતો તે લોગ કરો. જો CI માં પેમેન્ટ ઇફ્રેમને માઉન્ટ થવામાં ત્રણ સેકન્ડ લાગે છે પરંતુ તમારા ફાસ્ટ લોકલ કનેક્શન પર તે તરત જ લોડ થાય છે, તો તમારી "element not clickable" ભૂલનું અચાનક એક સ્પષ્ટ કારણ મળી જાય છે.
અને "element not clickable" એ ક્યારેય નિદાન નથી. તે માત્ર એક લક્ષણ છે. કારણનો ઈલાજ કરો.
એવિડન્સ કિટ (Evidence Kit) બનાવો
દરેક CI નિષ્ફળતા એવા પ્રકારની હોવી જોઈએ જેના પર કાર્ય કરી શકાય (actionable). માત્ર સ્ટેક ટ્રેસ (stack trace) પૂરતું નથી. તમારે એવિડન્સ કિટની જરૂર છે જે અન્ય એન્જિનિયરને, અથવા આવતા મહિને તમને જ, શું થયું હતું તે ફરીથી સમજવામાં મદદ કરે.
નિષ્ફળ ગયેલા રનમાંથી સ્ક્રીનશોટ્સ અને વિડિયો રેકોર્ડિંગ્સ રાખો. સંપૂર્ણ બ્રાઉઝર કન્સોલ આઉટપુટ કેપ્ચર કરો, માત્ર ભૂલો જ નહીં પણ ચેતવણીઓ (warnings) પણ. 404s, CORS રિજેક્શન અને ડ્રોપ્ડ કનેક્શન સહિત નેટવર્ક નિષ્ફળતાઓ લોગ કરો. જે બિલ્ડ આઈડી (build IDs) અને ફીચર ફ્લેગ્સ એક્ટિવ હતા તેને સાચવી રાખો. એસેર્શન (assertion) નિષ્ફળ જાય તે જ ક્ષણે DOM સ્નેપશોટ લો. સ્નેપશોટ તમને ઘટના બન્યા પછી HTML સ્ટ્રક્ચરનું નિરીક્ષણ કરવાની મંજૂરી આપે છે, તેના બદલે...
