projek_padi/TESTING_GUIDE.md

13 KiB

🧪 Testing Guide - Classification System Integration

📋 Pre-Testing Checklist

Server Status

  • Laravel server running (php artisan serve --port=8000)
  • Python API running (python api_server.py on port 5000)
  • Database migrations done (php artisan migrate)
  • Flutter pubspec packages updated (flutter pub get)

Network Configuration

  • Python API accessible from Laravel: http://127.0.0.1:5000
  • Laravel API accessible from mobile: http://10.0.2.2:8000 (emulator) or http://192.168.x.x:8000 (device)
  • Mobile device/emulator has internet access

Environment

  • .env configured with database credentials
  • storage/app/public directory writable
  • Model file loaded in Python API

🖥️ Backend Testing (Laravel + Python)

Test 1: Connection Test

By Postman/curl

curl -X GET http://127.0.0.1:8000/api/classification/test

Expected Response

{
  "success": true,
  "message": "Koneksi ke model API berhasil",
  "model_info": {
    "model": "TensorFlow CNN Model",
    "classes": ["Bacterialblight", "Brownspot", "Leafsmut"]
  }
}

What's Being Tested

  • ✓ Laravel server responding
  • ✓ Connection to Python API server
  • ✓ Model loaded in Python

Test 2: Single Classification (No Save)

By Postman

  1. Open Postman
  2. Create POST request to http://127.0.0.1:8000/api/classification/classify
  3. Go to Bodyform-data
  4. Add key image → select rice leaf image
  5. Click Send

By curl

curl -X POST http://127.0.0.1:8000/api/classification/classify \
  -F "image=@/path/to/rice_leaf.jpg"

Expected Response

{
  "success": true,
  "data": {
    "predicted_class": "Bacterialblight",
    "confidence": "95.23%",
    "disease_info": {
      "name": "Bercak Bakteri",
      "severity": "Sedang hingga Tinggi",
      "symptoms": "...",
      "treatments": ["..."]
    },
    "timestamp": "2026-03-09T10:30:00"
  }
}

What's Being Tested

  • ✓ Image upload functionality
  • ✓ Image preprocessing in Python
  • ✓ TensorFlow model prediction
  • ✓ JSON response formatting
  • ✗ Database save (intentionally not saved)

Test 3: Classification with Save

By Postman

  1. Create POST request to http://127.0.0.1:8000/api/classification/classify-and-save
  2. Go to Bodyform-data
  3. Add key image → select rice leaf image
  4. Add key notes → enter "Initial test classification"
  5. Click Send

By curl

curl -X POST http://127.0.0.1:8000/api/classification/classify-and-save \
  -F "image=@/path/to/rice_leaf.jpg" \
  -F "notes=Initial test classification"

Expected Response

{
  "success": true,
  "data": {
    "predicted_class": "Bacterialblight",
    "confidence": "95.23%",
    "disease_info": {...}
  }
}

Verify Database Save (Tinker)

php artisan tinker

>>> DB::table('classifications')->count()
1

>>> DB::table('classifications')->latest()->first()
{
  "id": 1,
  "image_path": "classifications/2026_03_09_...",
  "filename": "rice_leaf.jpg",
  "predicted_class": "Bacterialblight",
  "confidence": 0.9523,
  "all_predictions": "[...]",
  "disease_name": "Bercak Bakteri",
  "severity": "Sedang hingga Tinggi",
  "notes": "Initial test classification",
  "created_at": "2026-03-09 10:30:00",
  "updated_at": "2026-03-09 10:30:00"
}

What's Being Tested

  • ✓ Image upload
  • ✓ Model prediction
  • Database save (new in Phase 5!)
  • ✓ Image file storage
  • ✓ JSON all_predictions storage

Test 4: Get All Classifications

By curl

curl -X GET "http://127.0.0.1:8000/api/classifications?page=1"

By Browser

http://127.0.0.1:8000/api/classifications?page=1

Expected Response

{
  "success": true,
  "data": {
    "data": [
      {
        "id": 1,
        "image_path": "classifications/...",
        "filename": "rice_leaf.jpg",
        "predicted_class": "Bacterialblight",
        "confidence": 0.9523,
        "disease_name": "Bercak Bakteri",
        "severity": "Sedang hingga Tinggi",
        "notes": "Initial test classification",
        "created_at": "2026-03-09T10:30:00Z"
      }
    ],
    "current_page": 1,
    "total": 1,
    "per_page": 15,
    "last_page": 1
  }
}

