உங்கள் மின்னஞ்சல் சோதனைகள் (email tests) உங்கள் லேப்டாப்பில் சரியாக இயங்கி, CI-க்கு வந்தவுடன் தோல்வியடைந்தால், நீங்கள் மட்டும் தனியாக இல்லை. பொதுவாக இதற்குப் பதிலாக, சோதனை குறியீட்டில் (test code) sleep அழைப்புகளைச் சேர்ப்பதோ அல்லது பில்ட் (build) வெற்றி பெறும் வரை மறுமுயற்சி எண்ணிக்கையை (retry count) அதிகரிப்பதோ வழக்கமாக உள்ளது. இது ஒரு நாள் மட்டும் பிரச்சனையைத் தற்காலிகமாகத் தணிக்கும், ஆனால் பிழையை (bug) சரிசெய்யாது. இது பிழையை மறைக்க மட்டுமே செய்யும்.

உண்மையான பிரச்சனை என்னவென்றால், உங்கள் சோதனை எந்த மின்னஞ்சலைத் திறக்க வேண்டும் என்பதைக் கண்டறிவதுதான்.

பகிரப்பட்ட இன்பாக்ஸ் பிரச்சனை (The Shared Inbox Problem)

உங்கள் உள்ளூர் கணினியில் (local machine), நீங்கள் ஒவ்வொரு முறையும் ஒரு சோதனையை மட்டுமே இயக்குவீர்கள். ஒரு மின்னஞ்சல் வரும். நீங்கள் அதை எடுத்துக்கொள்வீர்கள். அவ்வளவுதான், எளிது.

CI என்பது முற்றிலும் மாறுபட்ட சூழலாகும். ஒரு ஒற்றைப் புல் ரிக்வெஸ்ட் (pull request), நான்கு, எட்டு அல்லது பதினாறு இணக்கமான வேலைகளை (parallel jobs) தூண்டக்கூடும். அவை அனைத்தும் ஒரு சோதனை இன்பாக்ஸைப் பகிர்ந்து கொண்டால்—அது ஒரு Mailosaur சர்வர், Mailtrap இன்பாக்ஸ் அல்லது ஒரு ஸ்டேஜிங் டொமைனில் உள்ள உண்மையான கணக்காக இருந்தாலும் சரி—அவை அனைத்தும் ஒரே நேரத்தில் ஒரே இடத்திற்குத் தரவுகளை எழுதுகின்றன. வேலை A ஒரு கடவுச்சொல் மாற்றும் (password reset) மின்னஞ்சலை அனுப்புகிறது. வேலை B ஒரு அழைப்பை (invite) அனுப்புகிறது. வேலை C தோல்வியடைந்த வரவேற்புச் செயல்பாட்டை (welcome flow) மீண்டும் முயற்சிக்கிறது. இதற்கிடையில், பின்னணிப் பணியாளர்கள் (background workers) மற்றும் டெலிவரி வரிசைகள் (delivery queues) நீங்கள் கட்டுப்படுத்த முடியாத ஒரு சீரற்ற தன்மையை (jitter) உருவாக்குகின்றன.

ஒவ்வொரு வேலையும் அந்தப் பகிரப்பட்ட இன்பாக்ஸிற்குச் சென்று "Reset your password" என்ற தலைப்புடன் கூடிய புதிய செய்தியைத் தேடும்போது, அது ஒரு போட்டியாக மாறிவிடுகிறது. வெற்றி பெறும் சோதனை சரியான மின்னஞ்சலைப் பெறும். தோற்கும் சோதனை மற்றொரு வேலைக்காக ஒதுக்கப்பட்ட இணைப்பைக் (link) கிளிக் செய்யும், தவறான உள்ளடக்கத்தைச் சரிபார்க்க முயலும் (assert), மேலும் அது நேரச் சிக்கல் (timing problem) போன்ற ஒரு பிழையுடன் தோல்வியடையும். இது நேரச் சிக்கல் அல்ல. இது ஒரு அடையாளச் சிக்கல் (identity problem).

ஏன் "புதிய செய்தி" (Newest Message) தோல்வியடைகிறது

இந்தத் தவறான முறையைப் பின்பற்றுவது எளிது, ஏனெனில் இது இயல்பாகத் தோன்றுகிறது:

  1. பயனர் செயல்பாட்டைத் தூண்டுங்கள் (Trigger the user flow).
  2. ஒவ்வொரு சில வினாடிகளுக்கும் இன்பாக்ஸைச் சரிபார்க்கவும் (Poll the inbox).
  3. தலைப்புடன் பொருந்தும் மிக சமீபத்திய செய்தியைத் திறக்கவும்.
  4. முதல் இணைப்பைக் கிளிக் செய்து சரிபார்ப்புகளை (assertions)ச் செய்யவும்.

இது வெறும் இணையாகச் செயல்படுவதைத் தாண்டி பல காரணங்களால் தோல்வியடைகிறது. முந்தைய தோல்வியடைந்த சோதனையின் மறுமுயற்சி தாமதமாக வந்து, உங்கள் தற்போதைய சோதனை இன்பாக்ஸைச் சரிபார்க்கும் அதே நேரத்தில் திடீரெனப் புதிய செய்தியாக மாறக்கூடும். உங்கள் பயன்பாட்டிற்குள் இருக்கும் பின்னணிப் பணியாளர்கள் இரண்டு மின்னஞ்சல்களை வரிசைப்படுத்தி, முதல் மின்னஞ்சலுக்கு முன்பே இரண்டாவது மின்னஞ்சலை அனுப்பக்கூடும். தலைப்புகள் மட்டுமே பலவீனமான அடையாளக் குறிகளாகும்; உங்கள் ஸ்டேஜிங் பயன்பாடு வெவ்வேறு பாதைகளில் இருந்து ஒரே மாதிரியான மின்னஞ்சல்களை அனுப்பக்கூடும். நேர முத்திரையை (timestamp) வைத்து வரிசைப்படுத்துவது பார்ப்பதை விட மோசமானது, ஏனெனில் CI ரன்னருக்கும் (runner) மின்னஞ்சல் வழங்குநருக்கும் இடையிலான நேர வேறுபாடு (clock skew) உண்மையானது, மேலும் மின்னஞ்சல் API-கள் பெரும்பாலும் அவற்றின் குறியீடுகளை (indexes) சேமித்து வைக்கும் (cache) அல்லது தொகுத்து (batch) அனுப்பும்.

பரபரப்பான சூழல்களில் நேர முத்திரைகள் குழப்பமடையக்கூடும். உங்களுக்கு நேரடியான ஒன்று தேவை.

ரன் டோக்கன் (Run Token) என்பது உண்மையில் என்ன

ரன் டோக்கன் என்பது உங்கள் சோதனையின் தொடக்கத்தில் உருவாக்கப்பட்டு, உங்கள் பயன்பாடு அனுப்பும் மின்னஞ்சலில் சேர்க்கப்படும் ஒரு தனித்துவமான சரமாகும் (unique string). இது பயனர்களுக்குத் தெரிய வேண்டிய அவசியமில்லை, மேலும் இது அழகாக இருக்க வேண்டிய அவசியமும் இல்லை. இந்த குறிப்பிட்ட செய்தி இந்த குறிப்பிட்ட சோதனைச் செயல்பாட்டிற்குச் சொந்தமானது என்பதை நீங்கள் நிரூபிக்க முடியும் என்பதை உறுதி செய்வதே இதன் நோக்கம்.

தெளிவான உதாரணங்கள் சிறப்பாகச் செயல்படும். சோதனை தொடங்குவதற்கு முன், பின்வருவன போன்ற ஒரு டோக்கனை உருவாக்கவும்:

  • ஒரு UUID: 550e8400-e29b-41d4-a716-446655440001
  • ஒரு பில்ட் சார்ந்த கோரிக்கை ஐடி (build-scoped request ID): req_ci_build_4821_a7f3
  • ஒரு அழைப்பு ஸ்லக் (invite slug) அல்லது மெட்டாடேட்டா பின்னொட்டு (metadata suffix): signup-token-8k2m9n
  • சோதனை ரன்னரால் உருவாக்கப்பட்ட ஒரு சீரற்ற ஹெக்ஸ் சரம் (random hex string): test-run-a4f9c2d1

நீங்கள் பேக்எண்ட் குறியீட்டைக் (backend code) கட்டுப்படுத்தினால், டோக்கனை மின்னஞ்சல் சூழலுக்குள் (email context) அனுப்பி, அதன் உள்ளடக்கத்தில் (body) எங்காவது தெரியும்படிச் செய்யவும். நீங்கள் ஒரு பிளாக்-பாக்ஸ் பயன்பாட்டை (black-box application) சோதிப்பதாக இருந்தால், அந்தப் பயன்பாடு ஏற்கனவே நீங்கள் பயன்படுத்தக்கூடிய ஒரு குறிப்பு புலத்தை (reference field) ஏற்கிறதா என்று பாருங்கள். இல்லையெனில், பிளஸ் அட்ரஸிங் (plus addressing) முறையைப் பயன்படுத்தி பெறுநரின் லோக்கல்-பார்ட்டில் (local-part) டோக்கனை இணைக்கலாம்—testuser+a4f9c2d1@example.com—ஆனால் உங்கள் பயன்பாடு அதை அப்படியே மின்னஞ்சலில் பிரதிபலிக்க வேண்டும் என்றால் மட்டுமே இது வேலை செய்யும்.

