การทดสอบ BDD คืออะไร? ตัวอย่างกรอบงาน

การทดสอบ BDD (การพัฒนาพฤติกรรมขับเคลื่อน) คืออะไร?

การทดสอบ BDD (การพัฒนาที่ขับเคลื่อนด้วยพฤติกรรม) เป็นเทคนิคหนึ่งของการพัฒนาซอฟต์แวร์แบบ Agile และเป็นส่วนขยายของ TDD เช่น Test Driven Development ใน BDD กรณีทดสอบจะเขียนด้วยภาษาธรรมชาติที่แม้แต่ผู้ที่ไม่ใช่โปรแกรมเมอร์ก็สามารถอ่านได้

การทดสอบ BDD ทำงานอย่างไร

พิจารณาว่าคุณได้รับมอบหมายให้สร้างโมดูลการโอนเงินในแอปพลิเคชัน Net Banking

มีหลายวิธีในการทดสอบ

  1. การโอนเงินควรเกิดขึ้นหากมียอดเงินในบัญชีต้นทางเพียงพอ
  2. การโอนเงินควรเกิดขึ้นหากรายละเอียดบัญชีปลายทางถูกต้อง
  3. การโอนเงินควรเกิดขึ้นหากรหัสผ่านธุรกรรม / รหัส rsa / การตรวจสอบความปลอดภัยสำหรับธุรกรรมที่ผู้ใช้ป้อนนั้นถูกต้อง
  4. การโอนเงินควรทำแม้ว่าจะเป็นวันหยุดธนาคารก็ตาม
  5. การโอนเงินควรเกิดขึ้นในอนาคตตามที่เจ้าของบัญชีกำหนด

การขอ สถานการณ์ทดสอบ กลายเป็นเรื่องซับซ้อนและละเอียดอ่อนมากขึ้นเมื่อเราพิจารณาถึงคุณลักษณะเพิ่มเติม เช่น จำนวนเงินโอน 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 ในปัจจุบัน จึงมีความสำคัญไม่แพ้กันในการสร้างกรณีทดสอบ REST API โดยอัตโนมัติพร้อมกับกรณีทดสอบ UI โดยพื้นฐานแล้ว REST เหล่านี้ การทดสอบ API เกี่ยวข้องกับการทดสอบการดำเนินการ CRUD (สร้าง-อ่าน-อัปเดต-ลบ) ด้วยวิธีการ POST, GET, PUT และ DELETE ตามลำดับ

ประพฤติคืออะไร?

ประพฤติเป็นหนึ่งในความนิยม Python กรอบการทดสอบ BDD

มาดูกันว่า Behave ทำงานอย่างไร:

ไฟล์ฟีเจอร์เขียนโดยนักวิเคราะห์ธุรกิจ / ผู้สนับสนุน / ใครก็ตามที่มีสถานการณ์พฤติกรรมของคุณอยู่ในนั้น มีรูปแบบภาษาธรรมชาติที่อธิบายคุณลักษณะหรือส่วนหนึ่งของคุณลักษณะพร้อมตัวอย่างที่เป็นตัวแทนของผลลัพธ์ที่คาดหวัง

ขั้นตอนของสถานการณ์สมมติเหล่านี้ถูกแม็ปกับการใช้งานขั้นตอนที่เขียนไว้ Python.

และยังมีการควบคุมด้านสิ่งแวดล้อมบางอย่าง (โค้ดที่ต้องรันก่อนและหลังขั้นตอน สถานการณ์ คุณสมบัติ หรือการแข่งขันนัดยิงทั้งหมด)

เริ่มต้นด้วยการตั้งค่ากรอบการทดสอบระบบอัตโนมัติด้วย Behave:

การตั้งค่า BDD Testing Framework ทำงาน Windows

การติดตั้ง:

การตั้งค่าโครงการ:

  • สร้างโครงการใหม่
  • สร้างโครงสร้างไดเร็กทอรีต่อไปนี้:

ตั้งค่าโครงการ

ไฟล์คุณสมบัติ:

เรามาสร้างไฟล์ฟีเจอร์ของเรากันดีกว่า 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 ไฟล์ในไดเร็กทอรี "ขั้นตอน"

