BDD 테스트란 무엇입니까? 프레임워크 예시
BDD(행동 중심 개발) 테스트란 무엇입니까?
BDD(행동 중심 개발) 테스트 민첩한 소프트웨어 개발 기술이며 TDD의 확장, 즉 테스트 주도 개발입니다. BDD에서는 테스트 케이스가 프로그래머가 아닌 사람도 읽을 수 있는 자연어로 작성됩니다.
BDD 테스트는 어떻게 작동하나요?
Net Banking 애플리케이션에서 자금 이체 모듈을 생성하도록 지정되었다고 가정해 보세요.
테스트하는 방법에는 여러 가지가 있습니다.
- 원본 계정에 잔액이 충분한 경우 자금 이체가 이루어져야 합니다.
- 목적지 a/c 세부 정보가 정확한 경우 자금 이체가 이루어져야 합니다.
- 사용자가 입력한 거래에 대한 거래비밀번호/RSA코드/보안인증이 정확할 경우 자금이체가 이루어져야 합니다.
- 은행 휴무일이라도 자금 이체는 이루어져야 합니다.
- 자금 이체는 계좌 소유자가 설정한 미래 날짜에 이루어져야 합니다.
The 테스트 시나리오 X의 이체 금액에 대해 Y일/월 간격을 두고, 총 금액이 Z에 도달하면 이체 일정을 중지하는 등의 추가 기능을 고려함에 따라 더욱 정교하고 복잡해집니다.
개발자의 일반적인 경향은 기능을 개발하고 나중에 테스트 코드를 작성하는 것입니다. 위의 사례에서 알 수 있듯이, 테스트 케이스 이 경우 개발은 복잡하고 개발자는 이를 미룰 것입니다. 지원 출시될 때까지 그는 신속하지만 비효과적인 테스트를 수행할 것입니다.
이 문제(행동 중심 개발)를 극복하기 위해 BDD가 고안되었습니다. 개발자가 전체 테스트 프로세스를 쉽게 수행할 수 있습니다.
BDD에서는 무엇이든 작성해야 합니다. 주어진 시기와 그때 단계. BDD에서 위의 동일한 예를 고려해 보겠습니다.
Given that a fund transfer module in net banking application has been developed And I am accessing it with proper authentication
WhenI shall transfer with enough balance in my source account Or I shall transfer on a Bank Holiday Or I shall transfer on a future date And destination a/c details are correct And transaction password/rsa code / security authentication for the transaction is correct And press or click send button
Then amount must be transferred And the event will be logged in log file
쓰고 읽고 이해하는 것이 쉽지 않습니까? 이는 자금 이체 모듈에 대해 가능한 모든 테스트 사례를 다루며 더 많은 것을 수용하도록 쉽게 수정할 수 있습니다. 또한 자금 이체 모듈에 대한 문서를 작성하는 것과 비슷합니다.
REST API 테스트란 무엇입니까?
REST가 요즘 API 구축에 널리 사용되는 스타일이 되면서 UI 테스트 사례와 함께 REST API 테스트 사례를 자동화하는 것도 똑같이 중요해졌습니다. 기본적으로 이러한 REST는 API 테스트 POST, GET, PUT 및 DELETE 메서드를 각각 사용하여 CRUD(Create-Read-Update-Delete) 작업을 테스트하는 작업이 포함됩니다.
행동이란 무엇입니까?
행동은 인기있는 것 중 하나입니다 Python BDD 테스트 프레임워크.
Behave가 어떻게 작동하는지 살펴보겠습니다.
기능 파일은 비즈니스 분석가/후원자/행동 시나리오가 있는 사람이 작성합니다. 예상 결과의 대표적인 예와 함께 기능 또는 기능의 일부를 설명하는 자연어 형식이 있습니다.
이러한 시나리오 단계는 다음으로 작성된 단계 구현과 매핑됩니다. Python.
그리고 선택적으로 몇 가지 환경 제어(단계, 시나리오, 기능 또는 전체 촬영 경기 전후에 실행되는 코드)가 있습니다.
Behave를 사용하여 자동화 테스트 프레임워크 설정을 시작해 보겠습니다.
BDD 테스트 프레임워크 동작 설정 Windows
설치:
- 다운로드 및 설치 Python 3에서 https://www.python.org/
- 명령 프롬프트에서 다음 명령을 실행하여 Behavior를 설치하세요.
- pip 설치 동작
- IDE: PyCharm Community Edition을 사용했습니다. https://www.jetbrains.com/pycharm/download
프로젝트 설정 :
- 새로운 프로젝트 만들기
- 다음 디렉토리 구조를 생성하세요.
기능 파일:
이제 기능 파일을 만들어 보겠습니다. Sample_REST_API_Testing.feature '게시물' 서비스에 CRUD 작업을 수행하는 기능이 있습니다.
우리의 예에서는 http://jsonplaceholder.typicode.com/ 샘플 REST 서비스를 게시합니다.
예제 POST 시나리오
Scenario: POST post example ->Here we are considering creating new post item using 'posts' service Given: I set post posts API endpoint ->This is prerequisite for the test which is setting URL of posts service When: I set HEADER param request content type as "application/json." And set request body And send POST HTTP request ->This is actual test step of sending a post request Then: Then I receive valid HTPP response code 201 And Response body "POST" is non-empty-> This is verification of response body
마찬가지로 나머지 시나리오도 다음과 같이 작성할 수 있습니다.
Sample_REST_API_Testing.feature
Feature: Test CRUD methods in Sample REST API testing framework
Background:
Given I set sample REST API url
Scenario: POST post example
Given I Set POST posts api endpoint
When I Set HEADER param request content type as "application/json."
And Set request Body
And Send a POST HTTP request
Then I receive valid HTTP response code 201
And Response BODY "POST" is non-empty.
Scenario: GET posts example
Given I Set GET posts api endpoint "1"
When I Set HEADER param request content type as "application/json."
And Send GET HTTP request
Then I receive valid HTTP response code 200 for "GET."
And Response BODY "GET" is non-empty
Scenario: UPDATE posts example
Given I Set PUT posts api endpoint for "1"
When I Set Update request Body
And Send PUT HTTP request
Then I receive valid HTTP response code 200 for "PUT."
And Response BODY "PUT" is non-empty
Scenario: DELETE posts example
Given I Set DELETE posts api endpoint for "1"
When I Send DELETE HTTP request
Then I receive valid HTTP response code 200 for "DELETE."
단계 구현
이제 위 시나리오에서 사용되는 기능 단계의 경우 구현을 다음과 같이 작성할 수 있습니다. Python "steps" 디렉터리에 있는 파일입니다.
Behave 프레임워크는 기능 파일 조건자와 일치하는 데코레이터로 Step 함수를 식별합니다. 예를 들어 기능 파일 시나리오의 주어진 술어는 데코레이터가 "주어진" 단계 함수를 검색합니다. When과 Then에 대해서도 비슷한 일치가 발생합니다. 하지만 'But', 'And'의 경우 Step 함수는 이전 단계와 동일하게 Decorator를 사용합니다. 예를 들어, Give에 'And'가 오면 일치하는 단계 함수 데코레이터는 @given입니다.
예를 들어 POST 단계를 다음과 같이 구현할 수 있습니다.
@when (u'I Set HEADER param request content type as "{header_conent_type}"')
Mapping of When, here notice “application/json” is been passed from feature file for "{header_conent_type}” . This is called as parameterization
def step_impl (context, header_conent_type):
This is step implementation method signature
request_headers['Content-Type'] = header_conent_type
Step implementation code, here you will be setting content type for request header
마찬가지로, 단계 Python 파일의 다른 단계 구현은 다음과 같습니다.
샘플_단계_구현.py
from behave import given, when, then, step
import requests
api_endpoints = {}
request_headers = {}
response_codes ={}
response_texts={}
request_bodies = {}
api_url=None
@given(u'I set sample REST API url')
def step_impl(context):
global api_url
api_url = 'http://jsonplaceholder.typicode.com'
# START POST Scenario
@given(u'I Set POST posts api endpoint')
def step_impl(context):
api_endpoints['POST_URL'] = api_url+'/posts'
print('url :'+api_endpoints['POST_URL'])
@when(u'I Set HEADER param request content type as "{header_conent_type}"')
def step_impl(context, header_conent_type):
request_headers['Content-Type'] = header_conent_type
#You may also include "And" or "But" as a step - these are renamed by behave to take the name of their preceding step, so:
@when(u'Set request Body')
def step_impl(context):
request_bodies['POST']={"title": "foo","body": "bar","userId": "1"}
#You may also include "And" or "But" as a step - these are renamed by behave to take the name of their preceding step, so:
@when(u'Send POST HTTP request')
def step_impl(context):
# sending get request and saving response as response object
response = requests.post(url=api_endpoints['POST_URL'], json=request_bodies['POST'], headers=request_headers)
#response = requests.post(url=api_endpoints['POST_URL'], headers=request_headers) #https://jsonplaceholder.typicode.com/posts
# extracting response text
response_texts['POST']=response.text
print("post response :"+response.text)
# extracting response status_code
statuscode = response.status_code
response_codes['POST'] = statuscode
@then(u'I receive valid HTTP response code 201')
def step_impl(context):
print('Post rep code ;'+str(response_codes['POST']))
assert response_codes['POST'] is 201
# END POST Scenario
# START GET Scenario
@given(u'I Set GET posts api endpoint "{id}"')
def step_impl(context,id):
api_endpoints['GET_URL'] = api_url+'/posts/'+id
print('url :'+api_endpoints['GET_URL'])
#You may also include "And" or "But" as a step - these are renamed by behave to take the name of their preceding step, so:
@when(u'Send GET HTTP request')
def step_impl(context):
# sending get request and saving response as response object
response = requests.get(url=api_endpoints['GET_URL'], headers=request_headers) #https://jsonplaceholder.typicode.com/posts
# extracting response text
response_texts['GET']=response.text
# extracting response status_code
statuscode = response.status_code
response_codes['GET'] = statuscode
@then(u'I receive valid HTTP response code 200 for "{request_name}"')
def step_impl(context,request_name):
print('Get rep code for '+request_name+':'+ str(response_codes[request_name]))
assert response_codes[request_name] is 200
@then(u'Response BODY "{request_name}" is non-empty')
def step_impl(context,request_name):
print('request_name: '+request_name)
print(response_texts)
assert response_texts[request_name] is not None
# END GET Scenario
#START PUT/UPDATE
@given(u'I Set PUT posts api endpoint for "{id}"')
def step_impl(context,id):
api_endpoints['PUT_URL'] = api_url + '/posts/'+id
print('url :' + api_endpoints['PUT_URL'])
@when(u'I Set Update request Body')
def step_impl(context):
request_bodies['PUT']={"title": "foo","body": "bar","userId": "1","id": "1"}
@when(u'Send PUT HTTP request')
def step_impl(context):
# sending get request and saving response as response object # response = requests.post(url=api_endpoints['POST_URL'], headers=request_headers) #https://jsonplaceholder.typicode.com/posts
response = requests.put(url=api_endpoints['PUT_URL'], json=request_bodies['PUT'], headers=request_headers)
# extracting response text
response_texts['PUT'] = response.text
print("update response :" + response.text)
# extracting response status_code
statuscode = response.status_code
response_codes['PUT'] = statuscode
#END PUT/UPDATE
#START DELETE
@given(u'I Set DELETE posts api endpoint for "{id}"')
def step_impl(context,id):
api_endpoints['DELETE_URL'] = api_url + '/posts/'+id
print('url :' + api_endpoints['DELETE_URL'])
@when(u'I Send DELETE HTTP request')
def step_impl(context):
# sending get request and saving response as response object
response = requests.delete(url=api_endpoints['DELETE_URL'])
# response = requests.post(url=api_endpoints['POST_URL'], headers=request_headers) #https://jsonplaceholder.typicode.com/posts
# extracting response text
response_texts['DELETE'] = response.text
print("DELETE response :" + response.text)
# extracting response status_code
statuscode = response.status_code
response_codes['DELETE'] = statuscode
#END DELETE
테스트 실행
이제 테스트 스크립트 개발 부분이 완료되었으므로 테스트를 실행해 보겠습니다.
명령 프롬프트에서 다음 명령을 실행하여 기능 파일을 실행합니다.
C: \프로그램\Python\Python37>행동하다 -f 예쁘다 씨:\ \features\feature_files_folder\Sample_REST_API_Testing.feature
그러면 테스트 실행 결과가 다음과 같이 표시됩니다.
콘솔에 보고서 표시
여기서 또 다른 멋진 점을 살펴보겠습니다.
사용자는 항상 더 읽기 쉽고 표현하기 쉬운 형식으로 테스트 결과를 보고 싶어하므로 Allure의 도움을 받아 HTML 형식으로 보고서를 만들어 보겠습니다.
보고서
먼저 Allure Behave 포맷터를 설치해야 합니다.https://docs.qameta.io/allure-report/]:
이제 다음 명령을 실행하세요.
보고서의 경우
>행동 -f json -o Sample_REST_API_Testing.feature
> 매력 서브
그러면 다음과 같이 표시 가능하고 유익한 형식으로 테스트 결과 보고서가 생성됩니다.
HTML 형식의 테스트 보고서
개별 시나리오 결과를 표시하는 테스트 보고서
제품 개요
- BDD는 행동 중심 개발입니다. 민첩한 소프트웨어 개발 기술 중 하나입니다.
- REST는 요즘 API 구축에 매우 인기 있는 스타일이 되었으며, UI 테스트 사례와 함께 REST API 테스트 사례를 자동화하는 것도 똑같이 중요해졌습니다.
- BDD에는 예상 결과의 대표적인 예와 함께 기능 또는 기능의 일부를 설명하는 자연어 형식이 있습니다.
- Behave 프레임워크는 기능 파일 조건자와 일치하는 데코레이터로 Step 함수를 식별합니다.
- BDD 테스트 프레임워크의 예: 1) Cucumber 2) SpecFlow 3) Quantum 4) JBehave 5) 코드셉션






