การทดสอบ BDD คืออะไร? ตัวอย่างกรอบงาน
การทดสอบ BDD (การพัฒนาพฤติกรรมขับเคลื่อน) คืออะไร?
การทดสอบ BDD (การพัฒนาที่ขับเคลื่อนด้วยพฤติกรรม) เป็นเทคนิคหนึ่งของการพัฒนาซอฟต์แวร์แบบ Agile และเป็นส่วนขยายของ TDD เช่น Test Driven Development ใน BDD กรณีทดสอบจะเขียนด้วยภาษาธรรมชาติที่แม้แต่ผู้ที่ไม่ใช่โปรแกรมเมอร์ก็สามารถอ่านได้
การทดสอบ BDD ทำงานอย่างไร
พิจารณาว่าคุณได้รับมอบหมายให้สร้างโมดูลการโอนเงินในแอปพลิเคชัน Net Banking
มีหลายวิธีในการทดสอบ
- การโอนเงินควรเกิดขึ้นหากมียอดเงินในบัญชีต้นทางเพียงพอ
- การโอนเงินควรเกิดขึ้นหากรายละเอียดบัญชีปลายทางถูกต้อง
- การโอนเงินควรเกิดขึ้นหากรหัสผ่านธุรกรรม / รหัส rsa / การตรวจสอบความปลอดภัยสำหรับธุรกรรมที่ผู้ใช้ป้อนนั้นถูกต้อง
- การโอนเงินควรทำแม้ว่าจะเป็นวันหยุดธนาคารก็ตาม
- การโอนเงินควรเกิดขึ้นในอนาคตตามที่เจ้าของบัญชีกำหนด
การขอ สถานการณ์ทดสอบ กลายเป็นเรื่องซับซ้อนและละเอียดอ่อนมากขึ้นเมื่อเราพิจารณาถึงคุณลักษณะเพิ่มเติม เช่น จำนวนเงินโอน 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
การติดตั้ง:
- ดาวน์โหลดและติดตั้ง Python 3 จาก https://www.python.org/
- ดำเนินการคำสั่งต่อไปนี้ที่พรอมต์คำสั่งเพื่อติดตั้งพฤติกรรม
- 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 ไฟล์ในไดเร็กทอรี "ขั้นตอน"
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
รายงานการทดสอบแสดงผลสถานการณ์แต่ละรายการ
สรุป
- BDD คือการพัฒนาที่ขับเคลื่อนด้วยพฤติกรรม เป็นหนึ่งในเทคนิคการพัฒนาซอฟต์แวร์แบบอไจล์
- REST กลายเป็นสไตล์ยอดนิยมสำหรับการสร้าง API ในปัจจุบัน และมีความสำคัญไม่แพ้กันในการสร้างกรณีทดสอบ REST API โดยอัตโนมัติพร้อมกับกรณีทดสอบ UI
- BDD มีรูปแบบภาษาธรรมชาติที่อธิบายคุณลักษณะหรือส่วนหนึ่งของคุณลักษณะพร้อมตัวอย่างที่เป็นตัวแทนของผลลัพธ์ที่คาดหวัง
- Behave Framework ระบุฟังก์ชัน Step โดยตัวตกแต่งที่ตรงกับเพรดิเคตไฟล์ฟีเจอร์
- ตัวอย่างของกรอบการทดสอบ BDD: 1) Cucumber 2) SpecFlow 3) ควอนตัม 4) JBehave 5) การรับรู้โค้ด






