ბიბლიოთეკა
00/08 · ~38 წთ
GUIDEDECK · კოდისთვის, რომელსაც შიშის გარეშე შეცვლით

ტესტირება & TDD
— მტკიცებულება, რომ კოდი
იმას აკეთებს, რასაც ფიქრობთ.

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

~38 წთშერეული გუნდიენისგან დამოუკიდებელი
გადაახვიეთ
01 · რატომ ვტესტავთ 4 წთ

ტესტი არის მტკიცება თქვენს კოდზე,
რომელსაც მანქანა უფასოდ ამოწმებს.

ტესტები იმას არ ემსახურება, რომ დღეს თქვენი სიმართლე დაამტკიცოთ. ისინი იმისთვისაა, რომ შემდეგმა ადამიანმა — ხშირად მომავალმა თქვენ — ამ კოდის შეცვლა სუნთქვაშეკრული არ მოუწიოს. ბაგის დაჭერა ყველაზე იაფი მაშინაა, როცა მას წერთ, შემდეგ კი ფასი მხოლოდ იზრდება.

ტესტი — ავტომატური შემოწმება — თქვენი კოდის ნაწილს ცნობილი შემავალი მონაცემებით უშვებს და ამტკიცებს, რომ შედეგი მოლოდინს ემთხვევა. მწვანე ნიშნავს, რომ მტკიცება ჯერ კიდევ ძალაშია; წითელი — რომ რაღაც შეიცვალა. მთელი ღირებულება სწრაფ, გამეორებად ხელახალ შემოწმებაშია — და არა იმ ერთხელ, როცა ხელით გაუშვით.
1×

ღირს ბაგის გასწორება, როცა მას აკრეფის დროსვე იჭერთ.

10×

…როცა უკვე შემერჯულია და მასზე სხვამ ააშენა.

100×

…როცა უკვე პროდაქშენშია და ღამის 2 საათზე გიძახებენ.

∞

ბაგი, რომელიც ჩუმად გადის და მონაცემებისადმი ნდობას ღრღნის.

რას გაძლევთ სინამდვილეში ტესტების ნაკრები

მიზანი 100% დაფარვა არაა. მიზანი დახარჯულ წუთზე მიღებული ნდობაა.

02 · ტესტების პირამიდა 5 წთ

ბევრი სწრაფი ტესტი,
რამდენიმე ნელი.

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

ტესტების პირამიდა — პროპორციის მეგზური — ტესტებს მოცულობისა და ღირებულების მიხედვით ალაგებს: იუნიტი (ერთი ნაწილი იზოლაციაში) ფართო ფუძეზე, ინტეგრაცია (რამდენიმე ნაწილი ერთმანეთთან შეერთებული) შუაში და ბოლოდან ბოლომდე (მთელი სისტემა, როგორც რეალური მომხმარებელი) ვიწრო წვერზე. რაც უფრო ფართოა, მით უფრო იაფი, სწრაფი და მრავალრიცხოვანია.
E2E ~10% · slow Integration ~20% Unit ~70% · fast cost · scope ↑

გავრცელებული ორიენტირია დაახლოებით 70% იუნიტი, 20% ინტეგრაცია, 10% ბოლოდან ბოლომდე — ბიუჯეტის უმეტესობა სწრაფ ფუძეზე, რომელიც ნელი, სრულსისტემური წვერისკენ თხელდება.

სამი შრე

  • იუნიტი — ერთი ფუნქცია ან კლასი, დამოკიდებულებები ჩანაცვლებული. მილიწამები. ზუსტად მიგითითებთ, რომელი ხაზი გატყდა.
  • ინტეგრაცია — ნამდვილი თანამონაწილეები ერთმანეთთან შეერთებული (კოდი + ბაზა, ორი მოდული, HTTP-ჰენდლერი). ამტკიცებს, რომ ნაკერები ერგება.
  • ბოლოდან ბოლომდე — დადეპლოებული სისტემა, მართული როგორც მომხმარებლის მიერ (ბრაუზერი, შემომავალი API-გამოძახება, ბაზა გამოსავალზე). ამტკიცებს, რომ მთელი მარშრუტი მუშაობს.

რაც უფრო მაღლა, მით უფრო რეალისტურია, მაგრამ ნელი, არასტაბილური და გასამართად რთული. ნდობას ფასი აქვს; პირამიდა ანგარიშს გონივრულ ფარგლებში ატარებს.

