SiamCafe.net Blog
Technology

Semgrep SAST Testing Strategy QA

semgrep sast testing strategy qa
Semgrep SAST Testing Strategy QA | SiamCafe Blog
2025-09-11· อ. บอม — SiamCafe.net· 9,075 คำ

Semgrep SAST Testing

Semgrep SAST ช่วย QA ตรวจ Security Bugs ตั้งแต่ Code Review Custom Rules Anti-patterns CI/CD Pipeline ร่วม Unit Tests Integration Tests Quality Gate

Testing Strategy 4 ระดับ Testing Pyramid Unit Integration E2E Manual Semgrep Static Analysis ก่อน Unit Tests

Testing Pyramid กับ Security

# testing_pyramid.py — Testing Pyramid with Security
from dataclasses import dataclass, field
from typing import List, Dict

@dataclass
class TestLevel:
    name: str
    count: str
    speed: str
    scope: str
    tools: List[str]
    security_tools: List[str]

class TestingPyramid:
    """Testing Pyramid with Security Layers"""

    def __init__(self):
        self.levels: List[TestLevel] = []

    def add(self, level: TestLevel):
        self.levels.append(level)

    def show(self):
        print(f"\n{'='*55}")
        print(f"Testing Pyramid + Security")
        print(f"{'='*55}")

        for level in self.levels:
            print(f"\n  [{level.name}]")
            print(f"    Count: {level.count} | Speed: {level.speed}")
            print(f"    Scope: {level.scope}")
            print(f"    Tools: {', '.join(level.tools)}")
            print(f"    Security: {', '.join(level.security_tools)}")

pyramid = TestingPyramid()

levels = [
    TestLevel("Static Analysis (SAST)", "ทุก Commit", "เร็วมาก (วินาที)",
              "โค้ดทั้งหมด ไม่ต้องรัน",
              ["Semgrep", "ESLint", "Pylint"],
              ["Semgrep Security Rules", "gitleaks", "Checkov"]),
    TestLevel("Unit Tests", "มากที่สุด (70%)", "เร็ว (วินาที)",
              "ฟังก์ชันเดียว แยกส่วน",
              ["pytest", "Jest", "JUnit"],
              ["Security Unit Tests", "Input Validation Tests"]),
    TestLevel("Integration Tests", "ปานกลาง (20%)", "ปานกลาง (นาที)",
              "หลายส่วนทำงานร่วมกัน",
              ["pytest", "Testcontainers", "Supertest"],
              ["Auth Integration Tests", "API Security Tests"]),
    TestLevel("E2E Tests", "น้อย (10%)", "ช้า (นาที-ชั่วโมง)",
              "ระบบทั้งหมดจากมุม User",
              ["Playwright", "Cypress", "Selenium"],
              ["OWASP ZAP", "Nuclei", "Security E2E"]),
    TestLevel("Manual/Exploratory", "น้อยที่สุด", "ช้ามาก",
              "หา Edge Cases ที่ Automated ไม่เจอ",
              ["Manual Testing", "Bug Bounty"],
              ["Penetration Testing", "Security Audit"]),
]

for level in levels:
    pyramid.add(level)

pyramid.show()

# QA Metrics
qa_metrics = {
    "Code Coverage": {"target": "> 80%", "tool": "pytest-cov, Istanbul"},
    "Semgrep Findings (ERROR)": {"target": "0", "tool": "Semgrep"},
    "Semgrep Findings (WARNING)": {"target": "< 5", "tool": "Semgrep"},
    "Unit Test Pass Rate": {"target": "100%", "tool": "pytest, Jest"},
    "Integration Test Pass Rate": {"target": "100%", "tool": "Testcontainers"},
    "E2E Test Pass Rate": {"target": "> 95%", "tool": "Playwright"},
    "DAST Findings (Critical)": {"target": "0", "tool": "OWASP ZAP"},
    "Mean Time to Fix (Security)": {"target": "< 48 ชั่วโมง", "tool": "Jira"},
}

print(f"\n\nQA Metrics:")
for metric, info in qa_metrics.items():
    print(f"  {metric}: Target {info['target']} ({info['tool']}")

Semgrep Custom Rules สำหรับ QA

# semgrep_qa_rules.py — Custom Rules for QA

# rules:
#   # Rule 1: ห้ามใช้ print() ใน Production Code
#   - id: no-print-in-production
#     patterns:
#       - pattern: print(...)
#       - pattern-not-inside: |
#           def test_...(...)
#     paths:
#       exclude:
#         - tests/
#         - scripts/
#     message: "Remove print() from production code. Use logging instead."
#     severity: WARNING
#     languages: [python]
#
#   # Rule 2: ต้องมี Error Handling
#   - id: missing-error-handling
#     patterns:
#       - pattern: |
#           requests.get(...)
#       - pattern-not-inside: |
#           try:
#             ...
#     message: "HTTP requests must be wrapped in try/except."
#     severity: WARNING
#     languages: [python]
#
#   # Rule 3: ห้าม Hardcode URLs
#   - id: hardcoded-url
#     pattern: |
#       $VAR = "https://..."
#     message: "Use config or environment variable for URLs."
#     severity: INFO
#     languages: [python]
#
#   # Rule 4: ต้องใช้ Parameterized Queries
#   - id: sql-string-concat
#     patterns:
#       - pattern: |
#           $CURSOR.execute("..." + $VAR + "...")
#     message: "Use parameterized queries to prevent SQL injection."
#     severity: ERROR
#     languages: [python]
#
#   # Rule 5: Test Functions ต้องมี Assert
#   - id: test-without-assert
#     patterns:
#       - pattern: |
#           def test_$NAME(...):
#             ...
#       - pattern-not: |
#           def test_$NAME(...):
#             ...
#             assert ...
#     message: "Test function must contain at least one assert."
#     severity: WARNING
#     languages: [python]

qa_rules = {
    "Security": [
        "no-hardcoded-secrets: ห้าม Hardcode Passwords/API Keys",
        "sql-injection: ต้องใช้ Parameterized Queries",
        "missing-auth: API Endpoints ต้องมี Authentication",
        "insecure-random: ใช้ secrets.token_hex() แทน random()",
    ],
    "Code Quality": [
        "no-print: ห้าม print() ใน Production Code",
        "error-handling: HTTP Requests ต้องมี try/except",
        "hardcoded-url: ห้าม Hardcode URLs",
        "max-complexity: Cognitive Complexity < 15",
    ],
    "Testing": [
        "test-assert: Test Functions ต้องมี Assert",
        "mock-external: ต้อง Mock External Services",
        "test-naming: Test Names ต้องอธิบายสิ่งที่ทดสอบ",
        "no-sleep: ห้ามใช้ time.sleep() ใน Tests",
    ],
}

print("Semgrep Custom Rules for QA:")
for category, rules in qa_rules.items():
    print(f"\n  [{category}]")
    for rule in rules:
        print(f"    - {rule}")

CI/CD Quality Pipeline

# qa_pipeline.py — QA Pipeline with Semgrep

