Sobes.tech
Middle+

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

sobes.tech AI

პასუხი AI-სგან

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

ძირითადი პრინციპები:

  • მომხმარებელი-კონტრაქტი: ტესტები ეფუძნება მომხმარებლის მოლოდინებს. მომხმარებელი განსაზღვრავს, რა მონაცემები და ფორმატები სჭირდება.
  • ორმხრივი ტესტირება: შემოწმება, მუშაობს თუ არა მომხმარებლის მხარე (შესაძლებელია თუ არა მას მუშაობა მიმდინარე კონტრაქტთან), ასევე მიმწოდებლის მხარე (შესაბამისია თუ არა მისი რეალიზაცია მომხმარებლის მოლოდინებს).
  • სწრაფობა: ტესტები სწრაფად სრულდება, ხშირად CI/CD-ის ჩარჩოებში, რადგან არ საჭიროებს ყველა დამოკიდებული სერვისის განთავსებას.

პროცესი ჩვეულებრივ მოიცავს:

  1. მომხმარებელი ქმნის ტესტებს, რომლებიც აღწერენ მის მოლოდინებს მიმწოდებლის API-ზე. ეს ტესტები ქმნის "კონტრაქტს".
  2. კონტრაქტი გამოქვეყნდება (მაგალითად, ცენტრალიზებულ საცავში).
  3. მიმწოდებელი იყენებს გამოქვეყნებულ კონტრაქტს თავისი API-ის რეალიზაციის ვალიდაციისთვის. ის იწყებს ტესტებს (სხვადასხვა მხარიდან), რომლებიც ამოწმებენ, შეესაბამება თუ არა მისი API კონტრაქტს.
  4. თუ მომხმარებლის მოლოდინები და მიმწოდებლის რეალიზაცია არ ემთხვევა, ტესტი ჩავარდება და კონტრაქტის დარღვევა გამოიწვევს.

საშუალებები:

  • Pact (ყველაზე პოპულარული)
  • Spring Cloud Contract
  • Swagger/OpenAPI და ვალიდაციის ინსტრუმენტები

უპირატესობები:

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

მოხერხებულობები:

  • არ აყვანილობს სრულყოფილ ინტეგრაციის ტესტებს (მხოლოდ API დონეზე ურთიერთქმედებას).
  • საჭიროებს კონტრაქტების ვერსიების კონტროლს.
  • შეიძლება იყოს რთული ძალიან რთული კონტრაქტების მქონე სერვისებისთვის.

მაგალითი Pact-ის გამოყენებით:

  1. მომხმარებელი (მაგალითად, Order Service) იყენებს Pact ბიბლიოთეკას, რათა შექმნას მომხმარებლის მხარის ტესტები:
    // მომხმარებლის ტესტის მაგალითი Pact JVM-ით
    @ExtendWith(PactConsumerTestExt.class)
    @PactTestFor(providerName = "ProductService", port = "8080")
    public class ProductServiceContractTest {
    
        @Pact(consumer = "OrderService")
        public RequestResponsePact createPact(PactDslWithRequest r) {
            return r.given("a product with id 1 exists")
                    .uponReceiving("a request for product by id")
                    .path("/products/1")
                    .method("GET")
                    .willRespondWith()
                    .status(200)
                    .headers(Map.of("Content-Type", "application/json"))
                    .body(new PactDslJsonBody()
                            .stringValue("id", "1")
                            .stringValue("name", "Laptop")
                            .numberType("price", 1200.00))
                    .toPact();
        }
    
        @Test
        void testGetProductById(MockServer mockServer) throws IOException {
            // API-ის გამოძახების ლოგიკა mockServer-ის საშუალებით
            // შემოწმება, რომ მომხმარებელი სწორად ახდენს მოკ-პასუხის დამუშავებას
            HttpResponse response = Request.Get(mockServer.getUrl() + "/products/1").execute().returnResponse();
            assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
        }
    }
    
  2. მომხმარებლის ტესტების შესრულებისას გენერირდება კონტრაქტის ფაილი (.json).
  3. ეს ფაილი გამოქვეყნდება Pact Broker-ზე ან სხვა ცენტრალიზებულ საცავში.
  4. მიმწოდებელი (Product Service) იყენებს Pact ბიბლიოთეკას (მაგ., Pact Provider Verifier) თავისი API-ის რეალიზაციის ვალიდაციისთვის კონტრაქტის საფუძველზე, რომელიც მიღებულია Pact Broker-დან:
    // მიმწოდებლის ტესტის მაგალითი Pact Provider Verifier-ით
    @Provider("ProductService")
    @PactFolder("relative/path/to/pacts") // ან Pact Broker
    public class ProductServiceVerificationTest {
    
        @TestTemplate
        @ExtendWith(PactVerificationInvocationContextProvider.class)
        public void verifyPact(PactVerificationContext context) {
            context.verifyInteraction();
        }
    
        @State("a product with id 1 exists")
        public void productWithId1Exists() {
            // მონაცემების მომზადების ლოგიკა სერვისისთვის
        }
    
        // სერვისის URL-ის დამატება, სადაც ტესტირებადი სერვისი მუშაობს
        @BeforeEach
        void beforeEach(PactVerificationContext context) {
            context.setTarget(new HttpTestTarget("localhost", 8080));
        }
    }
    
  5. მიმწოდებლის მხარეზე ვალიდატორი რეალურ API-ს იძახის კონტრაქტის სპეციფიკაციის შესაბამისად და პასუხს ადარებს კონტრაქტში განსაზღვრულს.

კონტრაქტული ტესტირება მნიშვნელოვანი პრაქტიკაა სერვისებზე დაფუძნებული სისტემების სანდოობისა და შენარჩუნების უზრუნველსაყოფად.