மின்னஞ்சல் அமைப்பு ஏற்கனவே வைத்திருக்கும் மெட்டாடேட்டாவை வைத்துப் பொருத்துவதை நிறுத்துவதே இதன் நோக்கம். உங்கள் சோதனைக்குச் சொந்தமான தரவை வைத்துப் பொருத்துங்கள்.

நம்பகமான முறை (The Reliable Pattern)

"புதிய செய்தி" அல்காரிதத்திற்குப் பதிலாக, டோக்கன் மூலம் இயங்கும் ஒரு குறுகிய தேடலைப் பயன்படுத்தவும்:

  1. எந்தச் செயல்பாட்டையும் தூண்டுவதற்கு முன் ரன் டோக்கனை உருவாக்கவும்.
  2. பயனர் செயல்பாட்டைத் தொடங்குங்கள், அதே நேரத்தில் பயன்பாடு வெளிச்செல்லும் மின்னஞ்சலில் டோக்கனைச் சேர்ப்பதை உறுதி செய்யவும்.
  3. அந்த டோக்கனுக்கு மட்டுமே கட்டுப்படுத்தப்பட்ட வடிகட்டிகளுடன் (filters) மின்னஞ்சல் வழங்குநரைச் சரிபார்க்கவும். API-ஆல் உள்ளடக்கத்தைத் தேட (body search) முடியுமென்றால், அதைப் பயன்படுத்தவும். இல்லையெனில், சாத்தியமான செய்திகளைப் பெற்று, அவற்றின் உள்ளடக்கத்தை கிளையண்ட் பக்கத்திலேயே (client-side) தேடவும் (grep).
  4. எந்தவொரு இணைப்புகள், பொத்தான்கள் அல்லது சரிபார்ப்பு குறியீடுகளைத் தொடங்குவதற்கு முன்பும், செய்தி உள்ளடக்கத்தில் டோக்கன் இருப்பதை உறுதி செய்யவும் (assert).
  5. அதன் பின்னரே உறுதிப்படுத்தல் URL அல்லது குறியீட்டைப் பிரித்தெடுத்துத் தொடரவும்.

இந்த வரிசைமுறை முக்கியமானது. நீங்கள் முதலில் ஒரு இணைப்பைப் பிரித்தெடுத்துவிட்டு, இரண்டாவதாக டோக்கனைச் சரிபார்த்தால், நீங்கள் ஏற்கனவே தவறான மின்னஞ்சலைக் கிளிக் செய்துவிட்டீர்கள் என்று அர்த்தம். சரிபார்ப்பு (assertion) என்பது உங்கள் பாதுகாப்புக் காவலர் (gatekeeper).

நடைமுறையில், உங்கள் helper Subject:"Welcome to AppName" sort:-received என்பதற்குப் பதிலாக Subject:"Welcome to AppName" AND Body:"a4f9c2d1" என்பதைத் தேட வேண்டும். பல மின்னஞ்சல் சோதனைச் சேவைகள் (mail testing services) உள்ளடக்கத் தேடல்களை (body content filters) ஏற்கும் search APIs-களை வழங்குகின்றன. அவற்றைப் பயன்படுத்தவும். நீங்கள் ஒரு எளிமையான provider-உடன் பணிபுரிந்தால், உங்கள் polling logic-ஐ ஒரே இடத்தில் வைத்திருக்கவும், இதன் மூலம் ஒவ்வொரு சோதனைக்கும் (test) ஒரே மாதிரியான client-side filtering-ஐ நீங்கள் சேர்க்க முடியும்.

அமைப்பைத் துல்லியமாக வைத்திருக்க மூன்று விதிகள்

ஒரு run token தேர்வினைத் துல்லியமாக்குகிறது, ஆனால் நீங்கள் எவ்வாறு poll செய்கிறீர்கள் மற்றும் ஏதேனும் தவறுகள் ஏற்படும் போது என்ன செய்கிறீர்கள் என்பதில் ஒழுக்கம் தேவை.

தோல்வியடையும் போது inbox நிலையைப் பதிவு செய்யவும் (Log the inbox state on failure). ஒரு சோதனை தோல்வியடையும் போது, inbox identifier, நீங்கள் தேடிய subject line, துல்லியமான timestamp window மற்றும் உங்கள் அளவுகோல்களுக்கு (criteria) எத்தனை செய்திகள் பொருந்தின என்பதை வெளியிடுங்கள். இது தெளிவற்ற "email not found" பிழையை ஒரு தெளிவான தகவலாக மாற்றுகிறது. வேலை 7823, வேலை 7821-லிருந்து வந்த ஒரு retry செய்தியை மூன்று வினாடிகள் தாமதமாக வந்ததால் எடுத்துக்கொண்டால், உங்கள் logs அதைத் தெளிவாகக் காட்ட வேண்டும். இந்தத் தகவல் இல்லையென்றால், நீங்கள் நேரக் குறைபாட்டை (timing)탓 செய்துவிட்டு, மீண்டும் ஒரு sleep-ஐச் சேர்த்துவிடுவீர்கள்.