What's Being Tested

  • ✓ Pagination
  • ✓ Data retrieval from database
  • ✓ JSON response with all fields

Test 5: Get Classification Detail

By curl

curl -X GET http://127.0.0.1:8000/api/classifications/1

Expected Response

{
  "success": true,
  "data": {
    "id": 1,
    "image_path": "classifications/...",
    "filename": "rice_leaf.jpg",
    "predicted_class": "Bacterialblight",
    "confidence": 0.9523,
    "all_predictions": {
      "Bacterialblight": 0.9523,
      "Brownspot": 0.0350,
      "Leafsmut": 0.0127
    },
    "disease_name": "Bercak Bakteri",
    "severity": "Sedang hingga Tinggi",
    "notes": "Initial test classification",
    "created_at": "2026-03-09T10:30:00Z",
    "updated_at": "2026-03-09T10:30:00Z"
  }
}

What's Being Tested

  • ✓ Detail retrieval by ID
  • ✓ JSON array decoding for all_predictions
  • ✓ Timestamp formatting

Test 6: Get Statistics

By curl

curl -X GET http://127.0.0.1:8000/api/classifications/stats/summary

Expected Response

{
  "success": true,
  "data": {
    "total_classifications": 1,
    "average_confidence": "95.23%",
    "by_disease": [
      {
        "disease_name": "Bercak Bakteri",
        "count": 1
      }
    ]
  }
}

What's Being Tested

  • ✓ Aggregation queries
  • ✓ Statistical calculations
  • ✓ Grouping by disease

Test 7: Delete Classification

By curl

curl -X DELETE http://127.0.0.1:8000/api/classifications/1

Expected Response

{
  "success": true,
  "message": "Classification deleted successfully"
}

Verify Delete

php artisan tinker

>>> DB::table('classifications')->count()
0

>>> file_exists(storage_path('app/public/classifications/...'))
false  // Image should also be deleted

What's Being Tested

  • ✓ Database record deletion
  • ✓ Image file cleanup
  • ✓ Cascade delete

📱 Mobile Testing (Flutter)

Setup

  1. Update API URL in classification_service.dart

    // For Android emulator
    static const String baseUrl = 'http://10.0.2.2:8000/api/classification';
    
    // For physical device (replace with your computer IP)
    static const String baseUrl = 'http://192.168.1.100:8000/api/classification';
    
  2. Ensure Flutter dependencies installed

    cd d:\PROJECT TA\mobile_TA\padi_app
    flutter pub get
    
  3. Run Flutter app

    flutter run
    

Test 1: App Startup

Steps

  1. Run flutter run
  2. Wait for app to build and launch
  3. Should see SplashScreen → MainNavigation

Expected

  • ✓ App starts without crashes
  • ✓ Navigation loads correctly
  • ✓ Bottom tabs visible

What's Being Tested

  • ✓ Flutter build success
  • ✓ Navigation routing
  • ✓ UI rendering

Test 2: Image Picker

Steps

  1. Navigate to Klasifikasi tab
  2. Click on image container or camera button
  3. Choose Camera or Gallery
  4. Select/take a rice leaf photo

Expected

  • ✓ Image picker opens
  • ✓ Permission dialog appears (first time)
  • ✓ Image selected shows in UI

What's Being Tested

  • ✓ Image picker plugin
  • ✓ Permission handling
  • ✓ Image display in UI

Test 3: Classification Request

Steps

  1. Select a rice leaf image
  2. Click "Klasifikasikan" button
  3. Wait for loading spinner
  4. Should receive results or error

Expected Success

Disease: Bercak Bakteri
Confidence: 95.23%
Severity: Sedang hingga Tinggi
Loading indicator disappears
Result screen shows data

Expected Errors (should handle gracefully)

  • Network timeout → "Koneksi timeout"
  • Connection refused → "Server tidak dihubungi"
  • Image validation → "Gambar tidak valid"

What's Being Tested

  • ✓ API request from mobile
  • ✓ Error handling
  • ✓ Loading state management
  • ✓ Response parsing
  • ✓ Navigation to result screen

Test 4: Result Display

Steps

  1. After classification completes
  2. Verify result screen shows:
    • Disease name
    • Confidence percentage with bar
    • Severity badge
    • Symptoms list
    • Treatments list
    • Disease description

Expected

  • ✓ All fields populated correctly
  • ✓ Confidence bar displays correctly
  • ✓ Info readable and formatted well

What's Being Tested

  • ✓ UI rendering of API response
  • ✓ Data parsing and formatting
  • ✓ Conditional rendering

Test 5: Error Handling

Scenario 1: No Internet

  1. Turn off WiFi/mobile data
  2. Try classification
  3. Should see error message

Scenario 2: Server Down

  1. Stop Python/Laravel server
  2. Try classification
  3. Should see timeout or connection error

Scenario 3: Invalid Image

  1. Select a non-image file (if possible)
  2. Try to classify
  3. Should see validation error

What's Being Tested

  • ✓ Network error handling
  • ✓ Timeout handling
  • ✓ Exception catching
  • ✓ User feedback

🔄 Integration Test

Full Workflow Test

  1. Start all servers

    # Terminal 1: PHP
    cd d:\PROJECT TA\web_TA
    php artisan serve --port=8000
    
    # Terminal 2: Python (in dataset folder)
    python api_server.py
    
    # Terminal 3: Flutter
    cd d:\PROJECT TA\mobile_TA\padi_app
    flutter run
    
  2. Test flow

    • Open app → Klasifikasi tab
    • Pick rice leaf image
    • Click "Klasifikasikan"
    • Wait for result
    • Verify result displays correctly
  3. Verify database

    php artisan tinker
    >>> App\Models\Classification::latest()->first()
    
  4. Check stored files

    dir d:\PROJECT TA\web_TA\storage\app\public\classifications
    

All Tests Checklist

Backend (Laravel + Python)

  • Test 1: Connection test passes
  • Test 2: Single classification works
  • Test 3: Save to database works
  • Test 4: List all classifications works
  • Test 5: Get detail works
  • Test 6: Statistics endpoint works
  • Test 7: Delete + cleanup works

Mobile (Flutter)

  • Test 1: App starts successfully
  • Test 2: Image picker opens
  • Test 3: Classification request works
  • Test 4: Results display correctly
  • Test 5: Error handling works

Integration

  • Full workflow end-to-end
  • Database saves when classifying from mobile
  • Can retrieve history from mobile?
  • Statistics reflect classified images

🐛 Troubleshooting

Error: Connection Refused (Python API)

Error: Failed to connect to 127.0.0.1:5000

Solution:

  1. Check Python API running: python api_server.py
  2. Verify port 5000 not blocked
  3. Check firewall settings

Error: Connection Refused (Laravel API)

Error: Failed to connect to 127.0.0.1:8000

Solution:

  1. Check Laravel running: php artisan serve --port=8000
  2. Verify database connected: php artisan migrate
  3. Check .env database credentials

Error: CORS Error on Mobile

Error: CORS policy: No 'Access-Control-Allow-Origin' header

Solution:

  1. Check python api_server.py has CORS enabled
  2. Verify requests from correct origin IP (not localhost for emulator)
  3. Update API URL in Flutter service

Error: Database Migration Failed

Error: SQLSTATE[HY000]: General error

Solution:

  1. Reset migrations: php artisan migrate:rollback
  2. Drop and recreate database
  3. Run migrations again: php artisan migrate

Error: File Not Saved

Storage path not writable

Solution:

chmod -R 775 storage/
chmod -R 775 bootstrap/cache/

📊 Test Results Template

## Test Session: [Date/Time]

### Environment
- Laravel Version: ___
- PHP Version: ___
- Python Version: ___
- Database: ___
- Flutter/Dart Version: ___

### Backend Tests
| Test | Result | Duration | Notes |
|------|--------|----------|-------|
| Connection Test | ✓/✗ | __ ms | ___ |
| Classify Only | ✓/✗ | __ ms | ___ |
| Classify & Save | ✓/✗ | __ ms | ___ |
| Get All | ✓/✗ | __ ms | ___ |
| Get Detail | ✓/✗ | __ ms | ___ |
| Get Stats | ✓/✗ | __ ms | ___ |
| Delete | ✓/✗ | __ ms | ___ |

### Mobile Tests
| Test | Result | Duration | Notes |
|------|--------|----------|-------|
| App Startup | ✓/✗ | __ sec | ___ |
| Image Picker | ✓/✗ | __ sec | ___ |
| Classification | ✓/✗ | __ sec | ___ |
| Result Display | ✓/✗ | __ sec | ___ |
| Error Handling | ✓/✗ | __ sec | ___ |

### Issues Found
1. [Issue] → Fix: [Solution]
2. [Issue] → Fix: [Solution]

### Performance Notes
- Average classification time: __ ms
- Average database save time: __ ms
- Mobile response time: __ sec

### Sign-off
Tester: ___ | Date: ___ | Status: ___