간편한 API 통합 테스트

마이크로 서비스 분야에서 API를 위한 통합 테스트를 작성하는 것은 여러 구성 요소의 여러 API와 관련되기 때문에 도전이다.
본고에서 우리는 API 통합 테스트를 작성하는 두 가지 주요 도전을 중점적으로 토론할 것이다.그것은 또한 어떻게 현대적인 테스트 도구와 기술을 사용하여 이런 문제들을 극복할 수 있는지도 토론했다.PactumJS를 사용하여 자동화 API 통합 테스트 용례를 작성합니다.

pactumjs / 두꺼운 가죽


피라미드의 모든 레벨을 테스트하는 REST API 테스트 도구



PactumJS








피라미드의 모든 레벨을 테스트하는 REST API 테스트 도구



PactumJS는 e2e, 통합, 계약 및 구성 요소(또는 서비스 수준) 테스트를 자동화하는 REST API 테스트 도구입니다.

  • ⚡ Swift

  • 🎈 가벼운

  • 🚀 단순하고 강력한

  • 🛠️ 아날로그 서버

  • 💎 세련된 데이터 관리

  • 🔧 확장 및 맞춤형

  • 📚 선명하고 포괄적인 테스트 스타일

  • 🔗 API
  • 용 구성 요소, 계약 및 E2E 테스트

    문서


    이 자술은 이 도서관의 기본적인 소개를 제공하였다.전체 문서를 보려면 https://pactumjs.github.io으로 전화하십시오.
  • API Testing
  • Integration Testing
  • Component Testing
  • Contract Testing
  • E2E Testing
  • Mock Server
  • 도움이 필요하세요?


    Github Discussions을 사용하여 피드백을 받고 아이디어를 토론하며 질문에 답했습니다.

    장치

    # install pactum as a dev dependency
    npm install --save-dev pactum
    # install a test runner to run pactum tests
    # mocha / jest / cucumber
    npm install --save-dev mocha

    사용법

    pactum can be used for all levels…

    도전하다

    These are the two things of many that I personally felt challenging while writing API Integration Tests.

    1. Passing data across tests.
    2. Retry on failed expectations.

    예.

    It's always better to have an example to understand the core concepts of a topic under discussion.

    Let's take a simple example of an e-commerce application with the following API endpoints for processing an order.

    • POST /api/orders (for placing an order)
    • POST /api/payments (for making a payment)
    • GET /api/payments/{payment_id} (for fetching the status of payment)

    작업흐름

    To make things clear, the requests and responses shown below are overly simplified.

    1. 주문서 내리기

    A user comes in and makes a POST request to /api/orders with the following payload to place an order.

    Request Payload
    {
      "product": "PlayStation 5"
    }
    

    At the time of writing this article, it's highly impossible to buy the above product. At-least in some places. 🙂


    현재 서버는 주문 id을 포함하는 다음 응답 본문으로 응답합니다.

    응수
    {
      "id": "1f4c99e9-12df-45d4-b455-98418f4e3b1e"
    }
    
    주문서 id은 API 서버에서 동적으로 생성됩니다.우리는 주문서를 완성하기 위해 그것을 잡고 다른 단점, 예를 들어 지불에 전달해야 한다.
    모든 테스트 라이브러리를 사용하면 응답을 변수에 저장하고 나중에 사용할 수 있습니다.그것은 효과가 있지만 효율이 높지 않다.대규모 응용 프로그램을 위한 통합 테스트를 작성할 때, 테스트와 API 호출 사이에 대량의 데이터를 전달하도록 하기 때문이다.성명 중간 변수는 코드의 가독성을 손상시킬 수 있다.
    이 도전을 극복하기 위해 PactumJS는 Data Store의 개념을 제공하여 테스트 사이의 API 호출 간에 데이터를 전달하는 데 사용한다.
    테스트부터 봅시다.
    await pactum.spec()
        .post('/api/orders')
        .withJson({
          "product": "PlayStation 5"
        })
        .expectStatus(200)
        .stores('OrderID', 'id');
    
    상기 테스트는 주어진 /api/orders의 유효 하중을 사용하여 json에 POST 요청을 보내고 응답을 받으면 200으로 예상되며 id의 값을 OrderID이라는 특수 변수에 저장한다. 이 변수는 PactumJS의 내부 변수이다.

    2. 지불


    다음 단계는 지불입니다.현재 사용자는 다음 유효 부하를 사용하여 /api/payments에 POST 요청을 보냅니다.

    요청 페이로드
    {
      "order_id": "1f4c99e9-12df-45d4-b455-98418f4e3b1e",
      "card_info": {
        "number": "1111-1111-1111-1111",
        "expiry": "11/11",
        "cvv": "111"
      }
    }
    
    현재 API는 id을 포함하여 다음과 같은 응답 주체로 응답합니다.

    응수
    {
      "id": "a32fce50-d4e8-4d95-b16f-57fd13fbb7df"
    }
    
    이제 테스트 용례를 토론해 봅시다.
    보시다시피 이전 요청에서 온 order id은 요청 부하에 포함되어 있습니다.
    특수 내부 변수의 값을 얻기 위해PactumJS는 특수한 모드-$S{<variable-name>}을 사용하여 그것을 방문합니다.
    테스트 한번 봅시다.
    await pactum.spec()
        .post('/api/payments')
        .withJson({
          "order_id": "$S{OrderID}",
          "card_info": {
            "number": "1111-1111-1111-1111",
            "expiry": "11/11",
            "cvv": "111"
          }
        })
        .expectStatus(200)
        .stores('PaymentID', 'id');
    
    요청에 앞서 팩텀JS는 내부에서 $S{OrderID}1f4c99e9-12df-45d4-b455-98418f4e3b1e을 교체한다.
    위의 테스트 용례에서 우리는stores 방법을 사용하여 지불 id을 특수 변수 PaymentId에 저장한다.결제 id을 사용하여 결제 상태를 추적할 수 있습니다.이것은 우리를 통합 테스트의 마지막 단계로 이끌었다.

    3단계 - 결제가 완료될 때까지 기다립니다.


    지불 상태를 얻으려면 사용자는 /api/payments/{payment_id} 노드에 get 요청을 보냅니다.
    API는 다음 응답체를 사용하여 응답합니다.

    응수
    {
      "status": "in-progress"
    }
    
    보시다시피 상태는 여전히 in-progress입니다.우리는 몇 초를 기다려야만 지불을 완성할 수 있다.
    테스트에서 억지로 기다리는 것을 포함하는 것은 나쁜 방법이다.PactumJS는 실패의 예상을 재시도할 수 있는 retry mechanism이라는 개념을 덧붙였다.이것은 selenium의 fluent wait와 유사합니다.
    테스트 용례를 봅시다.
    await pactum.spec()
        .get('/api/payments/{id}')
        .withPathParams('id', '$S{PaymentID}')
        .expectStatus(200)
        .expectJson({
          "status": "completed"
        })
        .retry();
    
    기본적으로 재시도는 3회이며 재시도 간격은 1000ms회입니다.

    전체 테스트


    이제 PactumJSmocha을 사용한 전체 테스트를 살펴보겠습니다.
    const pactum = require('pactum');
    
    it('order PS5 and make payment', async () => {
      await pactum.spec()
        .post('/api/orders')
        .withJson({
          "product": "PlayStation 5"
        })
        .expectStatus(200)
        .stores('OrderID', 'id');
    
      await pactum.spec()
        .post('/api/payments')
        .withJson({
          "order_id": "$S{OrderID}",
          "card_info": {
            "number": "1111-1111-1111-1111",
            "expiry": "11/11",
            "cvv": "111"
          }
        })
        .expectStatus(200)
        .stores('PaymentID', 'id');
    
      await pactum.spec()
        .get('/api/payments/{id}')
        .withPathParams('id', '$S{PaymentID}')
        .expectStatus(200)
        .expectJson({
          "status": "completed"
        })
        .retry();
    
    });
    

    결론


    읽을 수 있고 유지 보수가 가능한 테스트를 작성하는 것은 API 테스트를 효율적이고 유쾌하게 만드는 데 매우 중요합니다.
    PactumJS은 도전적인 부분을 추상화하여 간단하고 재미있는 방식으로 테스트를 작성하여 API 통합 테스트를 매우 간단하게 만들었다.

    좋은 웹페이지 즐겨찾기