ნაყინის რქა (ანტიპატერნი)

გუნდების უმეტესობა თავდაყირა პირამიდისკენ მიდის: ნელი ბოლოდან ბოლომდე ტესტების სქელი შრე და თითქმის არცერთი იუნიტ-ტესტი. ნაკრები 40 წუთს ითხოვს, შემთხვევით ვარდება და წითელს აღარავინ ენდობა.

  • ნელი უკუკავშირი → ხალხი მას ლოკალურად აღარ უშვებს.
  • ჩავარდნა ნებისმიერ ადგილას შეიძლება იყოს — გამართვა ნადირობად იქცევა.
  • არასტაბილურობა გუნდს წითელი ბილდების იგნორირებას აჩვევს.

ჯანსაღი ფორმა

ლოგიკა ქვემოთ ჩამოწიეთ: ფასდადების წესი იუნიტად დატესტეთ და არა ჩექაუთში კლიკებით. E2E რამდენიმე კრიტიკულ მარშრუტს დაუტოვეთ — რეგისტრაცია, ჩექაუთი, ფულის გზა.

  • სწრაფი ფუძე ყოველ შენახვაზე ეშვება.
  • წითელი იუნიტ-ტესტი ზუსტად ასახელებს გატეხილ ქცევას.
  • E2E მარშრუტებს იცავს და არა არითმეტიკას.

ჰგავს  კორექტურას: ყოველ წინადადებას მართლწერა შეუმოწმეთ, მაგრამ მთელი ესეს ხმამაღლა წაკითხვა მხოლოდ ორიოდე ჯერ დაგჭირდებათ.

03 · კარგი ტესტის ანატომია 5 წთ

Arrange, Act, Assert —
ერთი ქცევა, დასახელებული მარტივი ენით.

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

AAA — Arrange · Act · Assert — თითქმის ყველა ტესტის ჩონჩხია. Arrange — მოამზადეთ შემავალი მონაცემები და სატესტო სისტემა, Act — გამოიძახეთ ის ერთი რამ, რასაც ტესტავთ, შემდეგ Assert — შეამოწმეთ შედეგი. სამი ვიზუალური ბლოკი, ამ თანმიმდევრობით, ყოველთვის.
ბუნდოვანი და არეული
test("test1", () => {
  const c = new Cart()
  c.add(book); c.add(pen)
  expect(c.total()).toBe(30)
  c.applyCoupon("SAVE10")        // second behavior…
  expect(c.total()).toBe(27)
  expect(c.items.length).toBe(2)  // …and a third
})
// what broke? the name won't tell you.
ერთი ქცევა, AAA, სახელით
test("applies a 10% coupon to the cart total", () => {
  // Arrange
  const cart = cartWith(book30)

  // Act
  cart.applyCoupon("SAVE10")

  // Assert
  expect(cart.total()).toBe(27)
})

დაასახელეთ ქცევის მიხედვით

ტესტის სახელი დოკუმენტაციაა. მკითხველმა უნდა იცოდეს, რა გატყდა, სხეულის გახსნის გარეშე. აღწერეთ სცენარი და მოსალოდნელი შედეგი — არასდროს test1.

აკეთებს X-ს, როცა Yაბრუნებს ცარიელს, თუ დამთხვევა არაააგდებს შეცდომას უარყოფით თანხაზე
// სცენარი → მოსალოდნელი შედეგი "უარყოფს შესვლას 3 წარუმატებელი მცდელობის შემდეგ" "ამრგვალებს გადასახადს უახლოეს ცენტამდე" "აბრუნებს 404-ს, როცა შეკვეთა არ არსებობს"

FIRST თვისებები

F
Fast
მილიწამები და არა წუთები
I
Isolated
არც საერთო მდგომარეობა, არც თანმიმდევრობა
R
Repeatable
ერთი და იგივე შედეგი ყოველ გაშვებაზე
S
Self-checking
გავიდა/ჩავარდა, თვალით ჩხრეკის გარეშე
T
Timely
იწერება კოდთან ერთად

დაარღვიეთ რომელიმე მათგანი და ნაკრები გახდება ნელი, არასტაბილური ან ჩუმად უსარგებლო. Isolated და Repeatable ისინია, რომლებსაც გუნდები ყველაზე ხშირად არღვევენ — ჩვეულებრივ საერთო მონაცემთა ბაზებითა და საათით.

04 · ტესტით მართული განვითარება 6 წთ

წითელი → მწვანე → რეფაქტორინგი.

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

TDD — Test-Driven Development, ტესტით მართული განვითარება — მჭიდრო ციკლია: დაწერეთ პატარა ჩავარდნილი ტესტი შემდეგი ქცევისთვის (წითელი), დაწერეთ ზუსტად იმდენი კოდი, რომ ის გავიდეს (მწვანე), შემდეგ კი გააკეთეთ რეფაქტორინგი, სანამ ტესტი გიცავთ. გაიმეორეთ წუთოვან ციკლებში. პროდაქშენ-კოდს არასდროს წერთ ისე, რომ მას ჩავარდნილი ტესტი არ ითხოვდეს.

პატარა ციკლები, თითო რამდენიმე წუთი. ტესტი წითლდება მანამ, სანამ კოდი გაჩნდება, შემდეგ კი მას მწვანემდე მიჰყავს.

სამი კანონი (Uncle Bob)

1არ დაწეროთ პროდაქშენ-კოდი, სანამ არ გექნებათ ჩავარდნილი ტესტი, რომელიც მას მოითხოვს.
2დაწერეთ ზუსტად იმდენი ტესტი, რომ ჩავარდეს — კომპილაციის შეცდომაც ჩავარდნად ითვლება.
3დაწერეთ ზუსტად იმდენი პროდაქშენ-კოდი, რომ ჩავარდნილი ტესტი გავიდეს — მეტი არაფერი.

დისციპლინა პაწაწინა ნაბიჯებს გაიძულებთ. ცნობილ, გამართულ მდგომარეობას ყოველთვის სულ რამდენიმე წუთით სცილდებით.

რატომ ცვლის დიზაინს ჯერ ტესტის დაწერა

ჯერ კოდი — ტესტი მერე მიაწებეს
// written, then "how do I even test this?"
function checkout() {
  const now = Date.now()         // hidden clock
  const db = new Postgres()      // hidden dependency
  // 60 lines of mixed I/O + rules…
}
// untestable without a real DB and the right date.
ჯერ ტესტი — ნაკერები თავისით ჩნდება
// the test you wished you could write FIRST:
test("10% off orders over $100", () => {
  const price = discount(120)
  expect(price).toBe(108)
})
// forces a pure fn: inputs in, result out.
function discount(total) { /* no clock, no DB */ }

TDD-ის ნამდვილი საჩუქარი ტესტები არაა — არამედ ის, რომ ძნელად სატესტი კოდი ტყუილად როდი არის ძნელად სატესტი, და ტესტის ჯერ დაწერა ამ ტკივილს მაშინ ამოატივტივებს, როცა მისი გასწორება ჯერ კიდევ იაფია.

05 · ტესტ-დუბლიორები 6 წთ

შემცვლელები იმ
თანამონაწილეებისთვის, რომელთა გამოძახებაც არ გინდათ.

იმისთვის, რომ ერთეული იზოლაციაში დატესტოთ, მის ნამდვილ დამოკიდებულებებს — მონაცემთა ბაზას, გადახდის gateway-ს, საათს — მართვად შემცვლელებს უნაცვლებთ. "მოკს" ყველა მათგანზე ამბობენ, მაგრამ ხუთი ტიპი სხვადასხვა საქმეს აკეთებს.

ტესტ-დუბლიორი — ნამდვილი დამოკიდებულების შემცვლელი — საშუალებას გაძლევთ, სატესტო სისტემა (SUT) მისი ნამდვილი თანამონაწილეების გარეშე გაუშვათ. სასაუბრო ენაზე ყველა მათგანს მოკს ეძახიან, მაგრამ ზუსტად რომ ვთქვათ, დამი (dummy), სტაბი (stub), სპაი (spy), მოკი (mock) და ფეიქი (fake) სხვადასხვა ინსტრუმენტია.

დუბლიორი ნამდვილი gateway-ის ნაცვლად შეიყვანეთ. SUT განსხვავებას ვერ ხედავს — სწორედ ამას გაძლევთ დამოკიდებულებების ინექცია.

მდგომარეობის vs ქცევის შემოწმება

  • სტაბები & ფეიქები SUT-ს მონაცემებით კვებავს — შემდეგ თქვენ შედეგს ამოწმებთ (მდგომარეობის შემოწმება). ეს ჯობია.
  • მოკები & სპაები გამოძახებებს იწერს — თქვენ ამოწმებთ, რომ SUT-მა თანამონაწილე გარკვეული სახით გამოიძახა (ქცევის შემოწმება).
  • ქცევის შემოწმება ტესტს იმას აბამს, როგორ მუშაობს კოდი და არა იმას, რას აწარმოებს. გამოიყენეთ მხოლოდ მაშინ, როცა გამოძახება თავად არის ქცევა (მაგ. "აგზავნის იმეილს").

დამი — ადგილმჭერი, რომელიც არასდროს გამოიყენება

// passed only to satisfy a signature; never called
const logger = {} as Logger
new Invoice(items, logger)   // this test never logs
როდის გამოვიყენოთ
კონსტრუქტორი ან მეთოდი ითხოვს არგუმენტს, რომელსაც სატესტო გზა არ ეხება.
ფრთხილად
თუ ის მაინც გამოიძახება, სინამდვილეში სტაბი გინდოდათ.

სტაბი — აბრუნებს წინასწარ მომზადებულ პასუხებს

// pre-programmed responses, no logic of its own
const rates: RateApi = {
  usdTo: () => 0.8   // always returns 0.8, whatever the input
}
expect(convert(100, rates)).toBe(80)
როდის გამოვიყენოთ
გჭირდებათ, რომ თანამონაწილემ კონკრეტული შემავალი მონაცემი მოგაწოდოთ და შედეგი შეამოწმოთ.
სინამდვილეში ეს არის
მდგომარეობის შემოწმება — ამოწმებთ გამოსავალს და არა გამოძახებას.

სპაი — სტაბი, რომელიც იწერს, როგორ გამოიძახეს

const sent: string[] = []
const mailer: Mailer = {
  send: (to, body) => { sent.push(to) }   // records
}
notifyAll(users, mailer)
expect(sent).toEqual(["a@x.io", "b@x.io"])
როდის გამოვიყენოთ
გინდათ გამოძახებები ფაქტის შემდეგ შეამოწმოთ, მოლოდინების წინასწარ დაყენების გარეშე.
მოკისგან განსხვავებით
სპაი იწერს და თქვენ მოგვიანებით ამოწმებთ; მოკი კი გზადაგზა ამოწმებს.

მოკი — წინასწარ დაყენებული მოლოდინები, ვარდება, თუ არ შესრულდა

// the expectation IS the assertion
const gateway = mock<Payment>()
expect(gateway.charge).toHaveBeenCalledWith(2000, "usd")
// the test fails if charge() wasn't called exactly so
როდის გამოვიყენოთ
თავად ურთიერთქმედება არის ქცევა — "ბარათს ერთხელ უნდა ჩამოეჭრას".
ფრთხილად
ზედმეტი მოკირება ტესტებს იმპლემენტაციაზე აჭედებს. იხილეთ ნაწილი 6.

ფეიქი — ნამდვილი, მსუბუქი იმპლემენტაცია

// working logic, just not production-grade
class InMemoryUserRepo implements UserRepo {
  private rows = new Map()
  save(u) { this.rows.set(u.id, u) }
  findById(id) { return this.rows.get(id) }
}
როდის გამოვიყენოთ
გინდათ რეალისტური ქცევა (ბაზა, საათი) ნამდვილის ღირებულების გარეშე.
საუკეთესო ორივედან
სტაბივით სწრაფია, მაგრამ მართლა მუშაობს — შესანიშნავია ინტეგრაციული ტესტებისთვის.
06 · დაფარვა, არასტაბილურობა და რა არ ვტესტოთ 5 წთ

დაფარვა რუკაა,
და არა ტერიტორია.

მწვანე 100%-იც კი ბაგებს გაუშვებს, არასტაბილური ნაკრები კი მის არარსებობაზე უარესია. იმის ცოდნა, რა არ დატესტოთ, ისევე მნიშვნელოვანია, როგორც იმისა, რა დატესტოთ.

კოდის დაფარვა — გაშვებისას შესრულებული ხაზების/განშტოებების პროცენტი — გეუბნებათ, რას შეეხო თქვენი ტესტები, და არასდროს იმას, დაამტკიცა თუ არა რამე სასარგებლო. ეს შესანიშნავი გზაა დაუტესტავი კოდის საპოვნელად და საშინელი მიზანი 100%-მდე დასადევნად.
დაფარულია, არაფერს ამტკიცებს
test("runs without error", () => {
  calculateTax(order)   // 100% line coverage…
})
// no assertion → tax could be -∞ and this stays green.
ამტკიცებს მთავარ ქცევას
test("charges 8% tax, rounded to the cent", () => {
  expect(calculateTax({ subtotal: 49.99 }))
    .toBe(4.00)
})
// same line covered — but now it actually checks the rule.
არასტაბილური

