Tests
წარმოიდგინეთ, რომ ხართ ფრონტენდ დეველოპერი კომპანიაში, სადაც სხვა დეველოპერებთან ერთად აწყობთ ვებ-აპლიკაციას. აპლიკაცია საკმაოდ დიდია და შედგება ბევრი სხვადასხვა მოდულისგან. თქვენ დაგევალათ, რომ ერთ-ერთ მოდულში შეგესწორებინათ რაღაც ხარვეზი. რამდენიმე საათის შემდეგ თქვენ ეს ხარვეზი იპოვეთ, გამოსაწორეთ და აპლიკაციაში შეამოწმეთ ეს მოდული სწორად მუშაობდა თუ არა. შესწორებული კოდი ფროდაქშენში დაიმერჯა და რამდენიმე დღის მერე აღმოჩნდა რომ თქვენმა შესწორებულმა კოდმა სხვა მოდულში არსებული ფუნქციონალი გააფუჭა, რომელიც თქვენ არ შეგიმოწმებიათ.
ვინ არის ამ შემთხვევაში დამნაშავე? თქვენ, როგორც დეველიპერი, რომელმაც ყოველი პატარა ცვლილების გამო მთლიანი აპლიკაციის ფუნქციონალი არ შეამოწმა მთელი თავისი პატარა დეტალებით, თუ თქვენი მთლიანი გუნდი, რომელიც ავტომატიზირებულ ტესტებს არ იყენებს?
ავტომატიზირებული ტესტები არის პროგრამა, რომელიც ამოწმებს სხვა პროგრამებს. ჩვენ შეგვიძლია გავწეროთ აპლიკაციის რა ფუნქციონალი უნდა შემოწმდეს ყოველ ჯერზე, როცა ახალ ცვლილებებს შევიტანთ, იმის მაგივრად რომ ეს ჩვენით ვაკეთოთ.
არსებობს ტესტების ორი ძირითადი ტიპი: unit tests და end-to-end (e2e) tests. unit ტესტები ამოწმებენ კოდის ბლოკების სწორ ფუნქციონირებას, ხოლო e2e ტესტები მოხმარებლის პერსპექტივიდან აპლიკაციის გამართულობას, რომელიც სრულიად განცალკევებულია აპლიკაციის კოდისგან. ამ თავში გავეცნობით unit ტესტებს ანგულარში.
Jasmine & Karma
ანგულარი იყენებს Jasmine ბიბლიოთეკას იუნით ტესტებისთვის. ეს ბიბლიოთეკა გვთავაზობს ფუნქციების რეპერტუარს, რომლითაც ტესტების დაწერა შეგვიძლია. ანგულარი ასევე იყენებს Karma-ს, რაც Jasmine-ზე დაშენებული პროგრამაა, რომელიც ტესტების შედეგს ბრაუზერში გვიჩვენებს.
Component Unit Tests
unit ტესტების ჩატარება შესაძლებელია კომპონენტებსა და სერვისებზე. კომპონენტების ტესტები ამოწმებს, ერთი მხრივ, კომპონენტის კლასში ლოგიკას, ხოლო მეორე მხრივ, კომპონენტის თემფლეითში გარკვეულ პატერნებს.
კომპონენტების დასატესტად უნდა შევქმნათ იმავე კომპონენტის სახელის მქონდე ფაილი
+ spec.ts
. ასეთი ფაილები CLI-ით შექმნილ კომპონენტებს ავტომატურად მოყვება.
spec
იმიტომ, რომ ტესტის ფაილი ასევე ერთგვარი სპეციფიკაციის ფაილია. ანუ
ასეთ ფაილებში აღვწერთ როგორ უნდა მუშაობდეს კომპონენტი.
შევხედოთ ანგულარის CLI-ით შექმნილ აპლიკაციაში წინასწარ გამზადებულ app.component.spec.ts
ფაილს.
import { TestBed } from "@angular/core/testing";
import { AppComponent } from "./app.component";
describe("AppComponent", () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AppComponent],
}).compileComponents();
});
it("should create the app", () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'tests'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual("tests");
});
it("should render title", () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector(".content span")?.textContent).toContain(
"tests app is running!"
);
});
});
აქ გვაქვს ერთი დიდი describe
ფუნქცია. ეს ფუნქცია თავს უყრის ერთი კონკრეტული
კოდის მონაკვეთისთვის განკუთვნილ ტესტებს, ამ შემთხვევაში AppComponent
-ისთვის.
პირველ არგუმენტად ამ ფუნქციას ვაწვდით სტრინგს, რასაც შეიძლება ჰქონდეს ნებისმიერი
მნიშვნელობა. როცა Karma-ს გავხსნით, ამ describe
-ში არსებული ტესტების ბლოკი
ერთად იქნება შეკრული AppComponent
სახელის ქვეშ. describe
-ის ქოლბექში ვწერთ
ამ ცალკეულ ტესტებს it
ფუნქციებით.
it
ფუნქციებში აღვწერთ კომპონენტის შესახებ კონკრეტულ მოლოდინებს, ანუ რას
უნდა აკეთებდეს კომპონენტი. ეს აღწერა ეძლევა მას პირველ არგუმენტად, ხოლო ქოლბექში
იწერება კოდი, რომელიც ამ მოლოდინს ამოწმებს.
beforeEach
არის ფუნქცია, რომელიც ყოველი ჩვენს მიწოდებულ ქოლბექს გააქტიურებს ყოველი
it
ფუნქციისთვის. აქ საჭიროა რომ ანგულარის TestBed
-ს დახმარებით წინასწარ
დავაქომფაილოთ კომპონენტი, რათა მასზე წვდომა გვქონდეს ტესტირების დროს.
როგორც ხედავთ აქ წინასწარ გვაქვს 3 სპეციფიკაცია. ყოველ სპეციფიკაციაში TestBed
-ის
დახმარებით ვიღებთ სასურველი კომპონენტის ინსტაციას და Jasmine-ის ფუნქციებს ვიყენებთ
მის შესამოწმებლად.
expect
ფუნქციას ვაწვდით იმ მონაცემს, რომლის რაღაც მნიშვნელობა თუ თვისება გინვდა
რომ შევამოწმოთ და შემდეგ გვიბრუნდება JasmineMatchers
-ის ინსტანცია, რომელზეც
შესამოწმებელი მეთოდების დაძახება შეგვიძლია. isTruethy
გულისხმობს არის თუ არა
მნიშვნელობა ჭეშმარიტისებრი (ანუ ის არსებობს და არ არის null, undefined და ა.შ).
მეორე ბლოკში ხდება კომპონენტის თვისების შემოწმება, მოლოდინია, რომ title
იყოს test
.
ბოლო ბლოკში მოწმდება კომპონენტის თემფლეითი, სადაც DOM ელემენტს ვიღებთ
და ვამოწმებთ შეიცავს თუ არა მოსალოდნელ სათაურს. ვინაიდან სათაური კომპონენტის
თვისებიდან რენდერდება, ჯერ კომპონენტის fixture-ზე უნდა detectChanges
მეთოდს
დავუძახოთ რათა კომპონენტის თვისება თემფლეითში აისახოს (ამას აპლიკაციაში ანგულარი
ავტომატურად აკეთებს, მაგრამ ტესტში ეს სპეციალურად უნდა გამოვიწვიოთ).
ტესების გაშვება შესაძლებელია ბრძანებით:
npm run test
ეს გაუშვებს Jasmine-ს და გაგვიხსნის ბრაუზერით karma-ს, სადაც ვნახვთ, რომ ყველა ტესტი
წარმატებულია. თუ კომპონენტის კლასში title
-ს შეცვლით, ერთ-ერთი ტესტი ახლა
წარუმატებელი იქნება.
დავწეროთ ჩვენი ტესტიც. ვთქვათ კომპონენტის კლასში გვინდა შემოვიტანოთ მეთოდი changeTitle
,
რომელიც სათაურს შეცვლის. მაშინ ჯერ დავწეროთ ჩვენი მოლოდინი:
it("should change title with new value", () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
app.changeTitle();
expect(app.title).toEqual("changed");
});
ავიღოთ კომპონენტის fixture და შევქმნათ ამ კომპონენტის ინსტანცია. კომპონენტზე
დავუძახოთ changeTitle
-ს და შემდეგ შევამოწმოთ, რომ ამ კლასის სათაური არის
რაღაც ახალი მნიშვნელობა, მაგალითად changed
.
ახლა ტესტი ჩავარდება, რადგან ეს მეთოდი არც კი არსებობს კომპონენტში, ამიტომ ის დავამატოთ:
import { Component } from "@angular/core";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent {
title = "tests";
changeTitle() {
this.title = "changed";
}
}
და ასე ახლა ტესტი წარმატებით ჩაივლის.
შეჯამება
ეს არის იუნით ტესტების ძირითადი იდეა: ის ჩვენ მაგივრად ამოწმებს კოდს, ჩვენ უბრალოდ ფოკუსს ვაკეთებთ აპლიკაციის სტრუქტურასა და სპეციფიკაციებზე. ტესტები ძალიან დიდი სფეროა და ჩვენ მხოლოდ ზედაპირულად გავეცანით მის პრაქტიკას. მის შესახებ მეტის გასაგებად შეგიძლიათ გაეცნოთ შემდეგ რესურსებს: