რა არის Cucumber BDD – Gherkin და როგორ გამოვიყენოთ.

Gherkin ენა

**Gherkin** არის plain-text ენა, მარტივი სტრუქტურით, რომელსაც დეველოპერები/ავტომატიზაციის ინჟინრები იყენებენ Cucumber პლატფორმაზე ტესტების დასაწერად. (ზოგჯერ შეიძლება მოხსენიებული შეგხვდეთ როგორც პროგრამირების ენად, რაც არ არის სწორი, თუმცა ხდება ხოლმე 🙂 )

ეს ენა შექმნილია ისე, რომ პროგრამული სისტემის გამოყენების შემთხვევები (მარტივად რომ ვთქვათ, ტესტები) ახსნას ისეთი ფორმატით,
რომელიც იძლევა საშუალებას გუნდში ჩართული ადამიანების მაქსიმალურად დიდმა რაოდენობა მარტივად გაიგოს, რადგან გამოიყენება მარტივი ინგლისურ ენა.
ამის გამო, Gherkin-ის სინტაქსი ხელს უწყობს ქცევაზე ორიენტირებულ განვითარებას (Behavior-Driven Development – BDD), რადგან ის დეველოპერებს, მენეჯერებს, ბიზნეს ანალიტიკოსებს და სხვა დაინტერესებულ მხარეებს საშუალებას აძლევს გაიგონ პროექტის მოთხოვნები და მისი ციკლი.
Gherkin ენა ამარტივებს და ორგანიზებულად ახდენს კოდის დოკუმენტირებას, რომელიც იქმნება. გარდა ამისა, Gherkin გვთავაზობს ისეტ ტექ ფიჩერებსაც რომელიც ტესტ ავტომატიზაციისთვის თავსებადია არა მხოლოდ რომელიმე კონკრეტულად პროგრამულ ენასთან.
მისი ძირითადი ელემენტები მოიცავს:

  • Feature: ფუნქციონალის აღწერა.
  • Scenario: კონკრეტული შემთხვევის ტესტის აღწერა.
  • Given/When/Then: წინაპირობა, ქმედება და შედეგის მოლოდინი.

რა არის Cucumber BDD?

Cucumber არის Behavior-Driven Development (BDD) ტესტირების ფრეიმვორქი, რომელიც საშუალებას იძლევა ტესტები დავწეროთ მარტივი “ადამიანური” ენით, Gherkin-ის დახმარებით.
“ადამიანურ” ენაში კი იგულისხმება ის რომ არა ტექნიკურმა პიროვნებებმაც მარტივად გაარჩიონ ტესტ ქეისები და მათი ლოგიკა, ისე რომ კოდში ძრომიალი არ დაჭირდეთ.

რატომ შეიქმნა Cucumber?

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

Cucumber-ის უპირატესობები

  • მარტივი და გასაგები ენა, რომელიც ბიზნესის მომხმარებლებისთვისაც ადვილად აღქმადია.
  • BDD პროცესის სრული მხარდაჭერა.
  • ტექნიკური და ბიზნეს გუნდის ურთიერთობის გაღრმავება.
  • რეგრესიული ტესტების ავტომატიზაციის მხარდაჭერა.
  • მრავალენოვანი მხარდაჭერა.

Cucumber-ის ნაკლოვანებები

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

როგორ დავნერგოთ Cucumber Java Maven პროექტში?

Cucumber-ის დანერგვა Java Maven პროექტში სადაც ასევე ვიყენებთ TestNG-ით მოითხოვს შესაბამის დამოკიდებულებების (dependencies) დამატებას და კონფიგურაციას.

ეტაპები:


  • პროექტში pom.xml-ში დაამატეთ საჭირო დამოკიდებულებები (dependencies):
    პირველ რიგში საჭიროა cucumber-java, cucumber-testNG და Gherkin – (ინფო) ეს უკანასკნელი აღარ გამოიყენება cucumber-java -ს უახლოეს ვერსიებთან

    <dependencies>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>7.20.1</version>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-testng</artifactId>
            <version>7.20.1</version>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>7.7.1</version>
            
        </dependency>
        
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>gherkin</artifactId>
            <version>30.0.4</version>
       
        </dependency>
    </dependencies>
    

  • mvn clean install ბრძანების შესრულება დამოკიდებულებების ჩამოსატვირთად თუ ავტომატურად არ მოხდა მათი ჩამოტვირთვა

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

პროექტის ფოლდერების სტრუქტურა

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

src/
├── test/                              # მხოლოდ BDD და Cucumber ტესტინგისთვის გამოიყენება
    ├── java/                          # Java ფაილების ფოლდერი
    │   └── com/
    │       └── example/
    │           ├── runner/            # Runner კლასები
    │           │   └── TestRunner.java  # პასუხისმგებელია Feature ფაილების და Step Definition-ების დაკავშირებაზე
    │           ├── stepdefinitions/   # Step Definition კლასები
    │           │   └── LoginSteps.java  # Step-ების იმპლემენტაცია (Given/When/Then)
    │           └── hooks/             # Hooks (Before/After მეთოდები)
    │               └── TestHooks.java  # ტესტის დაწყების ან დასრულების სპეციალური ლოგიკა
    └── resources/                     # Feature ფაილების და სხვა რესურსების ფოლდერი
        └── features/                  # Gherkin Feature ფაილები
            └── login.feature           # ტესტის სცენარების აღწერა "ადამიანურ" ენაზე :)

Cucumber-ის იმპლემენტაცია TestNG-ით

Cucumber-ის იმპლემენტაცია მოიცავს Feature ფაილების, Step Definition-ების და TestNG Runner კლასის კონფიგურაციას.

საფეხურები:


  • Feature ფაილების შექმნა:
    src/test/resources/features ფოლდერში Gherkin სცენარების დაწერა .feature ფაილებში.

    Feature: Login functionality
      Scenario: Successful login
        Given the user is on the login page
        When the user enters valid credentials
        Then the user is redirected to the dashboard
    

  • Step Definition კლასი:
    src/test/java/steps ფოლდერში შექმენით Java კლასი და დაამატეთ მეთოდები @Given, @When, @Then ანოტაციებით.

    package steps;
    
    import io.cucumber.java.en.*;
    
    public class LoginSteps {
        @Given("the user is on the login page")
        public void userOnLoginPage() {
            System.out.println("User navigated to login page.");
        }
    
        @When("the user enters valid credentials")
        public void userEntersCredentials() {
            System.out.println("User entered valid credentials.");
        }
    
        @Then("the user is redirected to the dashboard")
        public void userRedirectedToDashboard() {
            System.out.println("User redirected to the dashboard.");
        }
    }
    

  • TestNG Runner კლასი:
    src/test/java/runners ფოლდერში შექმენით კლასი, რომელიც AbstractTestNGCucumberTests-ს განეკუთვნება.

    package runners;
    
    import io.cucumber.testng.AbstractTestNGCucumberTests;
    import io.cucumber.testng.CucumberOptions;
    
    @CucumberOptions(
        features = "src/test/resources/features",
        glue = "steps",
        plugin = {"pretty", "html:target/cucumber-reports.html"}
    )
    public class TestNGRunner extends AbstractTestNGCucumberTests {
        // ცარიელი Runner კლასი TestNG-ისთვის
    }
    

  • TestNG-ის XML ფაილი:
    testng.xml ფაილი Runner კლასის გასაშვებად.

    <suite name="Cucumber TestNG Suite">
        <test name="Cucumber Scenarios">
            <classes>
                <class name="runners.TestNGRunner"/>
            </classes>
        </test>
    </suite>
    

Feature ფაილის სრული განხილვა

Feature ფაილი არის Gherkin ენის ფორმატში დაწერილი ფაილი, რომელიც ტესტირების სცენარების ფორმალიზებულ აღწერას უზრუნველყოფს.
მისი ძირითადი ელემენტებია:

  • Feature: ფუნქციონალის აღწერა.
  • Scenario: კონკრეტული ტესტის აღწერა.
  • Given/When/Then: წინაპირობები, ქმედებები და შედეგები.
  • Scenario Outline: მონაცემთა მართვადი ტესტირება (data-driven testing).
  • Examples: მონაცემთა ნაკრები, რომელიც გამოიყენება Scenario Outline-ში.

Feature ფაილის სტრუქტურა

1. Feature

Feature: Login functionality
  This feature tests the login process for different user roles.

2. Scenario

Scenario აღწერს კონკრეტულ ტესტს.

Scenario: Successful login
  Given the user is on the login page
  When the user enters valid credentials
  Then the user is redirected to the dashboard

3. Scenario Outline

Scenario Outline გამოიყენება მონაცემთა ერთობლიობის გამოყენებით ტესტირებისათვის.

Scenario Outline: Login with multiple user roles
  Given the user is on the login page
  When the user enters "<username>" and "<password>"
  Then the user should see the "<dashboard>" page

  Examples:
    | username   | password | dashboard  |
    | admin      | admin123 | Admin Home |
    | manager    | manager1 | Manager Page |
    | guest      | guest123 | Guest Home |

4. Steps: Given, When, Then

Given the user is on the login page
When the user enters valid credentials
Then the user is redirected to the dashboard

5. Background

Background გამოიყენება საერთო Given საფეხურების განსაზღვრისთვის.

Feature: Shopping Cart Functionality

Background:
  Given the user is logged in
  And the user has items in the cart

Scenario: View cart details
  When the user views the cart
  Then the cart details are displayed

Scenario: Checkout items
  When the user proceeds to checkout
  Then the user is redirected to the payment page

Cucumber-ის ძირითადი Hooks

Cucumber-ში Hooks არის სპეციალური ანოტაციები, რომლებიც საშუალებას იძლევა, კოდი შესრულდეს ტესტების გარკვეულ ეტაპებზე.
ძირითადი Hooks მოიცავს:

  • @Before: სრულდება თითოეული სცენარის დაწყებამდე.
  • @After: სრულდება თითოეული სცენარის დასრულების შემდეგ.
  • @BeforeStep: სრულდება თითოეული ნაბიჯის დაწყებამდე.
  • @AfterStep: სრულდება თითოეული ნაბიჯის დასრულების შემდეგ.
  • @BeforeAll: სრულდება ტესტ სესიის დაწყებამდე (მოთხოვს static მეთოდს).
  • @AfterAll: სრულდება ტესტ სესიის დასრულების შემდეგ (მოთხოვს static მეთოდს).

როგორ შევქმნათ Hook კლასი და სად?

Hooks არის Cucumber-ის ფუნქციონალი, რომელიც საშუალებას გაძლევთ შეასრულოთ კოდი ტესტების კონკრეტულ ეტაპებზე.
Hook კლასები იქმნება Step Definition კლასების გვერდით და ინახება სპეციალურ ფოლდერში, მაგალითად, hooks.

Hooks კლასის განთავსება:

  • src/test/java/com/example/hooks/
    ეს ფოლდერი გამოიყენება Hook კლასების შესანახად.

მნიშვნელოვანი შენიშვნა:
glue პარამეტრში უნდა მიუთითოთ hooks პაკეტის მისამართი, რათა Cucumber-ს შეეძლოს Hooks-ის პოვნა და შესრულება. როდესაც სხვა რამეც გვაქვს მითითებული მაშინ ვიყენებ { და } შესაბამისად გამოვა ასეთი რამ: glue = {"ge.automation.steps", "ge.automation.hooks"},

Hook კლასის მაგალითი

1. @Before და @After

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

package ge.automation.hooks;

import io.cucumber.java.After;
import io.cucumber.java.Before;

public class TestHooks {

    @Before
    public void beforeScenario() {
        System.out.println("Executing setup before each scenario...");
        // მაგალითად: ბრაუზერის ინიციალიზაცია
    }

    @After
    public void afterScenario() {
        System.out.println("Executing cleanup after each scenario...");
        // მაგალითად: ბრაუზერის დახურვა ან რესურსების გაწმენდა
    }
}

2. @BeforeStep და @AfterStep

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

package ge.automation.hooks;