ტესტები, რომლებიც ცრუ განგაშს ტეხენ

არასტაბილური ტესტი კოდის ცვლილების გარეშე ხან გადის, ხან ვარდება. ყოველი ცრუ განგაში გუნდს წითელის იგნორირებას ასწავლის — ნაკრები კი, რომელსაც არავინ ენდობა, მკვდარი ტვირთია.

  • დრო — Date.now(), სასაათო სარტყლები, დაძინებები. შეიყვანეთ საათი.
  • თანმიმდევრობა & საერთო მდგომარეობა — სხვა ტესტისგან დარჩენილი სტრიქონი ბაზაში. მოახდინეთ იზოლირება.
  • ასინქრონულობა & რბოლები — ფიქსირებული sleep(500) პირობის მოლოდინის ნაცვლად.
  • შემთხვევითობა & ქსელი — უსიდო შემთხვევითი რიცხვები, ცოცხალი გამოძახებები მესამე მხარეებთან.

ჰგავს  კვამლის სენსორს, რომელიც შემთხვევით წრიპინებს — ხალხი ბატარეას ამოაძვრენს და მერე ის ვეღარაფერზე გაფრთხილებთ.

რა არ ვტესტოთ

დატესტეთ ქცევა და არა მილსადენი

  • ენა / ფრეიმვორკი — ნუ დატესტავთ, რომ გეტერი იმას აბრუნებს, რაც დააყენეთ.
  • პრივატული შიგთავსი — დატესტეთ საჯარო ზედაპირით; პრივატული მეთოდები თავისუფლად იცვლება.
  • ტრივიალური წებო — ერთხაზიანი გამტარი ლოგიკის გარეშე ცოტას თუ იძლევა.
  • იმპლემენტაციის დეტალები — "იძახებს ჰელპერ X-ს, მერე Y-ს" აცემენტებს იმას, როგორ, და რეფაქტორინგს ბლოკავს.

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

დაფარვა იმ ქვედა ზღვარზე მიმართეთ, რომელიც აშკარა ხარვეზებს იჭერს (ვთქვათ, 70–80% შეცვლილ კოდზე), დაზოგილი ენერგია კი უკეთეს მტკიცებებსა და სასაზღვრო შემთხვევებს — ზღვრებს, ცარიელ მნიშვნელობებს, შეცდომებს — დაუთმეთ და არა ბოლო, დაუტესტავი პროცენტის დევნას.

07 · ინსტრუმენტების ლანდშაფტი 4 წთ

აირჩიეთ გამშვები ფუძისთვის,
ბრაუზერის დრაივერი წვერისთვის.

ინსტრუმენტები პირამიდის მიხედვით იყოფა. ტესტების გამშვები იუნიტ- და ინტეგრაციული შრეების სამუშაო ცხენია; ბოლოდან ბოლომდე (E2E) ფრეიმვორკი კი ნამდვილ ბრაუზერს მართავს თხელი წვერისთვის. ჩვეულებრივ თითო-თითოს ირჩევთ და მიდიხართ — ნუ იტანჯებით.

ტესტების გამშვები — პროგრამა, რომელიც თქვენს ტესტებს უშვებს — პოულობს სატესტო ფაილებს, თითოეულს ასრულებს და მწვანე/წითელ ანგარიშს ბეჭდავს (უმეტესობა დაფარვასაც ზომავს). E2E ფრეიმვორკი უფრო შორს მიდის: ხსნის ნამდვილ ბრაუზერს, რომელშიც შეუძლია დააკლიკოს და აკრიფოს, ასე რომ მომხმარებლის მთელი მარშრუტის შემოწმება შეგიძლიათ. ქვემოთ წამყვანი ვარიანტებია, თითოეულთან ერთი დადებითი და ერთი ხაფანგი.
E2E few · slow Playwright Cypress Integration some Jest · Vitest JUnit · PyTest Unit many · fast Jest · Vitest JUnit · PyTest one runner + one driver

ერთი და იგივე გამშვები ჩვეულებრივ ფარავს იუნიტ- და ინტეგრაციულ ტესტებს; E2E ფრეიმვორკი კი ზემოდან დგას იმ რამდენიმე სრულმარშრუტიანი ტესტისთვის.

სინამდვილეში ეს ორი არჩევანია

  • გამშვები — თითო ენაზე ერთი. JavaScript-ის გუნდები Jest-ს ან Vitest-ს ირჩევენ; Java იყენებს JUnit-ს; Python — PyTest-ს. აქ ცხოვრობს თქვენი ტესტების უმეტესობა.
  • E2E ფრეიმვორკი — Playwright ან Cypress. ის ბრაუზერს უშვებს და მომხმარებელივით იქცევა, ამიტომ თავს მხოლოდ რამდენიმე კრიტიკულ მარშრუტზე ირჩენს.
  • რასაც არ უნდა აირჩევდეთ, ამ დეკის დანარჩენი ჩვევები — AAA, დასახელება, წითელი მწვანემდე — ბევრად უფრო მნიშვნელოვანია, ვიდრე ინსტრუმენტზე დაწერილი ბრენდი.

იუნიტ- & ინტეგრაციული გამშვებები

JavaScript · Jest

Jest

დიდი ხნის ნაგულისხმევი არჩევანი JS/TS-ისთვის. ერთი ინსტალაცია ერთად გაძლევთ გამშვებს, მტკიცებებს, მოკირებასა და დაფარვას.

  • დადებითი  ყველაფერი ყუთშია, ყველაზე დიდი საზოგადოება და ყველაზე მეტი გაკვეთილი.
  • უარყოფითი  დიდ ნაკრებებზე ნელია; ნატიური ES-მოდულებისა და TypeScript-ის დაყენება ხანდახან წვალებაა.
JavaScript · Vitest

Vitest

თანამედროვე მოწინააღმდეგე, აშენებული Vite-ის ბანდლერზე. მისი API Jest-ის სარკეა, ამიტომ გადმოსვლა ძირითადად ძებნა-ჩანაცვლებაა.

  • დადებითი  ძალიან სწრაფი watch-რეჟიმი; TypeScript და ES-მოდულები ყუთიდანვე მუშაობს.
  • უარყოფითი  უფრო ახალგაზრდაა, ამიტომ Jest-ის ზოგი პლაგინი და კიდური შემთხვევა ჯერ არ არის დაფარული.
Java · JUnit

JUnit

Java-ს დე ფაქტო სტანდარტი (JUnit 5). ყველა IDE და საბილდე ინსტრუმენტი (Maven, Gradle) მას ნატიურად ხვდება.

  • დადებითი  მყარი, უნივერსალური და ღრმად ინტეგრირებული Java-ს ინსტრუმენტებთან.
  • უარყოფითი  მარტო თავისთავად მწირია — წასაკითხად ნათელი შემოწმებებისთვის AssertJ-ს დაამატებთ, დუბლიორებისთვის კი Mockito-ს.
Python · PyTest

PyTest

Python-ის მთავარი არჩევანი. წერთ უბრალო assert-ს და ის დეტალურ შეცდომის შეტყობინებას თქვენ მაგივრად ქმნის.

  • დადებითი  თითქმის არავითარი ზედმეტი კოდი; ძლიერი ფიქსტურები და უზარმაზარი პლაგინების ეკოსისტემა.
  • უარყოფითი  ფიქსტურებისა და პლაგინების "ჯადოქრობის" მიდევნება დიდ ნაკრებში რთულდება.

ბოლოდან ბოლომდე ბრაუზერის დრაივერები

E2E · Playwright

Playwright

Microsoft-ის ბრაუზერის ავტომატიზაციის ინსტრუმენტი. ბრაუზერს გარედან მართავს და ელემენტებს ავტომატურად ელოდება, რაც ტესტებს უფრო მდგრადს ხდის.

  • დადებითი  სწრაფია, სამივე ბრაუზერის ძრავს ტესტავს (Chromium, Firefox, WebKit) და გამართვისთვის შესანიშნავი ტრეისის მნახველი აქვს.
  • უარყოფითი  იმდენი ფუნქციონალი აქვს, რომ API-ის შესწავლას ცოტა დრო სჭირდება.
E2E · Cypress

Cypress

თქვენს ტესტს ბრაუზერის შიგნით უშვებს, ყოველი ნაბიჯის ცოცხალი, დროში მოგზაურობის ხედით — უყვართ დეველოპერული გამოცდილების გამო.

  • დადებითი  შესანიშნავი გამართვა: ყოველი ნაბიჯის გამეორებას უყურებთ და გვერდს ნებისმიერ მომენტში ამოწმებთ.
  • უარყოფითი  სუსტია მრავალტაბიან და ბრაუზერთაშორის მხარდაჭერაში; პარალელური გაშვებები ფასიან დაშბორდს ეყრდნობა.
როგორ ავირჩიოთ — ახალი JS/TS პროექტისთვის (განსაკუთრებით, თუ უკვე Vite-ზეა) დაიწყეთ Vitest-ით; დარჩით Jest-ზე, თუ დიდი, არსებული Jest-ნაკრები გაქვთ. Java-ს გუნდები იყენებენ JUnit 5-ს (პლუს Mockito); Python-ის გუნდები — PyTest-ს. ბოლოდან ბოლომდე ტესტებისთვის ნაგულისხმევად აიღეთ Playwright სიჩქარის, ბრაუზერთაშორისი დაფარვისა და CI-ის გამო; Cypress აირჩიეთ, თუ თქვენს გუნდს მისი ბრაუზერშიდა გამართვა უფასდება და მხოლოდ Chromium-ზე უშვებთ.
08 · შველის თუ კეტავს · შეჯამება 3 წთ

ტესტმა ბაგი უნდა დაიჭიროს —
და არა ადგილზე გაყინოს.

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

ბაგს აცემენტებს
// the code is wrong; the test "documents" the wrong number
test("shipping for 0 items", () => {
  expect(shippingFee([])).toBe(5)
})
// empty carts shouldn't ship at all — but now green
// "proves" the bug. Fixing it breaks the suite.
იჭერს მას (დაწერეთ ბაგის რეპორტიდან)
// a failing test that names the intended behavior
test("empty cart has no shipping fee", () => {
  expect(shippingFee([])).toBe(0)
})
// red now → fix shippingFee → green. The test is the spec.

რეგრესიული ტესტის წესი: ყოველი ბაგის გასწორება იწყება ტესტით, რომელიც ბაგის გამო ვარდება. ჯერ გაიმეორეთ, მერე გაასწორეთ — რომ ის შეუმჩნევლად ვეღარასდროს დაბრუნდეს.

1დააოპტიმიზირეთ ნდობაზე და არა დაფარვაზე. მწვანე ციფრი შესრულებას ამტკიცებს და არა სისწორეს.
2ააწყვეთ პირამიდა. ბევრი სწრაფი იუნიტ-ტესტი, ნაკლები ინტეგრაციული და რამდენიმე E2E იმ მარშრუტებზე, რომლებსაც მნიშვნელობა აქვს.
3ერთი ქცევა, AAA, დასახელებული ადამიანურ ენაზე. ტესტი, რომელსაც ხუთ წამში წაიკითხავთ, გადარჩება.
4დატესტეთ რა და არა როგორ. დაამტკიცეთ დაკვირვებადი ქცევა; რეფაქტორინგი მწვანედ დარჩეს. მოკებს იშვიათად მიმართეთ.
5წითელი მწვანემდე. სრული TDD იქნება თუ უბრალოდ ბაგების გასწორება, ჯერ ნახეთ ტესტის ჩავარდნა — თორემ არ იცით, საერთოდ ტესტავს თუ არა რამეს.

გააგრძელეთ

  • Test-Driven Development by Example — Kent Beck
  • Growing Object-Oriented Software, Guided by Tests — Freeman & Pryce
  • xUnit Test Patterns — Gerard Meszaros (დუბლიორების ლექსიკონი)
  • "Test Desiderata" — Kent Beck-ის კარგი ტესტის 12 თვისება

ერთი წინადადება დასამახსოვრებლად

"ტესტეთ მანამ, სანამ შიში მოწყენილობად არ იქცევა."

— Kent Beck

ცოდნის შემოწმება

დაგამახსოვრდათ?

ხუთი სწრაფი კითხვა პირამიდაზე, AAA-ზე, TDD-ზე, ტესტ-დუბლიორებსა და დაფარვაზე — მყისიერი უკუკავშირი, შესვლის გარეშე.

შეაფასეთ ეს დასტა
იყავით პირველი

ნავიგაცია ← → ღილაკებით ან სქროლით · ნაწილი 2: გაღრმავებული ტესტირება → · უკან ბიბლიოთეკაში