Tavern เป็นผลงานวิศวกรรมที่ชาญฉลาด มันเชื่อมต่อกับ pytest ช่วยให้คุณสามารถอธิบายการทดสอบ API เป็นไฟล์ YAML และรันไฟล์นั้นเหมือนเป็นการทดสอบ pytest ปกติ คุณจะได้รับประโยชน์จากระบบนิเวศทั้งหมดของ pytest ฟรี: fixtures, plugins, การรันแบบขนานด้วย pytest-xdist, coverage และคำสั่งเดียวกันที่ทีม Python ของคุณใช้อยู่แล้ว สำหรับทีมแบ็กเอนด์ที่คุ้นเคยกับ pytest การเขียนไฟล์ test_*.tavern.yaml เพิ่มเติมข้าง ๆ หน่วยทดสอบก็เป็นเรื่องธรรมชาติ
ปัญหาเริ่มปรากฏขึ้นเมื่อไฟล์ YAML มีขนาดใหญ่ขึ้น คำขอเดียวที่ส่งเนื้อหา บันทึกโทเค็น และตรวจสอบฟิลด์ตอบกลับไม่กี่รายการ จะกลายเป็นบล็อกที่ซ้อนกันของคีย์ request, response, save และ verify_response_with ที่คุณต้องเว้นวรรคให้ถูกต้อง การไหลแบบหลายขั้นตอน (เช่น ล็อกอิน สร้างทรัพยากร อ่านข้อมูลกลับมา ลบทิ้ง) จะเรียงซ้อนบล็อกเหล่านั้นลงในไฟล์ยาว ๆ ไฟล์เดียว ซึ่งการเว้นวรรคผิดตำแหน่งอาจทำให้การแยกวิเคราะห์ล้มเหลว และสัญญา API ที่การทดสอบตรวจสอบก็ไปอยู่ในที่อื่นโดยสิ้นเชิง: ไฟล์ Swagger, หน้า Wiki, หรือ Postman collection ที่ล้าสมัยไปหลายเดือนแล้ว
Tavern ทำอะไรได้ดี
มาเริ่มต้นด้วยการให้เครดิต เพราะ Tavern สมควรได้รับมัน
มันอยู่บนพื้นฐานของ pytest ไม่ใช่การมาแทนที่ pytest Tavern เป็นปลั๊กอินของ pytest คุณติดตั้งมันด้วย pip install tavern วางไฟล์ YAML ไว้ในไดเรกทอรีทดสอบของคุณ และ pytest จะค้นพบและรันมันเหมือนกับการทดสอบอื่น ๆ นั่นหมายความว่าคุณยังคงรักษานิสัยการใช้ pytest ที่ทีมของคุณมีอยู่แล้ว: -k สำหรับการกรอง, -x สำหรับหยุดเมื่อพบความล้มเหลวครั้งแรก, pytest-html สำหรับรายงาน, pytest-xdist สำหรับการรันแบบขนาน, fixtures สำหรับการตั้งค่าร่วม ไม่มีอะไรเกี่ยวกับการรันเนอร์ของคุณเปลี่ยนแปลงไป สำหรับร้านค้าที่ใช้ Python นี่คือข้อได้เปรียบที่แท้จริง และเครื่องมือทดสอบ API ไม่กี่ตัวที่จะผสานรวมเข้ากับชุดทดสอบที่มีอยู่ได้อย่างลงตัวเช่นนี้
YAML เป็นแบบเชิงประกาศและอ่านง่าย การทดสอบ Tavern แบบง่าย ๆ นั้นอ่านง่ายจริง ๆ:
test_name: Get a single order
stages:
- name: Fetch order 1042
request:
url: https://api.shop.test/orders/1042
method: GET
response:
status_code: 200
json:
id: 1042
status: shipped
ไม่มีโค้ดเชื่อมต่อ ไม่มีไลบรารี assertion ให้ต้อง import ไม่มี test harness ให้ต้องเขียน คำขอและการตอบกลับที่คาดหวังอยู่เคียงข้างกัน สำหรับการตรวจสอบรหัสสถานะและฟิลด์ไม่กี่รายการ มันอ่านได้ดีกว่าโค้ด Python ที่เทียบเท่ากันโดยใช้ requests บวกกับ assert
การบันทึกและเชื่อมโยงตัวแปร Tavern สามารถดึงค่าออกจาก response หนึ่งและนำไปใช้ในขั้นตอนถัดไปได้ด้วย save และการแทนที่ {variable} ดังนั้นขั้นตอนการล็อกอินแล้วเรียกใช้จึงทำงานได้โดยไม่ต้องเขียนโค้ดเอง:
stages:
- name: Log in
request:
url: https://api.shop.test/auth/login
method: POST
json:
username: tester
password: hunter2
response:
status_code: 200
save:
json:
token: access_token
- name: Read the profile with the saved token
request:
url: https://api.shop.test/me
method: GET
headers:
Authorization: "Bearer {token}"
response:
status_code: 200
มันทำได้มากกว่า HTTP Tavern ยังทดสอบ MQTT ซึ่งมีความสำคัญหากคุณทำงานกับ IoT หรือระบบที่ขับเคลื่อนด้วยข้อความ และเนื่องจากมันอยู่ภายใต้ pytest คุณสามารถผสมผสานการทดสอบ API แบบ YAML และการทดสอบ Python ปกติในการรันเดียวกันและรายงานเดียวกันได้
ทั้งหมดที่กล่าวมาไม่ใช่การตลาด Tavern เป็นเครื่องมือที่แข็งแกร่ง คำถามคือสมมติฐานของมันตรงกับความต้องการของคุณหรือไม่
YAML ส่วนประกอบที่ซ้ำซ้อนเพิ่มขึ้นที่ไหน
มีสามข้อเสียที่มาพร้อมกับโมเดลของ Tavern และความสำคัญของมันขึ้นอยู่กับว่าชุดทดสอบของคุณใหญ่แค่ไหน
YAML เป็นสิ่งที่ต้องระวังการเว้นวรรค และโครงสร้าง schema ก็ลึกซึ้ง ตัวอย่างง่าย ๆ ข้างต้นนั้นสะอาดตา การทดสอบจริงนั้นไม่เป็นเช่นนั้น เมื่อคุณเพิ่ม headers, query parameters, request body, response-body assertions, type checks, saved variables และ verify_response_with external functions คุณจะต้องซ้อนกันสี่ถึงห้าระดับในรูปแบบที่การเว้นวรรคผิดเพียงจุดเดียวจะทำให้เกิดข้อผิดพลาดในการแยกวิเคราะห์ ไม่ใช่ข้อความที่ชัดเจน Editor ไม่เติมข้อความอัตโนมัติสำหรับคีย์ของ Tavern เหมือนกับที่ IDE เติมข้อความอัตโนมัติสำหรับเมธอด Python ดังนั้นคุณต้องตรวจสอบเอกสารว่าต้องใช้ status_code หรือ status, json หรือ body สำหรับแต่ละฟิลด์ใหม่
การทดสอบและสัญญา API เป็นสิ่งประดิษฐ์ที่แยกจากกันสองชิ้น YAML ของ Tavern กำหนด URL, เมธอด, ฟิลด์ที่คาดหวัง และประเภทของมันไว้ตายตัว คำจำกัดความ API จริง ๆ อยู่ในไฟล์ OpenAPI, ตัวตกแต่งเส้นทางของเฟรมเวิร์ก หรือไม่มีใครรู้แน่ชัดว่าอยู่ที่ไหน เมื่อ API เปลี่ยนชื่อฟิลด์ ไม่มีอะไรบอก YAML การทดสอบยังคงยืนยันรูปแบบเก่าจนกว่าจะล้มเหลวใน CI หรือแย่กว่านั้นคือยังคงผ่านการคาดการณ์ที่ล้าสมัยต่อไป ใครบางคนต้องทำให้ทั้งสองสิ่งตรงกันด้วยตนเอง และคน ๆ นั้นมักจะเป็นคนที่เจอปัญหาตอนตีสอง
มันตั้งสมมติฐานว่ามีเครื่องมือและคน Python Tavern ยอดเยี่ยมหากผู้ทดสอบของคุณเขียน Python หากกลุ่ม QA, วิศวกรส่วนหน้า หรือผู้บริหารผลิตภัณฑ์ของคุณต้องการเพิ่มหรืออ่านการทดสอบ พวกเขาจะต้องเผชิญกับ pip, virtualenvs, รูปแบบของ pytest และกฎ schema ของ YAML ทั้งหมดในคราวเดียว เพียงเพื่อส่งคำขอ HTTP และตรวจสอบการตอบกลับ อุปสรรคในการเริ่มต้นสูงชันสำหรับทุกคนที่อยู่นอกโลกของ Python
เส้นทางที่จะข้าม YAML
ทางเลือกอื่นคือการหยุดเขียนการทดสอบเป็นไฟล์ข้อความ และเริ่มสร้างการทดสอบกับคำจำกัดความ API ที่คุณมีอยู่แล้ว
ใน Apidog, สเปก API, คำขอ และการทดสอบ เป็นอ็อบเจกต์เดียวกัน คุณนำเข้าหรือออกแบบ API ของคุณเพียงครั้งเดียว (OpenAPI, Swagger, หรือ Postman collection สามารถนำเข้าได้ในคลิกเดียว) และแต่ละ endpoint ก็มาพร้อมกับ schema ที่แท้จริงของมัน คุณสร้างสถานการณ์ทดสอบโดยการเชื่อมโยง endpoint เหล่านั้นด้วยภาพ: ลากการเรียกเข้าสู่ระบบ, ลากการเรียกที่ต้องการโทเค็น, และส่งค่าไปข้างหน้าโดยไม่ต้องเขียนบล็อก save: หรือสตริง {variable} ด้วยตนเอง การยืนยัน (Assertions) เป็นช่องทำเครื่องหมายและนิพจน์ในแผงควบคุม ไม่ใช่คีย์ YAML ที่มีการเยื้องที่คุณต้องจดจำ
เนื่องจากการทดสอบถูกสร้างขึ้นจากสเปก สเปกจึงเป็นแหล่งความจริงเดียว การเปลี่ยนฟิลด์ตอบกลับในการออกแบบ และสถานการณ์ทดสอบที่อ้างถึงมันจะแสดงการเปลี่ยนแปลงแทนที่จะล้าสมัยไปอย่างเงียบ ๆ นี่คือสิ่งที่ Tavern ไม่สามารถทำได้ในเชิงโครงสร้าง: YAML ของมันไม่มีการเชื่อมโยงกลับไปยังสัญญา
และเมื่อถึงเวลาที่จะทำการอัตโนมัติ คุณจะไม่สูญเสียคุณสมบัติแบบ headless ที่เป็นมิตรกับ CI ซึ่งทำให้ Tavern น่าสนใจ Apidog CLI รันสถานการณ์เหล่านั้นจากบรรทัดคำสั่ง ใน CI โดยไม่มี GUI อย่างแท้จริงเหมือนกับที่ pytest รันไฟล์ Tavern ของคุณในปัจจุบัน
การติดตั้งและรัน Apidog CLI
รันเนอร์เป็นแพ็คเกจ npm ฟรีชื่อ apidog-cli ติดตั้งทั่วโลก:
npm install -g apidog-cli
จากนั้นรันสถานการณ์ทดสอบด้วยคำสั่ง apidog run:
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 605067 -e 1629989 -r cli
นี่คือสิ่งที่แต่ละส่วนทำ:
--access-tokenใช้ตรวจสอบสิทธิ์การรันกับบัญชี Apidog ของคุณ สร้างโทเค็นจากแท็บ CI/CD ของสถานการณ์และจัดเก็บเป็นความลับ ห้ามเก็บไว้ในไฟล์-tคือ ID สถานการณ์ทดสอบ-eคือ ID สภาพแวดล้อม (dev, staging, prod) เพื่อให้สถานการณ์เดียวกันเข้าถึง Base URL และตัวแปรที่ถูกต้อง-rเลือกตัวรายงานcliจะพิมพ์ผลลัพธ์ที่อ่านได้ไปยังเทอร์มินัล
คุณไม่จำเป็นต้องจำ ID เหล่านั้น เปิดสถานการณ์ทดสอบใน Apidog สลับไปที่แท็บ CI/CD เลือกตัวเลือกบรรทัดคำสั่ง และคลิก Generate token Apidog จะสร้างคำสั่ง apidog run ที่สมบูรณ์ให้คุณ โดยมี ID สถานการณ์และ ID สภาพแวดล้อมที่กรอกไว้แล้ว คัดลอกแล้วย้ายโทเค็นไปยัง CI secret
หากคุณไม่ต้องการติดตั้งแบบทั่วโลก โดยเฉพาะบน CI runner ชั่วคราว ให้รันด้วย npx:
npx apidog-cli run --access-token $APIDOG_ACCESS_TOKEN -t 605067 -e 1629989 -r cli
ตัวรายงานครอบคลุม cli, html, json และ junit สำหรับ CI การผสมผสานที่มีประโยชน์คือ -r html,junit: junit จะส่งออก XML มาตรฐานที่เกือบทุกแดชบอร์ด CI แยกวิเคราะห์เป็นต้นไม้ผ่าน/ล้มเหลว และ html จะสร้างรายงานที่เรียกดูได้ซึ่งคุณสามารถเก็บถาวรเป็น build artifact เพิ่ม --out-dir เพื่อควบคุมตำแหน่งที่จัดเก็บ:
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 605067 -e 1629989 -r html,junit --out-dir ./apidog-reports
สำหรับรายการธงทั้งหมดในเวอร์ชันที่คุณติดตั้ง ให้รัน apidog run --help
เปรียบเทียบเคียงข้างกัน
| Tavern | Apidog | |
|---|---|---|
| รูปแบบการทดสอบ | ไฟล์ YAML (*.tavern.yaml) |
สถานการณ์จำลองแบบภาพที่สร้างขึ้นจากสเปก |
| สภาพแวดล้อมรันไทม์ | Python + pytest | apidog run แบบ Headless (แพ็คเกจ npm) |
| การเขียน | เขียนและจัดระเบียบ YAML ด้วยตนเอง | ลากและเชื่อมโยง endpoints, ยืนยันด้วยช่องทำเครื่องหมาย |
| สัญญา API | สิ่งประดิษฐ์แยกต่างหาก ต้องดูแลให้ตรงกันด้วยตนเอง | สเปกคือแหล่งความจริงเดียวของการทดสอบ |
| การเชื่อมโยงตัวแปร | บล็อก save: และการแทนที่ {var} |
ส่งผ่านค่าระหว่างขั้นตอนใน UI |
| ตัวรายงาน | pytest-html, JUnit ผ่านปลั๊กอิน pytest |
cli, html, json, junit ในตัว |
| ใครสามารถเขียนการทดสอบได้บ้าง | ผู้ทดสอบที่คุ้นเคยกับ Python | ทุกคนในทีม รวมถึงผู้ที่ไม่ใช่โปรแกรมเมอร์ |
| โปรโตคอล | HTTP และ MQTT | HTTP, บวกกับ SOAP, WebSocket, gRPC และอื่น ๆ |
Tavern ชนะหากทีมของคุณใช้ Python เป็นหลัก และคุณต้องการให้การทดสอบอยู่ใน repository เดียวกัน และรัน pytest เดียวกันกับการทดสอบหน่วยของคุณ Apidog ชนะหากคุณต้องการลดการบำรุงรักษา YAML รักษาสัญญาและการทดสอบเป็นสิ่งเดียวกัน และให้ผู้ที่ไม่เขียน Python มีส่วนร่วมในการทดสอบได้
การเชื่อมต่อเข้ากับ CI
การรันแบบ headless คือจุดประสงค์ทั้งหมดของการย้ายจากไฟล์ทดสอบในเครื่องไปยัง pipeline นี่คือรูปแบบของ GitHub Actions:
name: API tests
on: [push, pull_request]
jobs:
api-tests:
runs-on: ubuntu-latest
steps:
- name: Install Apidog CLI
run: npm install -g apidog-cli
- name: Run API test scenario
run: |
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t 605067 \
-e 1629989 \
-r html,junit \
--out-dir apidog-reports
env:
APIDOG_ACCESS_TOKEN: ${{ secrets.APIDOG_ACCESS_TOKEN }}
- name: Upload report
if: always()
uses: actions/upload-artifact@v4
with:
name: apidog-report
path: apidog-reports
โทเค็นมาจาก repository secrets และเข้าถึงขั้นตอนในฐานะตัวแปรสภาพแวดล้อม if: always() ในขั้นตอนการอัปโหลดหมายความว่าคุณยังคงได้รับรายงานเมื่อการทดสอบล้มเหลว ซึ่งเป็นเวลาที่คุณต้องการอ่านมันมากที่สุด หากการยืนยันล้มเหลว ขั้นตอน apidog run จะออกโค้ดที่ไม่ใช่ศูนย์ งานจะกลายเป็นสีแดง และ pull request จะแสดงการตรวจสอบที่ล้มเหลว
พฤติกรรมการออกโค้ดนี้คือประตูคุณภาพ และมันทำงานในลักษณะเดียวกับ Tavern: CI อ่านโค้ดออกของแต่ละขั้นตอน โค้ดออกที่ไม่ใช่ศูนย์จะทำให้งานล้มเหลว และงานที่ล้มเหลวจะบล็อกการรวมหรือการปรับใช้ คุณไม่จำเป็นต้องกำหนดค่าอะไรเพิ่มเติมเพื่อให้สิ่งนี้ทำงาน สำหรับการตั้งค่า pipeline ที่ซับซ้อนยิ่งขึ้น Apidog CLI ใน CI/CD pipeline ของคุณ และ การแนะนำ GitHub Actions ก็ครอบคลุมถึง GitLab CI และ Jenkins ด้วย
หมายเหตุเกี่ยวกับ pytest และโลกของการทดสอบ Python ที่กว้างขึ้น
การย้ายออกจาก YAML ของ Tavern ไม่ได้หมายความถึงการทิ้ง pytest ทีมจำนวนมากยังคงรักษาการทดสอบหน่วยและการรวมระบบที่เป็น Python ล้วน ๆ ไว้ใน pytest และใช้ Apidog สำหรับเลเยอร์สัญญา API ซึ่งเป็นส่วนที่การทดสอบควรติดตามสเปกและรันได้สำหรับผู้ที่ไม่ใช่ผู้มีส่วนร่วมใน Python ด้วย ทั้งสองไม่จำเป็นต้องเป็นเอกสิทธิ์ซึ่งกันและกัน คุณค่าของ Tavern คือการทำให้ผู้ใช้ pytest สามารถเขียนการทดสอบ API ในรูปแบบที่เบากว่าโค้ด requests ดิบ; คุณค่าของ Apidog คือการทำให้การทดสอบ API เหล่านั้นติดตามสัญญาและคงความอ่านง่ายเมื่อชุดทดสอบมีขนาดใหญ่ขึ้นเกินกว่าไม่กี่ไฟล์
หากคุณกำลังพิจารณารันเนอร์อื่น ๆ ด้วย ตรรกะเดียวกันนี้ก็ใช้ได้กับเรื่องราวบรรทัดคำสั่งของ Postman ใน Postman CLI vs Newman และการรัน collections โดยไม่มีเครื่องมือเพิ่มเติมใน การทดสอบ API โดยไม่มี Postman
คำถามที่พบบ่อย
Apidog CLI ฟรีหรือไม่? ใช่ แพ็คเกจ apidog-cli npm ฟรีในการติดตั้งและรันด้วย npm install -g apidog-cli มันดำเนินการสถานการณ์ทดสอบจากโปรเจกต์ Apidog ของคุณ ดังนั้นสิ่งที่คุณสามารถรันได้ขึ้นอยู่กับแผน Apidog ของคุณ แต่ตัวรันเนอร์บรรทัดคำสั่งเองไม่ใช่ผลิตภัณฑ์ที่ต้องชำระเงินแยกต่างหาก
ฉันยังสามารถใช้ pytest ควบคู่ไปกับ Apidog ได้หรือไม่? ได้ คุณสามารถรักษาการทดสอบหน่วยและการรวมระบบ Python ของคุณไว้ใน pytest และใช้ Apidog สำหรับเลเยอร์การทดสอบสัญญา API หลายทีมรันทั้งสองอย่าง ความแตกต่างคือการทดสอบ Apidog ติดตามสเปกแทนที่จะฮาร์ดโค้ดในไฟล์แยกต่างหาก
Apidog บล็อกการรวมที่ไม่ถูกต้องใน CI ได้อย่างไร? ผ่านโค้ดออก (exit code) เมื่อมีการยืนยันใดๆ ล้มเหลว apidog run จะออกด้วยโค้ดที่ไม่ใช่ศูนย์ CI จะอ่านโค้ดออกนั้น ทำเครื่องหมายขั้นตอนว่าล้มเหลว และบล็อกการรวมหรือการปรับใช้ คุณไม่จำเป็นต้องกำหนดค่าอะไรเพิ่มเติมเพื่อให้สิ่งนี้ทำงาน
ฉันควรใช้ตัวรายงานใดสำหรับ CI? ใช้ junit สำหรับผลลัพธ์ที่เครื่องอ่านได้ที่แดชบอร์ด CI ของคุณจะแยกวิเคราะห์เป็นต้นไม้ผ่าน/ล้มเหลว และเพิ่ม html หากคุณต้องการรายงานที่สามารถเรียกดูได้ที่จัดเก็บเป็น artifact ทางเลือกที่พบบ่อยคือ -r html,junit โดยยังคงเปิด cli ไว้สำหรับเอาต์พุตบันทึกการสร้างที่อ่านง่าย
Apidog ทดสอบเฉพาะ HTTP เหมือนโหมด HTTP ของ Tavern หรือไม่? ไม่ Apidog ครอบคลุม HTTP บวกกับ SOAP, WebSocket, Server-Sent Events และ gRPC Tavern เพิ่ม MQTT ให้กับ HTTP ซึ่งเป็นจุดเดียวที่การครอบคลุมโปรโตคอลของมันไปในที่ที่ Apidog ไม่ครอบคลุม ดังนั้นโปรดจำไว้ว่าหาก MQTT เป็นศูนย์กลางของ stack ของคุณ
บทสรุปที่ซื่อสัตย์
Tavern เป็นวิธีที่สะอาดในการเขียนการทดสอบ API หากคุณคุ้นเคยกับ pytest และ YAML อยู่แล้ว และการรวม pytest นั้นเป็นคุณสมบัติที่ดีที่สุดของมันอย่างแท้จริง ข้อเสียคือตัว YAML เอง: มันจะลึกซึ้งและเปราะบางขึ้นเมื่อชุดทดสอบมีขนาดใหญ่ขึ้น และไม่มีการเชื่อมโยงกลับไปยังสัญญา API ที่มันตรวจสอบ หากคุณต้องการพฤติกรรมแบบ headless, แจ้งเตือนความล้มเหลวอย่างชัดเจนใน CI โดยไม่ต้องจัดระเบียบ YAML ด้วยมือ และไม่ต้องดูแลสำเนาที่สองของสเปกของคุณ การสร้างการทดสอบกับสัญญาและรันด้วย apidog run เป็นเส้นทางที่ง่ายกว่า
ดาวน์โหลด Apidog และนำเข้า API ที่มีอยู่เพื่อสัมผัสขั้นตอนการทำงานแบบ "สเปกคือการทดสอบ" ก่อนที่คุณจะตัดสินใจ มันฟรีที่จะเริ่มต้น