Behave Framework ระบุฟังก์ชัน Step โดยตัวตกแต่งที่ตรงกับเพรดิเคตไฟล์ฟีเจอร์ ตัวอย่างเช่น ภาคแสดงที่กำหนดในไฟล์ฟีเจอร์สถานการณ์จำลองค้นหาฟังก์ชันขั้นตอนที่มีมัณฑนากร "ให้" การจับคู่ที่คล้ายกันเกิดขึ้นสำหรับเมื่อใดและหลังจากนั้น แต่ในกรณีของฟังก์ชัน 'แต่' 'และ' ขั้นตอนจะใช้ตัวตกแต่งเหมือนกับขั้นตอนก่อนหน้า ตัวอย่างเช่น หากใช้ 'And' แทน Give ตัวตกแต่งฟังก์ชันขั้นตอนที่ตรงกันจะเป็น @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

ในทำนองเดียวกัน การใช้งานขั้นตอนอื่นๆ ในไฟล์ step python จะมีลักษณะดังนี้:

ขั้นตอนการดำเนินการ

ตัวอย่าง_step_implementation.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

ดำเนินการทดสอบ

ตอนนี้เราเสร็จสิ้นในส่วนการพัฒนาสคริปต์ทดสอบแล้ว มาทำการทดสอบกันดีกว่า:

ดำเนินการคำสั่งต่อไปนี้ที่พรอมต์คำสั่งเพื่อเรียกใช้ไฟล์ฟีเจอร์ของเรา

ค: \โปรแกรม\Python\Python37>ประพฤติตัวสวย ค:\ \features\feature_files_folder\Sample_REST_API_Testing.feature

ซึ่งจะแสดงผลการดำเนินการทดสอบดังต่อไปนี้:

ดำเนินการทดสอบ

รายงานการแสดงผลบนคอนโซล

เรามาดูสิ่งที่น่าสนใจอีกอย่างที่นี่

เนื่องจากผู้ใช้มักต้องการดูผลการทดสอบในรูปแบบที่อ่านได้และนำเสนอได้ง่ายกว่า ดังนั้นเราจึงสามารถสร้างรายงานในรูปแบบ HTML ด้วยความช่วยเหลือของ Allure

รายงาน

ก่อนอื่น คุณต้องติดตั้งฟอร์แมตเตอร์ Allure Behave [https://docs.qameta.io/allure-report/]:

และตอนนี้ให้ดำเนินการคำสั่งต่อไปนี้:

สำหรับรายงาน

>ประพฤติ -f json -o Sample_REST_API_Testing.feature

- เสน่ห์เสิร์ฟ

สิ่งนี้จะสร้างรายงานผลการทดสอบของคุณในรูปแบบที่ปรากฏและให้ข้อมูลดังนี้:

รายงาน

รายงานการทดสอบในรูปแบบ HTML

รายงานการทดสอบในรูปแบบ HTML

รายงานการทดสอบแสดงผลสถานการณ์แต่ละรายการ

สรุป

  • BDD คือการพัฒนาที่ขับเคลื่อนด้วยพฤติกรรม เป็นหนึ่งในเทคนิคการพัฒนาซอฟต์แวร์แบบอไจล์
  • REST กลายเป็นสไตล์ยอดนิยมสำหรับการสร้าง API ในปัจจุบัน และมีความสำคัญไม่แพ้กันในการสร้างกรณีทดสอบ REST API โดยอัตโนมัติพร้อมกับกรณีทดสอบ UI
  • BDD มีรูปแบบภาษาธรรมชาติที่อธิบายคุณลักษณะหรือส่วนหนึ่งของคุณลักษณะพร้อมตัวอย่างที่เป็นตัวแทนของผลลัพธ์ที่คาดหวัง
  • Behave Framework ระบุฟังก์ชัน Step โดยตัวตกแต่งที่ตรงกับเพรดิเคตไฟล์ฟีเจอร์
  • ตัวอย่างของกรอบการทดสอบ BDD: 1) Cucumber 2) SpecFlow 3) ควอนตัม 4) JBehave 5) การรับรู้โค้ด

สรุปโพสต์นี้ด้วย: