DEV Community

Cover image for Schemathesis คืออะไร? การทดสอบ API แบบ Property-based จาก OpenAPI Spec
Thanawat Wongchai
Thanawat Wongchai

Posted on • Originally published at apidog.com

Schemathesis คืออะไร? การทดสอบ API แบบ Property-based จาก OpenAPI Spec

หากคุณมี OpenAPI หรือ GraphQL schema, Schemathesis สามารถเปลี่ยน schema นั้นให้เป็นชุดทดสอบจำนวนมากได้โดยไม่ต้องเขียน assertion เองทุกเคส เครื่องมือนี้อ่านสเปก สร้างอินพุตตาม constraint ยิงคำขอไปยัง API ที่รันอยู่ และรายงานจุดที่ response ขัดกับสัญญา บทความนี้สรุปวิธีติดตั้ง รัน ใช้งานใน CI และวาง Schemathesis ร่วมกับการทดสอบเชิงฟังก์ชันและ การทดสอบสัญญา (contract testing) ใน Apidog

ลองใช้ Apidog วันนี้

Schemathesis คืออะไร?

Schemathesis เป็นเครื่องมือโอเพนซอร์สบน Python สำหรับสร้างการทดสอบ API จาก schema โดยตรง คุณชี้ไปที่ OpenAPI หรือ GraphQL definition แล้ว Schemathesis จะสร้าง test cases จาก type, format, required field, enum, minimum/maximum และ constraint อื่น ๆ ที่ประกาศไว้ในสเปก

Schemathesis สร้างบน Hypothesis ซึ่งเป็นไลบรารี property-based testing สำหรับ Python และเผยแพร่ภายใต้ใบอนุญาต MIT

Schemathesis demo

หลักการใช้งานคือ:

  1. ใช้ schema เป็น source of truth
  2. สร้าง request จาก schema
  3. ส่ง request ไปยัง API จริง
  4. ตรวจสอบว่า response ตรงกับ schema หรือไม่
  5. รายงานเคสที่ทำให้ API ล่มหรือผิดสัญญา

ตัวอย่างปัญหาที่มักเจอ:

  • API ตอบ 500 จาก input ที่ควรถูกจัดการเป็น 4xx
  • response body ไม่ตรงกับ schema
  • status code ไม่ได้ประกาศไว้ใน OpenAPI
  • content type ไม่ตรงกับที่สเปกระบุ
  • workflow แบบหลายขั้นตอนทำให้ state ผิดพลาด

คุณสามารถรันผ่าน CLI ด้วยคำสั่ง schemathesis run หรือชื่อย่อ st run และถ้าต้องการผูกกับ test suite เดิม ก็สามารถใช้งานร่วมกับ pytest ได้เช่นกัน

Property-Based Testing คืออะไร?

การทดสอบ API แบบทั่วไปมักเป็น example-based testing:

POST /users
Content-Type: application/json

{
  "email": "user@example.com",
  "age": 30
}
Enter fullscreen mode Exit fullscreen mode

จากนั้นคุณ assert response ที่คาดไว้ เช่น 201 Created หรือ field บางตัวใน JSON วิธีนี้ดีสำหรับ business case ที่รู้ล่วงหน้า แต่ครอบคลุมเฉพาะเคสที่คุณเขียนเอง

property-based testing เปลี่ยนจากการเขียนตัวอย่างตายตัวเป็นการนิยาม “คุณสมบัติที่ควรเป็นจริงเสมอ” แล้วให้เครื่องมือสร้าง input จำนวนมากเพื่อหาทางทำลายคุณสมบัตินั้น

สำหรับ Schemathesis property หลักคือ:

request ที่ถูกต้องตาม schema ไม่ควรทำให้ server ล่ม และ response ต้องไม่ละเมิด schema

ตัวอย่างเช่น หาก OpenAPI ระบุว่า field หนึ่งเป็น integer และมี minimum: 1 Schemathesis อาจลองค่าอย่าง:

  • 1
  • ค่าขอบเขต
  • ตัวเลขขนาดใหญ่
  • payload ที่ถูกต้องตาม schema แต่กดดัน validation logic
  • ลำดับ request ที่ทำให้ state ผิดพลาด

เมื่อเจอ failure, Hypothesis จะ “ย่อ” input ให้เล็กที่สุดเท่าที่ทำให้ bug เกิดซ้ำได้ คุณจึงได้ repro case ที่อ่านง่าย ไม่ใช่ payload สุ่มขนาดใหญ่

สิ่งนี้ต่างจาก Monkey Testing เพราะ monkey testing มักโยน input แบบสุ่มเข้าระบบ ส่วน property-based testing ใช้ schema เป็นตัวกำหนดขอบเขต input และรู้ว่าผลลัพธ์ควรสอดคล้องกับอะไร

ติดตั้ง Schemathesis

Schemathesis เป็น Python package ดังนั้นต้องมี Python 3 และ pip

ติดตั้งด้วย:

pip install schemathesis
Enter fullscreen mode Exit fullscreen mode

ตรวจสอบว่า CLI ใช้งานได้:

st --version
Enter fullscreen mode Exit fullscreen mode

หรือ:

schemathesis --version
Enter fullscreen mode Exit fullscreen mode

ถ้าคุณใช้ uv และไม่ต้องการติดตั้งถาวร สามารถรันผ่าน:

uvx schemathesis --version
Enter fullscreen mode Exit fullscreen mode

รัน Schemathesis กับ OpenAPI URL

หาก API ของคุณ expose OpenAPI schema ผ่าน URL เช่น /openapi.json ให้รันได้ทันที:

st run http://127.0.0.1:8000/openapi.json
Enter fullscreen mode Exit fullscreen mode

Schemathesis จะอ่าน schema, ค้นหา operations ทั้งหมด และยิง request ไปยัง server ตาม base URL ที่ระบุใน schema

ถ้าต้องการดู option ทั้งหมดของเวอร์ชันที่ติดตั้ง:

st run --help
Enter fullscreen mode Exit fullscreen mode

ควรตรวจสอบ help ของเวอร์ชันจริงเสมอ เพราะชื่อ flag และค่า default อาจเปลี่ยนระหว่าง major version

รันกับ schema ที่อยู่ในไฟล์

ถ้า schema อยู่ในเครื่อง เช่น openapi.yaml หรือ openapi.json ให้ส่ง path ของไฟล์และกำหนด URL ของ API จริงด้วย --url

st run ./openapi.yaml --url http://127.0.0.1:8000
Enter fullscreen mode Exit fullscreen mode

ตัวอย่างโครงสร้างโปรเจกต์:

my-api/
├── openapi.yaml
├── src/
└── tests/
Enter fullscreen mode Exit fullscreen mode

รันจาก root ของโปรเจกต์:

st run ./openapi.yaml --url http://localhost:3000
Enter fullscreen mode Exit fullscreen mode

รันกับ API ที่ต้องใช้ Authorization

ถ้า API ต้องมี token ให้ส่ง header เข้าไป:

st run http://127.0.0.1:8000/openapi.json \
  --header 'Authorization: Bearer your-token'
Enter fullscreen mode Exit fullscreen mode

หรือถ้าต้องใช้หลาย header:

st run ./openapi.yaml \
  --url http://127.0.0.1:8000 \
  --header 'Authorization: Bearer your-token' \
  --header 'X-Tenant-ID: demo'
Enter fullscreen mode Exit fullscreen mode

แนวทางที่ใช้จริงใน CI คือเก็บ token ใน environment variable:

st run ./openapi.yaml \
  --url "$API_BASE_URL" \
  --header "Authorization: Bearer $API_TOKEN"
Enter fullscreen mode Exit fullscreen mode

อ่านผลลัพธ์จาก Schemathesis

เมื่อเจอ failure, Schemathesis จะพิมพ์ข้อมูลที่ใช้ reproduce ได้ เช่น:

  • HTTP method
  • endpoint
  • query/path/body ที่ส่งไป
  • header ที่เกี่ยวข้อง
  • status code ที่ได้
  • error message
  • response validation error

แนวทางการ debug:

  1. copy request ที่ Schemathesis รายงาน
  2. replay ด้วย curl, Postman, Apidog หรือ client ที่คุณใช้
  3. ตรวจสอบว่า bug อยู่ที่ implementation หรือ schema
  4. แก้ code หรือแก้ OpenAPI spec
  5. รัน st run ซ้ำ

ถ้า response ผิด schema อย่ารีบแก้ test ก่อน ให้เช็กก่อนว่า:

  • schema เก่ากว่า implementation หรือไม่
  • implementation ส่ง field เกิน/ขาดหรือไม่
  • status code นั้นควรถูกเพิ่มใน OpenAPI หรือไม่
  • error response format ถูกประกาศไว้ครบหรือยัง

สิ่งที่ Schemathesis ตรวจจับได้

ปัญหา ลักษณะที่พบ
Server error request ทำให้เกิด 500 แทนที่จะเป็น response ที่จัดการแล้ว เช่น 400
Schema violation response body ไม่ตรงกับ schema ของ status code นั้น
Status code mismatch API ตอบ status code ที่ไม่ได้ประกาศในสเปก
Content-type mismatch response content type ไม่ตรงกับ OpenAPI
Stateful bug endpoint เดี่ยวผ่าน แต่ล้มเหลวเมื่อเรียงเป็น workflow หลายขั้นตอน

ตัวอย่างเช่น API อาจผ่านเมื่อทดสอบ GET /users/{id} อย่างเดียว แต่เมื่อรัน workflow แบบ:

  1. POST /users
  2. PATCH /users/{id}
  3. GET /users/{id}
  4. DELETE /users/{id}

อาจพบว่า state หลัง PATCH ไม่ถูกต้อง หรือ GET ส่ง response ที่ไม่ตรง schema

Schemathesis รองรับ stateful testing โดยอาศัยข้อมูลในสเปก เช่น link ระหว่าง operation เพื่อสร้างลำดับ request แบบ state machine

ปรับแต่งด้วย Hooks

ใน API จริง มักมีเงื่อนไขที่ schema อธิบายได้ไม่ครบ เช่น:

  • ต้องมี tenant เฉพาะ
  • ต้อง login ก่อน
  • field บางตัวต้องสัมพันธ์กับข้อมูลในระบบ
  • endpoint บางกลุ่มยังไม่พร้อมให้ fuzz

Schemathesis มี hooks ซึ่งเป็น Python function สำหรับปรับแต่งพฤติกรรม เช่น:

  • กรอง operation ที่จะทดสอบ
  • ปรับข้อมูลที่ generate
  • เพิ่ม custom checks
  • เพิ่ม header หรือ context เฉพาะระบบ

แนวคิดคือใช้ schema เป็นฐาน แล้วเติม logic ที่จำเป็นสำหรับระบบจริงผ่าน hook แทนการแก้ schema ให้ผิดความหมาย

เพิ่ม Schemathesis เข้า CI

ตัวอย่าง GitHub Actions แบบง่าย:

name: schemathesis

on:
  pull_request:
  push:
    branches:
      - main

jobs:
  api-fuzzing:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install Schemathesis
        run: pip install schemathesis

      - name: Run API server
        run: |
          # แทนที่ด้วยคำสั่ง start API ของโปรเจกต์คุณ
          python -m my_api &
          sleep 5

      - name: Run Schemathesis
        run: |
          st run ./openapi.yaml --url http://127.0.0.1:8000
Enter fullscreen mode Exit fullscreen mode

สำหรับ API ที่ต้องใช้ secret:

      - name: Run Schemathesis
        env:
          API_TOKEN: ${{ secrets.API_TOKEN }}
        run: |
          st run ./openapi.yaml \
            --url http://127.0.0.1:8000 \
            --header "Authorization: Bearer $API_TOKEN"
Enter fullscreen mode Exit fullscreen mode

เริ่มจากรันกับ environment ที่ควบคุมได้ก่อน เช่น local test server หรือ staging ที่ใช้ข้อมูลทดสอบ ไม่ควรยิง fuzzing ใส่ production โดยตรงถ้ายังไม่ได้จำกัด scope และ rate ให้ชัดเจน

ควรใช้ Schemathesis เมื่อใด?

Schemathesis เหมาะเมื่อคุณมี OpenAPI หรือ GraphQL schema ที่ค่อนข้างแม่น และต้องการเพิ่ม coverage สำหรับ edge cases โดยไม่ต้องเขียน test case เองจำนวนมาก

เหมาะเป็นพิเศษเมื่อ:

  • คุณดูแล OpenAPI specification และต้องการตรวจว่า server ทำตามจริง
  • คุณต้องการจับ 500 ที่ไม่ได้จัดการ
  • API มี workflow แบบ stateful
  • ต้องการเพิ่ม fuzzing layer ใน CI
  • ทีมใช้ Python, pip หรือ pytest อยู่แล้ว

ไม่เหมาะถ้า:

  • schema ไม่ละเอียด
  • schema ล้าสมัย
  • response schema ไม่ได้ประกาศ error format ไว้ชัดเจน
  • ต้องการตรวจ business logic เฉพาะเคส เช่น ส่วนลดคำนวณถูกหรือไม่

Schemathesis ไม่ได้แทนที่ functional tests เพราะการรู้ว่า API “ไม่ล่ม” ไม่เท่ากับการรู้ว่า API “คำนวณถูกต้อง” คุณยังต้องมี test แบบ example-based สำหรับ business behavior ที่สำคัญ

Schemathesis และ Apidog: ใช้ร่วมกันอย่างไร

Apidog และ Schemathesis แก้คนละปัญหา

Apidog เป็นแพลตฟอร์มสำหรับออกแบบ ดีบัก ทดสอบ mock และสร้างเอกสาร API ส่วน Schemathesis เป็น property-based fuzzer ที่ใช้ schema เพื่อสร้าง request จำนวนมากและตรวจว่า API ทำตามสัญญาหรือไม่

Apidog ไม่ได้ทำ property-based fuzzing ฟีเจอร์ที่ใกล้เคียงคือ monkey testing ซึ่งส่ง input แบบสุ่มเพื่อหา error แต่ไม่เหมือน Schemathesis ที่ generate input จาก constraint ใน schema และ validate response กลับกับ schema

ตารางนี้ช่วยแบ่งหน้าที่ให้ชัดเจน:

ขั้นตอนของเวิร์กโฟลว์ Schemathesis Apidog
Property-based fuzzing จากสเปก ใช่ เป็นฟีเจอร์หลัก ไม่
ออกแบบ API และแก้ไขสเปกแบบ visual ไม่ ใช่
Functional API testing แบบ example-based จำกัด ใช่
Contract testing เทียบกับสเปก บางส่วน ผ่าน schema validation ใช่ มี workflow เฉพาะ
Mock server จาก schema ไม่ ใช่
CI test runner ใช่ st run ใช่ apidog run
เอกสาร API ที่สร้างอัตโนมัติ ไม่ ใช่

workflow ที่ใช้งานได้จริง:

  1. ออกแบบและดูแล OpenAPI spec ใน Apidog
  2. สร้าง functional test cases สำหรับ business flow หลัก
  3. สร้าง mock server เพื่อให้ frontend หรือ consumer ทดสอบได้เร็วขึ้น
  4. รัน test เหล่านั้นใน CI ด้วย apidog run
  5. เพิ่ม Schemathesis เพื่อ fuzz schema เดียวกัน
  6. ใช้ failure จาก Schemathesis เพื่อแก้ implementation หรือปรับ schema ให้ตรงจริง

ผลลัพธ์คือคุณได้ test สองชั้น:

  • Apidog ตรวจว่า API ทำงานถูกต้องในเคสที่รู้ล่วงหน้า
  • Schemathesis ค้นหา edge cases ที่คุณอาจไม่ได้เขียนเอง

ถ้าเป้าหมายคือเปลี่ยนสเปกให้เป็นชุดทดสอบที่รันได้ ไม่ใช่ fuzzing อย่างเดียว Apidog สามารถ สร้างชุดการทดสอบ API จาก OpenAPI specs ของคุณได้โดยตรง และคุณสามารถ ดาวน์โหลด Apidog เพื่อลอง workflow นี้ได้

คำถามที่พบบ่อย

Schemathesis ฟรีหรือไม่?

ฟรี Schemathesis เป็นโอเพนซอร์สภายใต้ใบอนุญาต MIT และ CLI สามารถติดตั้งได้ด้วย:

pip install schemathesis
Enter fullscreen mode Exit fullscreen mode

เครื่องมือหลักที่ใช้รันในเครื่องหรือใน CI ไม่มีค่าใช้จ่าย นอกจากนี้ยังมีบริการเชิงพาณิชย์แบบโฮสต์สำหรับทีมที่ต้องการประสบการณ์แบบ managed

schemathesis run กับ st run ต่างกันอย่างไร?

ไม่ต่างกัน st เป็นชื่อย่อของ schemathesis

สองคำสั่งนี้ทำงานเหมือนกัน:

schemathesis run ./openapi.yaml --url http://localhost:8000
Enter fullscreen mode Exit fullscreen mode
st run ./openapi.yaml --url http://localhost:8000
Enter fullscreen mode Exit fullscreen mode

ใช้แบบที่ทีมคุณอ่านง่ายและใส่ใน CI ได้สะดวก

Schemathesis แทนที่ functional API tests ได้ไหม?

ไม่ได้ และไม่ควรใช้แทนกัน

Schemathesis ตรวจว่า API ไม่ล่มและ response ไม่ขัดกับ schema แต่ไม่ได้ตรวจ business logic เฉพาะ เช่น:

  • ส่วนลดคำนวณถูกหรือไม่
  • สิทธิ์ผู้ใช้ถูกใช้ตาม policy หรือไม่
  • workflow ทางธุรกิจให้ผลลัพธ์ตรงตาม requirement หรือไม่

สำหรับกรณีเหล่านี้ คุณยังต้องใช้ functional tests และ การทดสอบสัญญา (contract testing) แบบ example-based ซึ่งสามารถสร้างและรันใน Apidog ได้

ให้มอง Schemathesis เป็น fuzzing layer เพิ่มเติม ไม่ใช่ตัวแทน test suite เดิม

Schemathesis ใช้กับ GraphQL ได้หรือไม่?

ได้ Schemathesis รองรับทั้ง OpenAPI และ GraphQL schemas สำหรับ GraphQL เครื่องมือจะสร้าง query จาก type definition ใน schema และตรวจ response ในแนวทางเดียวกับ REST API ที่กำหนดด้วย OpenAPI

บทสรุป

Schemathesis เหมาะสำหรับเพิ่ม property-based fuzzing ให้ API ที่มี OpenAPI หรือ GraphQL schema อยู่แล้ว มันช่วยค้นหา 500, schema mismatch, status code ที่ไม่ได้ประกาศ และ edge cases ที่ test แบบเขียนเองมักพลาด โดยเพิ่มเข้า CI ได้ด้วยคำสั่ง st run

แต่ Schemathesis ไม่ได้ครอบคลุมการออกแบบ API, mock server, เอกสาร, functional tests หรือ business assertions

แนวทางที่ practical คือใช้ Apidog สำหรับออกแบบสเปก สร้าง functional tests, mock และเอกสาร รัน workflow ด้วย apidog run จากนั้นเพิ่ม Schemathesis เพื่อ fuzz schema เดียวกันและค้นหา edge cases เพิ่มเติม

หากต้องการเริ่มจากฝั่งออกแบบและ functional testing ให้ ดาวน์โหลด Apidog แล้วใช้ Schemathesis เป็น fuzzing layer เสริมใน CI

Top comments (0)