அனைத்து email polling-களையும் ஒரே helper file-இல் வைத்திருக்கவும். setTimeout மற்றும் cy.task அழைப்புகளை இருபது சோதனைத் கோப்புகளில் (test files) சிதறடிக்க வேண்டாம். செய்திகளுக்காகக் காத்திருக்கும், API அழைப்பை மீண்டும் முயற்சிக்கும் (retry) மற்றும் backoff முறையைப் பயன்படுத்தும் logic-ஐ மையப்படுத்தவும். ஒவ்வொரு சோதனையும் ஒரே helper-ஐப் பயன்படுத்தினால், உங்கள் filtering விதிகள் சீராக இருக்கும், மேலும் நீங்கள் search logic-ஐ மேம்படுத்தும்போது, அனைத்துச் சோதனைகளும் பயனடையும். இது token check-ஐ நடைமுறைப்படுத்துவதையும் எளிதாக்குகிறது; helper ஒரு token argument-ஐக் கோரினால், யாரும் தற்செயலாக "latest message" என்ற எளிமையான முறையைச் சார்ந்திருக்க முடியாது.

உங்கள் retries-களைக் கவனியுங்கள். CI-இல் சோதனைத் திரும்பத் திரும்பச் செய்தல் (test retries) பொதுவானது, ஆனால் ஒவ்வொரு retry-யும் inbox-இல் மற்றொரு மின்னஞ்சலை உருவாக்குகிறது. உங்கள் சோதனை மூன்றாவது முயற்சியில் வெற்றியடைந்தால், நீங்கள் அதை mừngிக் கொண்டாடிவிட்டு அடுத்த வேலைக்குச் செல்லலாம். ஆனால் நீங்கள் கவனிக்கத் தவறுவது என்னவென்றால், முதல் மற்றும் இரண்டாவது முயற்சிகள் ஒரு உண்மையான பிழையை—ஒரு race condition, ஒரு duplicate send அல்லது ஒரு missing index போன்றவற்றை—வெளிப்படுத்தியிருக்கலாம், ஆனால் கூடுதல் செய்திகள் அதை மறைத்துவிட்டன. நீங்கள் retries-களைப் பயன்படுத்த வேண்டிய கட்டாயம் இருந்தால், தோல்விக்குப் பிறகு inbox-இல் எதிர்பாராத நகல்கள் (duplicates) உள்ளனவா என்று சரிபார்க்கவும். அதைவிடச் சிறப்பாக, உங்கள் provider dynamic inboxes-களை ஆதரித்தால், inbox-ஐச் சுத்தம் செய்வதையோ அல்லது ஒவ்வொரு வேலைக்கும் ஒரு தனித்துவமான முகவரியைப் பயன்படுத்துவதையோ பரிசீலிக்கவும். நம்பகத்தன்மையற்ற selection logic-ஐ மறைப்பதற்கான ஒரு உத்தியாக retries மாறக்கூடாது.

உண்மையான கருத்து

ஒரு inbox-ஐ தேதியைக் கொண்டு வரிசைப்படுத்தி, முதல் முடிவைப் பெறுவது சோதனை அல்ல. அது குறியீட்டில் (code) மறைக்கப்பட்ட ஒரு யூகமே ஆகும். ஒரு run token-க்குச் செலவு மிகக் குறைவு—ஒரு string variable, ஒரு கூடுதல் filter parameter, அல்லது ஒரு சிறிய template மாற்றம்—மற்றும் இது உங்கள் சோதனைக்குத் துல்லியமான அடையாளத்தை (deterministic identity) வழங்குகிறது. உங்கள் முன்னால் இருக்கும் செய்தி, நீங்கள் இப்போது இயக்கி வரும் run-க்குச் சொந்தமானது என்பதை இது நிரூபிக்கிறது.

sleeps-களைச் சேர்த்துவிட்டு நெட்வொர்க் சரியாகச் செயல்படும் என்று நம்புவதை நிறுத்துங்கள். ஒரு token-ஐ உருவாக்கி, அதை மின்னஞ்சலில் சேர்த்து, அதை நேரடியாகத் தேடுங்கள். உங்கள் CI runs வேகமானதாக இருக்கும், உங்கள் logs வாசிக்க எளிதாக இருக்கும், மேலும் மின்னஞ்சல் தொகுப்பு (email suite) உங்களுக்குச் சொல்வதை நீங்கள் இறுதியாக நம்புவீர்கள்.