REST API 테스트(BDD)를 위해 오이를 사용합니다.

소개


BDD는 비기술자와 기술자에게 매우 강력한 도구입니다.
이 문서에서는 RESTAPI를 테스트하기 위해 Cucumber를 설정하고 실행하는 방법을 보여 줍니다.

BDD는 도대체 무엇입니까?


BDD는 비헤이비어 드라이브 개발의 약자입니다.
BDD는 다음과 같은 방식으로 업무 인력과 기술 인력 간의 격차를 줄이는 소프트웨어 팀의 업무 방식입니다.
  • 문제 해결에 대한 공동 이해를 구축하기 위해 크로스 역할 협업을 장려한다
  • 피드백과 가치 흐름을 증가시키기 위해 신속하고 작은 교체
  • 시스템 비헤이비어에 따라 자동으로 검사되는 시스템 문서 생성
  • 우리는 협업 업무를 구체적이고 진실한 예시에 중점을 두고 이 점을 실현한다. 이런 예들은 우리가 시스템이 어떻게 운행되기를 원하는지 설명한다.우리는 이러한 예를 사용하여 우리가 개념에서 실현까지 지도한다.

    오이가 뭐예요?


    Cucumber는 비헤이비어 제어 개발(BDD)을 지원하는 도구입니다.Cucumber는 순수한 텍스트로 작성된 실행 가능한 규범을 읽고 소프트웨어가 이 규범에 따라 실행되는지 확인합니다.규범은 여러 예나 장면으로 구성된다.예:
    Scenario Outline: create a contact
        Given A contact <request>
        When I send POST request to /directory
        Then I get response code 201
    
    (이 장면은 오이 문법으로 작성)
    각 장면은 Cucumber가 완료해야 하는 단계 목록입니다.Cucumber는 소프트웨어가 규범에 부합되는지 확인하고 보고서를 생성합니다.✅ 성공 또는❌ 각 장면의 실패.

    오이가 뭐예요?


    오이는 순수한 텍스트 구조를 Cucumber가 이해할 수 있도록 문법 규칙이다.오이 문서는 에 저장됩니다.기능 텍스트 파일은 일반적으로 소프트웨어 옆의 원본 코드 관리에서 버전 제어를 한다.

    오이 맛있다.기능 파일이 코드에 붙어 있습니까?


    우리는 작은 오이의 특징 파일에서 각 단계의 작성 절차를 정의한다.단계 정의는 오이 단계를 프로그래밍 코드에 연결합니다.단계는 이 단계를 수행할 작업을 정의합니다.따라서 절차 정의는 규범을 실현에 단단히 연결시킨다.

    특색


    기능은 관련 장면이다.따라서 응용 프로그램의 많은 관련 내용을 테스트할 것이다.이상적인 상황에서 오이 파일의 특징은 응용 프로그램의 특징에 밀접하게 비추기 때문에 이름을 얻었다
    그런 다음 장면은 특정 방식으로 정렬되는 단계로 구성됩니다.
    주어진 – 테스트를 진행하기 전에 초기 상태를 설정하는 데 사용됩니다.
    When – 이러한 단계는 실제 테스트를 수행하는 것입니다.
    그리고 – 테스트 결과를 단언하는 데 사용되는 단계

    인스턴스


    디렉터리를 관리하기 위해 간단한 RESTAPI를 만들었습니다.연락처를 만들고, 수정하고, 읽고, 삭제할 수 있습니다.모든 기능이 설계대로 작동하도록 BDD 테스트를 작성했습니다.

    NodeJs 항목 설정


    npm init
    

    다음 의존 항목 설치


     "dependencies": {
        "axios": "^0.20.0",
      },
      "devDependencies": {
        "cucumber": "^6.0.5",
        "cucumber-html-reporter": "^5.2.0"
      }
    

    디렉토리를 만듭니다.src의 요소 파일/요소


    @directory-service
    Feature: Directory Service
      In order to manage directory
      As a developer
      I want to make sure CRUD operations through REST API works fine
    
      Scenario Outline: create a contact
        Given A contact <request>
        When I send POST request to /directory
        Then I get response code 201
    
        Examples:
          | request                                                                                          
          | {"id":99,"name":"Dwayne Klocko","email":"[email protected]","phoneNumber":"1-876-420-9890"}          |
          | {"id":7,"name":"Ian Weimann DVM","email":"[email protected]","phoneNumber":"(297) 962-1879"} |
    
      Scenario Outline: modify contact
        Given The contact with <id> exist
        When I send PATCH request with a <secondaryPhoneNumber> to /directory
        Then I get response code 200
    
        Examples:
          | id | secondaryPhoneNumber                       |
          | 99 | {"secondaryPhoneNumber": "(914) 249-3519"} |
          | 7  | {"secondaryPhoneNumber": "788.323.7782"}   |
    
      Scenario Outline: get contact
        Given The contact with <id> exist
        When I send GET request to /directory
        Then I receive <response>
    
        Examples:
          | id | response                                      |
          | 99 | {"id":99,"name":"Dwayne Klocko","email":"[email protected]","phoneNumber":"1-876-420-9890","secondaryPhoneNumber": "(914) 249-3519"}         |
          | 7  | {"id":7,"name":"Ian Weimann DVM","email":"[email protected]","phoneNumber":"(297) 962-1879", "secondaryPhoneNumber": "788.323.7782"} |
    
      Scenario Outline: delete contact
        Given The contact with <id> exist
        When I send DELETE request to /directory
        Then I get response code 200
    
        Examples:
          | id |
          | 99 |
          | 7  |
    

    디렉토리를 만듭니다.src/steps의 js


    const {Given, When, Then, AfterAll, After} = require('cucumber');
    const assert = require('assert').strict
    const restHelper = require('./../util/restHelper');
    
    Given('A contact {}', function (request) {
        this.context['request'] = JSON.parse(request);
    });
    
    When('I send POST request to {}', async function (path) {
        this.context['response'] = await restHelper.postData(`${process.env.SERVICE_URL}${path}`, this.context['request']);
    })
    
    Then('I get response code {int}', async function (code) {
        assert.equal(this.context['response'].status, code);
    });
    
    When('I send PATCH request with a {} to {}', async function (phoneNumberPayload, path) {
        const response = await restHelper.patchData(`${process.env.SERVICE_URL}${path}/${this.context['id']}`, JSON.parse(phoneNumberPayload));
        this.context['response'] = response;
    })
    
    Given('The contact with {int} exist', async function (id) {
        this.context['id'] = id;
    })
    
    When('I send GET request to {}', async function (path) {
        const response = await restHelper.getData(`${process.env.SERVICE_URL}${path}/${this.context['id']}`);
        this.context['response'] = response;
    })
    
    Then(/^I receive (.*)$/, async function (expectedResponse) {
        assert.deepEqual(this.context['response'].data, JSON.parse(expectedResponse));
    })
    
    When('I send DELETE request to {}', async function (path) {
        const response = await restHelper.deleteData(`${process.env.SERVICE_URL}${path}/${this.context['id']}`);
        this.context['response'] = response;
    })
    
    

    실제 REST 호출을 실행하는 서비스 만들기


    너는 어떤 http 클라이언트를 사용할 수 있다. 나는 axios를 사용한다.

    테스트 실행 및 보고서 생성


    npm i
    "./node_modules/.bin/cucumber-js -f json:cucumber.json src/features/ -r src/steps/ --tags '@directory-service'"
    
    이 명령에서parallel은 세 장면을 동시에 실행하는 데 사용됩니다.
    그게 다야.내 말은 이것이 바로 BDD에 오이와 작은 오이를 곁들이는 요점이다.
    이것은 오이 보고서 견본이다.

    단계 간에 데이터 공유


    단계 간에 데이터를 공유해야 할 수도 있습니다.Cucumber는 모든 장면에 독립된 상하문을 제공하는데 이런 갈고리와 절차에 노출되어 세계라고 부른다.기본 세계 구조 함수는 다음과 같습니다.
    function World({ attach, log, parameters }) {
      this.attach = attach
      this.log = log
      this.parameters = parameters
    }
    
    참고: 단계에서 World를 사용하려면 단계에서 익명 함수를 사용할 수 없습니다.
    const {setWorldConstructor} = require("cucumber");
    
    if (!process.env.DIRECTORY_SERVICE_URL) {
        require('dotenv-flow').config();
    }
    
    class CustomWorld {
        constructor({parameters}) {
            this.context = {};
        }
    }
    setWorldConstructor(CustomWorld);
    
    다음은 내가 시범 과정에서 사용한 편리한 라이브러리들이다.

    .환경 파일


    나는 환경에 특정한 변수를 저장하기 위해dotenv-flow-npm를 사용한다.
    참조: https://github.com/kerimdzhanov/dotenv-flow

    아날로그 REST API 설치


    나는 이미 json 서버 npm를 사용하여 아날로그 REST API를 설정했다.
    참조: https://github.com/typicode/json-server
    오이-https://github.com/cucumber/cucumber-js

    소스 코드 -https://github.com/ynmanware/nodejs-bdd/tree/v1.0


    한마디로 BDD는 모든 이해관계자의 협력에 기반을 다졌다.태그를 사용하면 DEV, SIT, UAT 또는 PROD를 위한 파이프를 구성하여 다른 BDD 키트를 실행할 수 있습니다.이러한 설정은 CI/CD 실천에서 매우 효과적일 수 있으며 개발과 배치 주기를 가속화하고 기본적인 품질 검사를 유지할 수 있다.

    좋은 웹페이지 즐겨찾기