# GitHub Actions — Full QA Pipeline
# name: QA Pipeline
# on: [push, pull_request]
# jobs:
#   static-analysis:
#     runs-on: ubuntu-latest
#     steps:
#       - uses: actions/checkout@v4
#       - name: Semgrep Security Scan
#         uses: returntocorp/semgrep-action@v1
#         with:
#           config: p/security-audit ./custom-rules/
#       - name: Lint
#         run: |
#           pip install ruff
#           ruff check .
#
#   unit-tests:
#     runs-on: ubuntu-latest
#     needs: static-analysis
#     steps:
#       - uses: actions/checkout@v4
#       - name: Run Unit Tests
#         run: |
#           pip install -r requirements.txt
#           pytest tests/unit/ -v --cov=src --cov-report=xml
#       - name: Upload Coverage
#         uses: codecov/codecov-action@v3
#
#   integration-tests:
#     runs-on: ubuntu-latest
#     needs: unit-tests
#     services:
#       postgres:
#         image: postgres:15
#         env:
#           POSTGRES_PASSWORD: test
#     steps:
#       - uses: actions/checkout@v4
#       - name: Run Integration Tests
#         run: pytest tests/integration/ -v
#
#   e2e-tests:
#     runs-on: ubuntu-latest
#     needs: integration-tests
#     steps:
#       - uses: actions/checkout@v4
#       - name: Playwright E2E Tests
#         run: |
#           npx playwright install
#           npx playwright test
#
#   security-gate:
#     runs-on: ubuntu-latest
#     needs: [static-analysis, unit-tests, integration-tests]
#     steps:
#       - name: Check Quality Gate
#         run: |
#           echo "All checks passed - Quality Gate OK"

pipeline_stages = {
    "1. Static Analysis": {
        "tools": "Semgrep, Ruff, ESLint",
        "gate": "0 ERROR findings",
        "duration": "30 วินาที",
    },
    "2. Unit Tests": {
        "tools": "pytest, Jest",
        "gate": "100% pass, Coverage > 80%",
        "duration": "1-3 นาที",
    },
    "3. Integration Tests": {
        "tools": "pytest + Testcontainers",
        "gate": "100% pass",
        "duration": "3-10 นาที",
    },
    "4. E2E Tests": {
        "tools": "Playwright, Cypress",
        "gate": "> 95% pass",
        "duration": "5-15 นาที",
    },
    "5. Security Gate": {
        "tools": "Semgrep + OWASP ZAP",
        "gate": "0 Critical/High findings",
        "duration": "1 นาที",
    },
    "6. Deploy": {
        "tools": "ArgoCD, Flux",
        "gate": "All gates passed",
        "duration": "2-5 นาที",
    },
}

print("QA Pipeline Stages:")
for stage, info in pipeline_stages.items():
    print(f"\n  [{stage}]")
    for key, value in info.items():
        print(f"    {key}: {value}")

Best Practices

Semgrep ใช้กับ QA Testing อย่างไร

ตรวจ Security Bugs ตั้งแต่ Code Review Custom Rules Anti-patterns CI/CD Pipeline ร่วม Unit Tests Integration Tests Quality Gate ไม่ให้โค้ดมีช่องโหว่ผ่าน

Testing Strategy มีกี่ระดับ

4 ระดับ Testing Pyramid Unit Tests มากสุด Integration ปานกลาง E2E น้อย Manual น้อยสุด Semgrep Static Analysis ก่อน Unit Tests

SAST กับ DAST ต่างกันอย่างไร

SAST วิเคราะห์โค้ดไม่ต้องรัน เร็ว ครอบคลุม False Positives DAST ทดสอบแอปที่รัน แม่นยำ ช้า ไม่ครอบคลุม ใช้ทั้งสองร่วมกัน

Quality Gate สำหรับ Security ตั้งอย่างไร

Semgrep ERROR = 0 WARNING < 5 Coverage > 80% Unit Tests ผ่าน Integration Tests ผ่าน ไม่ผ่าน Pipeline Fail ไม่ Deploy Production

สรุป

Semgrep SAST ร่วม QA Testing Strategy Testing Pyramid Static Analysis Unit Integration E2E Custom Rules Quality Gate Security Pipeline SAST DAST Coverage Fix SLA Pre-commit CI/CD

📖 บทความที่เกี่ยวข้อง

Semgrep SAST Multi-cloud Strategyอ่านบทความ → Semgrep SAST Interview Preparationอ่านบทความ → Semgrep SAST DevOps Cultureอ่านบทความ → Semgrep SAST Troubleshooting แก้ปัญหาอ่านบทความ → Semgrep SAST Security Hardening ป้องกันแฮกอ่านบทความ →

📚 ดูบทความทั้งหมด →