import io.cucumber.java.AfterStep;
import io.cucumber.java.BeforeStep;

public class StepHooks {

    @BeforeStep
    public void beforeStep() {
        System.out.println("Before executing each step...");
    }

    @AfterStep
    public void afterStep() {
        System.out.println("After executing each step...");
    }
}

3. @BeforeAll და @AfterAll

ეს Hooks გამოიყენება მთლიანი ტესტ სესიის დაწყებამდე ან დასრულების შემდეგ და მოითხოვს static მეთოდებს.

package ge.automation.hooks;

import io.cucumber.java.BeforeAll;
import io.cucumber.java.AfterAll;

public class GlobalHooks {

    @BeforeAll
    public static void beforeAllTests() {
        System.out.println("Executing global setup before all tests...");
        // მაგალითად: გლობალური კონფიგურაციის ინსტალაცია
    }

    @AfterAll
    public static void afterAllTests() {
        System.out.println("Executing global teardown after all tests...");
        // მაგალითად: ლოგირების სისტემის დახურვა ან საერთო რესურსების გაწმენდა
    }
}

Hook კლასის გამოყენების საუკეთესო პრაქტიკები

  • ჩასვით Hook კლასები ცალკე პაკეტში, მაგალითად, ge.automation.hooks.
  • დარწმუნდით, რომ glue პარამეტრი მოიცავს Hooks პაკეტის მისამართს.
  • გამოიყენეთ @Before და @After რესურსების მართვისთვის თითოეული სცენარისთვის.
  • @BeforeStep და @AfterStep გამოიყენეთ ნაბიჯის დეტალური ლოგირების ან მონიტორინგისთვის.
  • @BeforeAll და @AfterAll გამოიყენეთ გლობალური კონფიგურაციის ან რესურსების მართვისთვის.
  • მოერიდეთ ჰუკებში რთული ლოგიკის გამოყენებას. გამოიყენეთ ისინი საერთო პროცესებისთვის.

Hook-ის შესრულების თანმიმდევრობა

თუ ერთიდაიგივე Hook გვაქვს რამდენჯერმე შეგვიძლია განვსაზღვროთ მათი პრიორიტეტები – @Order ანოტაცია უზრუნველყოფს შესრულების თანმიმდევრობას.

package hooks;

import io.cucumber.java.Before;
import org.testng.annotations.Test;

public class OrderedHooks {

    @Before(order = 1)
    public void initializeDatabase() {
        System.out.println("Setting up database...");
        // ლოგიკა მონაცემთა ბაზის ინიციალიზაციისთვის
    }

    @Before(order = 2)
    public void initializeCache() {
        System.out.println("Setting up cache...");
        // ლოგიკა cache-ის კონფიგურაციისთვის
    }
}

Hooks გამოყენების საუკეთესო პრაქტიკები

  • გამოიყენეთ @BeforeAll/@AfterAll გლობალური რესურსების კონფიგურაციისთვის.
  • @Before და @After გამოიყენეთ ტესტ სცენარის ლოკალური რესურსების მართვისთვის.
  • @BeforeStep და @AfterStep გამოიყენეთ ნაბიჯის დეტალური ლოგირების ან API ლოგიკისათვის.
  • გამოიყენეთ @Order ჰუკების თანმიმდევრობის სწორად მართვისთვის.
  • არასდროს გადატვირთოთ ჰუკები რთული ლოგიკით; მათი გამოყენება უნდა იყოს საერთო პროცესებისთვის.

Tags გამოყენების საუკეთესო პრაქტიკები Cucumber-ში

  • დაამატეთ @Tag სცენარებს ან ფიჩერს ორგანიზების და ტესტების მარტივად შერჩევისთვის.
  • გამოიყენეთ ლოგიკური ოპერატორები (@Tag, or, and, not) Runner კლასში ტესტების დასაფილტრავად.
  • სტრუქტურა: სცენარებს და ფიჩერებს მიაწერეთ თეგები კონკრეტული დანიშნულების ან ფუნქციონალის მიხედვით, მაგალითად, @SmokeTest, @Login, @Regression.
  • მიანიჭეთ ბუნებრივი სახელები თეგებს, რაც მარტივს გახდის მათი მნიშვნელობის გაგებას.
  • გამოიყენეთ Maven-ის -Dcucumber.filter.tags პარამეტრი ტესტების შერჩევისთვის კონკრეტული თეგებით.
  • მოერიდეთ ზედმეტად ბევრი თეგის გამოყენებას ერთ სცენარზე, რათა თავიდან აიცილოთ კომპლექსურობა.

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

