Integration ტესტები მონაცემთა ბაზებით (Node.js + Mocha მაგალითზე)

კოდის ავტომატური ტესტები რამდენიმე ჯგუფად იყოფა. მოკლედ რომ ვთქვათ, Unit ტესტი გამოიყენება კოდის მცირე ფრაგმენტების გასატესტად. მაგალითად, თუ გვაქვს ტელეფონის ნომრის ფორმატირების ფუნქცია, მისთვის შეიძლება რამდენიმე unit ტესტი გვქონდეს სხვადასხვა შემთხვევის დასაფარად. მაგრამ თუ გვინდა შევამოწმოთ, როგორ რეგისტრირდება მომხმარებელი ამ ტელეფონის ნომრით და შემდეგ ავტორიზაციას გადის, უკვე რამდენიმე კომპონენტის ურთიერთობა უნდა მოვაქციოთ ჩვენს ტესტში – ეს integration ტესტია.

როგორც წესი, Integration ტესტთან გვაქვს საქმე, თუ ტესტი იყენებს:

  • მონაცემთა ბაზას
  • ქსელს
  • რაიმე გარე სისტემას (მაგ: მეილ სერვერს)
  • I/O ოპერაციებს

ზუსტად ამაშია მისი სირთულე, რომ უწყინარი unit ტესტების მსგავსად გარე სისტემებზე პირდაპირ ვერ შევასრულებთ სატესტო ოპერაციებს. მაგალითად, ასობით სატესტო მეილს ვერ გავგზავნით შემთხვევით გენერირებულ მისამართებზე. ასეთი პრობლემის გადასაჭრელად რამდენიმე გზა არსებობს, გააჩნია ჩვენ რისი ტესტირება გვსურს. მოდი ვარიანტებს შევხედოთ:

 

სერვისის იმიტაცია (Stubs, Mocks)

მაგალითად, ვწერთ კლიენტ აპლიკაციას, რომელიც სხვადასხვა სერვერზე არსებულ სერვისებს იძახებს. ანუ, ჩვენთვის კლიენტის კოდის შემოწმებაა მნიშვნელოვანი და არ გვსურს, რომ მან რეალურად გამოიყენოს სერვისები. ასეთ დროს შეგვიძლია სერვისის stub, ანუ სერვისის იმიტაცია გავაკეთოთ, რომელსაც ზუსტად იგივე ფუნქციები და პარამეტრები აქვს რაც ნამდვილს, უბრალოდ ლოგიკის შესრულების ნაცვლად პირდაპირ ჩვენს მიერ გაწერილ ფიქსირებულ პასუხებს აბრუნებს.

function sendMail(email, content) {
    console.log(‘Email sent to: ‘ + email);
    return true;
}

როდესაც ტესტირების რეჟიმში გავუშვებთ პროგრამას, მას ნამდვილი სერვისის ობიექტის ნაცვლად ჩვენი ყალბი სერვისი უნდა გამოვაყენებინოთ (ამის დეტალებს ცალკე პოსტში შემოგთავაზებთ).

 

მონაცემთა ბაზის გამოყენება

ახლა, ვთქვათ, სერვისს ვწერთ, რომელიც ინტენსიურად იყენებს მონაცემთა ბაზას და მის შესამოწმებლად გვინდა integration ტესტები. ცხადია, შეგვიძლია რომ ბაზის ფენაც stub-ით ჩავანაცვლოთ და select-ებმა, insert-ებმა, ა.შ. ფიქსირებული მნიშვნელობები დაგვიბრუნოს. თუმცა ხშირ შემთხვევაში ეს არაპრაქტიკულია და რეალურად პროცესებს შორის ურთიერთობა ვერ მოწმდება. მაგალითად, მინდა რომ მომხმარებელი დარეგისტრირდეს, გაააქტიუროს თავისი ანგარიში და გაიაროს ავტორიზაცია. ასეთი ოპერაციები ბაზის რამდენიმე ცხრილს იყენებს და მირჩევნია, რომ რეალურად ბაზაზე შესრულდეს.

ასეთ შემთხვევაშიც არსებობს რამდენიმე გამოსავალი. მაგალითად, მე ვამჯობინებ, რომ ცალკე ცარიელი ბაზა მქონდეს. არც in-memory და არც ბაზის მსუბუქი ალტერნატივა, არამედ ზუსტად იგივენაირი ბაზა, ოღონდ მხოლოდ ტესტებისთვის განკუთვნილი.
როდესაც ტესტირების რეჟიმში გაეშვება ჩემი პროგრამა, ის შესაბამისი კონფიგურაციიდან აიღებს სატესტო ბაზის მისამართს და სწორედ მას გამოიყენებს არენად. ტესტების ყოველი გაშვების წინ კი ცხრილებიდან ჩანაწერებს წაშლის, რომ არსებულმა მონაცემებმა ხელი არ შეუშალოს.

Node-ისა და Mocha-ს მაგალითზე გავაკეთებ ამას

წინა პოსტში სხვადასხვა გარემოს დაკონფიგურირებაზე ვსაუბრობდი. Mocha-ს ტესტებს მთლად ცალკე გარემოდ არ ვთვლი, რადგან შეიძლება გვქონდეს dev და test, ან კიდევ build სერვერები და ყველა მათგანზე ვუშვებდეთ ტესტებს. თუმცა ანალოგიურ მიდგომას – environment ცვლადებს გამოვიყენებ ტესტების გარემოს დასაკონფიგურირებლადაც და შევქმნი ფაილს .env.mocha

აქვე აღვნიშნავ: dotenv-ის აღწერაში თუ შეიხედავთ, იქ მუქად წერია, რომ არ არის რეკომენდირებული გვქონდეს .env, env.test, env.prod და ასე გამოყოფილი ფაილები, არამედ მხოლოდ ერთი .env ფაილი, რომელსაც სხვადასხვა სერვერზე სხვადასხვა შიგთავსი აქვს. ჩემი აზრით .env.mocha სულ სხვა მიზანს ემსახურება და ამ წესში არ შედის.

შემდეგი ნაბიჯია, რომ ტესტების გაშვების დროს ნამდვილის ნაცვლად .env.mocha ფაილი იყოს გამოყენებული. ინტერნეტში ამის კროს-პლატფორმული მუშა მაგალითი არ არის, მე კი ვინდოუსზე მიყვარს მუშაობა. ამიტომ ჩემს ვარიანტს შემოგთავაზებთ, სადაც ყველა ტესტ ფაილში არ მოგიწევთ კონფიგურაციის ჩატვირთვა:

  • პროექტის საქაღალდეში .env-ის გვერდით შევქმნათ .env.mocha და შევავსოთ სასურველი კონფიგურაციით.
  • test საქაღალდეში შევქმნათ ფაილი setup.js და შიგნით ჩავწეროთ ეს ხაზი:
    require('dotenv').config({path:__dirname + '/../.env.mocha'});
  • test საქაღალდეში შევქმნათ კიდევ ერთი ფაილი – mocha.opts და შიგნით ჩავწეროთ:
    --require test/setup.js

სულ ეს არის.
npm test-ს რომ გავუშვებთ პროექტზე, ტესტები ავტომატურად ყველგან .env.mocha კონფიგურაციას გამოიყენებენ.

თავი რომ დავიზღვიო და დარწმუნებული ვიყო რომ mocha-ს გაშვებისას ნამდვილად შესაბამისი კონფიგურაცია არის ჩატვირთული და სამუშაო ბაზა არ წავშალო, კიდევ რაიმე ცვლადს ჩავამატებ .env.mocha ფაილში და მხოლოდ მისი არსებობის შემთხვევაში გავაგრძელებ setup.js-ის შესრულებას (მაგალითად: MOCHA_CONFIG_LOADED=yes)

მე ასევე მინდა, რომ ყოველ გაშვებაზე ცხრილები დაცარიელდეს. Mocha-ს აქვს სხვადასხვა ჰუკები, მათ შორის before(), რომელსაც თუ describe-ის შიგნით აღვწერთ, მაშინ test suite-ის გაშვების წინ შესრულდება, ხოლო თუ გლობალურად აღვწერთ, მაშინ სულ ყველა ტესტამდე ერთხელ შესრულდება. სწორად მას გამოვიყენებ, რომ ტესტირების დაწყებისას ცხრილები დავაცარიელო. კარგი იქნებოდა, რომ setup.js ფაილშივე შეიძლებოდეს მისი აღწერა, მაგრამ თუ ცდით, ნახავთ რომ იქ mocha არ არის ჯერ ჩატვირთული და before ცვლადს ვერ იპოვის. ამიტომ test საქაღალდეში დავამატე ფაილი hooks.js და ამ ფაილში აღვწერე ჩემი გლობალური ჰუკები.

თუ Integration ტესტების შესრულებას დიდი დრო მიაქვს, შესაძლებელია ისე დააკონფიგურიროთ package.json-ში სკრიპტები, რომ unit ტესტებისა და integration ტესტების გაშვება (დირექტორიის დონეზე) ცალცალკე ბრძანებით ხდებოდეს.

გამოხმაურება

comments

კომენტარის დატოვება

თქვენი ელფოსტის მისამართი გამოქვეყნებული არ იყო. აუცილებელი ველები მონიშნულია *