აქ არის მაგალითი, თუ როგორ უნდა გამოიყენოთ თეგები ფიჩერის და სცენარების დონეზე:


@UserManagement
Feature: User login functionality

  @Login @Positive
  Scenario: User logs in successfully
    Given the user is on the login page
    When the user enters valid credentials
    Then the user is redirected to the dashboard

  @Login @Negative
  Scenario: User enters invalid credentials
    Given the user is on the login page
    When the user enters invalid credentials
    Then an error message is displayed

Tags-ის ფილტრაცია Runner-ში


  • Runner კლასში: გამოიყენეთ tags პარამეტრი ტესტების გასაფილტრად.
  • ერთი თეგის შერჩევა:
    @CucumberOptions(
        features = "src/test/resources/features",
        glue = "ge.automation",
        tags = "@Login",
        plugin = {"pretty", "html:target/cucumber-reports.html"}
    )
    
  • მრავალ თეგზე ფილტრაცია (OR):
    @CucumberOptions(
        features = "src/test/resources/features",
        glue = "ge.automation",
        tags = "@Login or @SmokeTest",
        plugin = {"pretty", "html:target/cucumber-reports.html"}
    )
    
  • თეგების გამორიცხვა (NOT):
    @CucumberOptions(
        features = "src/test/resources/features",
        glue = "ge.automation",
        tags = "not @Negative",
        plugin = {"pretty", "html:target/cucumber-reports.html"}
    )
    
  • ტერმინალიდან ტესტის გაშვებისთვის თეგის მიხედვით mvn clean test -Dcucumber.filter.tags="@smoke"

API Testing Scenarios

მოცემულია API ტესტირების სხვადასხვა სცენარი, რომლებიც ამოწმებენ JSONPlaceholder API-ის ფუნქციონალს,
მათ შორის GET და POST მოთხოვნების ვალიდაციას.

Feature: JSONPlaceholder API Testing

  Background:
    Given the base URI is "https://jsonplaceholder.typicode.com"

  Scenario: Validate retrieving all posts
    When I send a GET request to "/posts"
    Then the response should contain exactly 100 posts

  Scenario: Validate the status code of a GET request
    When I send a GET request to "/posts/1"
    Then the response status code should be 200

  Scenario Outline: Validate the status code of various endpoints
    When I send a GET request to ""
    Then the response status code should be 

    Examples:
      | endpoint     | statusCode |
      | /posts/1     | 200        |
      | /posts/9999  | 404        |
      | /invalid-url | 404        |
      | /comments    | 200        |
      | /nonexistent | 404        |

  Scenario: Validate post titles are not empty
    When I send a GET request to "/posts"
    Then each post title should not be empty

  Scenario Outline: Validate posts contain specific user IDs
    When I send a GET request to "/posts"
    Then the response should contain posts with "userId" equal to 

    Examples:
      | userId |
      | 1      |
      | 2      |
      | 3      |

  Scenario Outline: Validate retrieving a single post contains specific fields
    When I send a GET request to "/posts/"
    Then the response should contain the field ""

    Examples:
      | postId | field  |
      | 1      | userId |
      | 2      | id     |
      | 3      | title  |
      | 4      | body   |

  Scenario: Validate posts with multiple query parameters
    Given I send a GET request to "/posts" with query parameters:
      | userId | 1 |
      | id     | 1 |
    Then the response should contain exactly 1 posts

  Scenario Outline: Validate a specific post by ID contains expected title
    Given I send a GET request to "/posts/{postId}" with path parameter:
      | postId |  |
    Then the response should contain the title ""

    Examples:
      | postId | expectedTitle                                                              |
      | 1      | sunt aut facere repellat provident occaecati excepturi optio reprehenderit |
      | 2      | qui est esse                                                               |
      | 3      | ea molestias quasi exercitationem repellat qui ipsa sit aut                |
      | 4      | eum et est occaecati                                                       |
      | 5      | nesciunt quas odio                                                         |
      | 6      | dolorem eum magni eos aperiam quia                                         |

Step-ები

ქვემოთ მოცემულია სტეპები, რომლებიც აღწერენ API ტესტირების სხვადასხვა მოქმედებას და შესაბამისია ზემოთ აღწერილი სცენარების.

// იმპორტირებული ბიბლიოთეკები: გამოიყენება Cucumber-ის ანოტაციების, RestAssured-ის და TestNG-ის Assert მეთოდებისათვის.

import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.testng.Assert;

import java.util.List;
import java.util.Map;

// კლასის აღწერა: ეს კლასი შეიცავს RestAssured-ის დახმარებით API ტესტირებისათვის საჭირო ნაბიჯებს.
public class loginSteps {

    // ცვლადი, რომელიც ინახავს API-ს პასუხს.
    private Response response;

    // @Given ანოტაცია: აღნიშნავს საწყის მდგომარეობას, სადაც ჩვენ ვადგენთ API-ს ბაზურ URI-ს.
    @Given("the base URI is {string}")
    public void theBaseURIIs(String baseUri) {
        // RestAssured-ის baseURI-ს ინიცირება.
        RestAssured.baseURI = baseUri;
    }

    // @When ანოტაცია: აღნიშნავს მოქმედებას, სადაც ვაგზავნით GET მოთხოვნას კონკრეტულ endpoint-ზე.
    @When("I send a GET request to {string}")
    public void iSendAGETRequestTo(String endpoint) {
        // GET მოთხოვნა endpoint-ზე და პასუხის შენახვა.
        response = RestAssured.given().log().all().get(endpoint);
    }

    // @Then ანოტაცია: აღნიშნავს შემოწმებას, სადაც ვამოწმებთ, რომ პასუხის სტატუს კოდი სწორია.
    @Then("the response status code should be {int}")
    public void theResponseStatusCodeShouldBe(int expectedStatusCode) {
        // მიიღე ფაქტობრივი სტატუს კოდი
        int actualStatusCode = response.getStatusCode();
        // შეადარე მოსალოდნელი და ფაქტობრივი სტატუს კოდები
        Assert.assertEquals(actualStatusCode, expectedStatusCode,
                "Unexpected status code. Expected: " + expectedStatusCode + ", Actual: " + actualStatusCode);
    }

    // @When ანოტაცია: აღნიშნავს მოქმედებას, სადაც ვაგზავნით GET მოთხოვნას path პარამეტრებით.
    @When("I send a GET request to {string} with path parameter:")
    public void iSendAGETRequestToWithPathParameter(String endpoint, Map<String, String> pathParams) {
        // GET მოთხოვნა path პარამეტრებით და პასუხის მიღება.
        response = RestAssured.given()
                .log().all()
                .pathParams(pathParams)
                .get(endpoint)
                .then()
                .extract()
                .response();
    }

    // @Then ანოტაცია: აღნიშნავს შემოწმებას, სადაც ვამოწმებთ, რომ პასუხში კონკრეტული რაოდენობის პოსტებია.
    @Then("the response should contain exactly {int} posts")
    public void theResponseShouldContainExactlyPosts(int expectedCount) {
        // პასუხიდან ყველა პოსტის მიღება და მათი რაოდენობის შემოწმება.
        List posts = response.jsonPath().getList("$");
        Assert.assertEquals(posts.size(), expectedCount, "Post count mismatch!");
    }

    // @Then ანოტაცია: აღნიშნავს შემოწმებას, სადაც ვამოწმებთ, რომ პასუხში მოცემულია კონკრეტული ველის მნიშვნელობა.
    @Then("the response should contain posts with {string} equal to {int}")
    public void theResponseShouldContainPostsWithFieldEqualTo(String field, int expectedValue) {
        // ველის ყველა მნიშვნელობის მიღება და შემოწმება.
        List actualValues = response.jsonPath().getList(field);
        boolean found = false;
        for (Integer actualValue : actualValues) {
            if (actualValue == expectedValue) {
                found = true;
                break;
            }
        }
        Assert.assertTrue(found, "The response does not contain any posts with " + field + " equal to " + expectedValue);
    }

    // @Then ანოტაცია: აღნიშნავს შემოწმებას, სადაც ვამოწმებთ, რომ პასუხი შეიცავს კონკრეტულ ველს.
    @Then("the response should contain the field {string}")
    public void theResponseShouldContainTheField(String field) {
        // ველის არსებობის შემოწმება.
        Assert.assertNotNull(response.jsonPath().getString(field), "Field not found: " + field);
    }

    // @Then ანოტაცია: აღნიშნავს შემოწმებას, სადაც ვამოწმებთ, რომ ყველა პოსტის სათაური ცარიელი არ არის.
    @Then("each post title should not be empty")
    public void eachPostTitleShouldNotBeEmpty() {
        // სათაურების სიის მიღება და თითოეულის შემოწმება, რომ არ იყოს ცარიელი ან null.
        List titles = response
                .jsonPath()
                .getList("title");

        for (String title : titles) {
            Assert.assertNotNull(title, "Post title is empty or null!");
            Assert.assertFalse(title.trim().isEmpty(), "Post title is empty or blank!");
        }
    }

    // @When ანოტაცია: აღნიშნავს მოქმედებას, სადაც ვაგზავნით GET მოთხოვნას query პარამეტრებით.
    @When("I send a GET request to {string} with query parameters:")
    public void iSendAGETRequestToWithQueryParameters(String endpoint, Map<String, String> queryParams) {
        // GET მოთხოვნა query პარამეტრებით.
        response = RestAssured
                .given()
                .queryParams(queryParams)
                .get(endpoint);
    }

    // @Then ანოტაცია: აღნიშნავს შემოწმებას, სადაც ვამოწმებთ, რომ პასუხი შეიცავს მოცემულ სათაურს.
    @Then("the response should contain the title {string}")
    public void theResponseShouldContainTheTitle(String expectedTitle) {
        // სათაურის მიღება პასუხიდან და მისი შედარება მოსალოდნელ მნიშვნელობასთან.
        String actualTitle = response
                .jsonPath()
                .getString("title");
        Assert.assertEquals(actualTitle, expectedTitle, "Title mismatch! Expected: " + expectedTitle + ", Found: " + actualTitle);
    }

   
}

Runner კლასი

Runner კლასი აერთიანებს Cucumber-ს TestNG-თან. მისი მეშვეობით ხდება Feature ფაილების, Step-ების და Hook-ების ლოკაციის განსაზღვრა და
კონკრეტული ტეგებით (მაგ. @SmokeTest) სცენარების გაშვება.

package ge.automation.runner;

import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;

@CucumberOptions(
        features = "src/test/resources/features", // Feature ფაილების ლოკაცია
        glue = {"ge.automation.steps", "ge.automation.hooks"}, // Step და Hook კლასების პაკეტები
        tags = "@SmokeTest", // გაშვებისთვის მითითებული ტეგი

        plugin = {"pretty", "html:target/cucumber-reports.html"} // რეპორტების გენერაციის პლაგინები
)
public class TestRunner extends AbstractTestNGCucumberTests {
    // კლასი მემკვიდრეობით იღებს AbstractTestNGCucumberTests-ს, 
    // რაც უზრუნველყოფს Cucumber-სcenarios-ის TestNG ფორმატში გაშვებას.
}

testng.xml კონფიგურაცია

TestNG სუიტის ფაილი განსაზღვრავს, თუ რომელ Runner კლასს უნდა მიაკითხოს ტესტებისთვის. მაგალითად `ge.automation.runner.TestRunner`-ს.

<suite name="Cucumber TestNG Suite">
    <test name="Cucumber Scenarios">
        <classes>
            <class name="ge.automation.runner.TestRunner"/>
        </classes>
    </test>
</suite>

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

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