347 lines
12 KiB
PHP
347 lines
12 KiB
PHP
<?php
|
|
/**
|
|
* WebGIS Poverty Mapping - Integration Tests
|
|
* Version: 1.0
|
|
* Description: Test suite for API endpoints
|
|
*/
|
|
|
|
error_reporting(E_ALL);
|
|
ini_set('display_errors', 1);
|
|
|
|
// Simple test framework
|
|
class TestRunner {
|
|
private $passed = 0;
|
|
private $failed = 0;
|
|
private $tests = [];
|
|
|
|
public function test($name, $callback) {
|
|
try {
|
|
$callback();
|
|
$this->passed++;
|
|
$this->tests[] = ['✓', $name];
|
|
} catch (Exception $e) {
|
|
$this->failed++;
|
|
$this->tests[] = ['✗', $name, $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
public function assertEqual($actual, $expected, $message = '') {
|
|
if ($actual !== $expected) {
|
|
throw new Exception($message . " (expected: $expected, got: $actual)");
|
|
}
|
|
}
|
|
|
|
public function assertTrue($value, $message = '') {
|
|
if ($value !== true) {
|
|
throw new Exception($message);
|
|
}
|
|
}
|
|
|
|
public function assertFalse($value, $message = '') {
|
|
if ($value !== false) {
|
|
throw new Exception($message);
|
|
}
|
|
}
|
|
|
|
public function report() {
|
|
echo "\n=== TEST RESULTS ===\n";
|
|
echo "Passed: {$this->passed}\n";
|
|
echo "Failed: {$this->failed}\n";
|
|
echo "Total: " . ($this->passed + $this->failed) . "\n\n";
|
|
|
|
foreach ($this->tests as $test) {
|
|
if (count($test) === 2) {
|
|
echo "{$test[0]} {$test[1]}\n";
|
|
} else {
|
|
echo "{$test[0]} {$test[1]}: {$test[2]}\n";
|
|
}
|
|
}
|
|
|
|
echo "\n";
|
|
return $this->failed === 0;
|
|
}
|
|
}
|
|
|
|
// Database connection for tests
|
|
function getTestConnection() {
|
|
$conn = new mysqli("localhost", "root", "", "webgis_unified");
|
|
if ($conn->connect_error) {
|
|
die("Connection failed: " . $conn->connect_error);
|
|
}
|
|
$conn->set_charset("utf8mb4");
|
|
return $conn;
|
|
}
|
|
|
|
// Initialize test runner
|
|
$runner = new TestRunner();
|
|
|
|
// ============ Database Tests ============
|
|
$runner->test("Database Connection", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$runner->assertTrue($conn !== null, "Database connection failed");
|
|
$conn->close();
|
|
});
|
|
|
|
$runner->test("Table data_unified Exists", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$result = $conn->query("SHOW TABLES LIKE 'data_unified'");
|
|
$runner->assertTrue($result && $result->num_rows > 0, "Table data_unified not found");
|
|
$conn->close();
|
|
});
|
|
|
|
$runner->test("Table audit_log Exists", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$result = $conn->query("SHOW TABLES LIKE 'audit_log'");
|
|
$runner->assertTrue($result && $result->num_rows > 0, "Table audit_log not found");
|
|
$conn->close();
|
|
});
|
|
|
|
$runner->test("Reference Tables Exist", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$tables = ['ref_kondisi_rumah', 'ref_status_bantuan', 'ref_sumber_penghasilan'];
|
|
foreach ($tables as $table) {
|
|
$result = $conn->query("SHOW TABLES LIKE '$table'");
|
|
$runner->assertTrue($result && $result->num_rows > 0, "Table $table not found");
|
|
}
|
|
$conn->close();
|
|
});
|
|
|
|
// ============ Data Insertion Tests ============
|
|
$runner->test("Insert Point Feature", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$sql = "INSERT INTO data_unified (tipe, nama, alamat, latitude, longitude, status)
|
|
VALUES ('point', 'Test Point', 'Jln Test', -0.0554, 109.3494, 'aktif')";
|
|
$runner->assertTrue($conn->query($sql) === TRUE, "Failed to insert point");
|
|
$conn->close();
|
|
});
|
|
|
|
$runner->test("Insert Worship Feature", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$sql = "INSERT INTO data_unified (tipe, nama, jenis, alamat, latitude, longitude,
|
|
radius_meter, kapasitas, status)
|
|
VALUES ('worship', 'Test Masjid', 'Masjid', 'Jln Imam', -0.0554, 109.3494,
|
|
200, 500, 'aktif')";
|
|
$runner->assertTrue($conn->query($sql) === TRUE, "Failed to insert worship");
|
|
$conn->close();
|
|
});
|
|
|
|
$runner->test("Insert Poor House Feature", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$sql = "INSERT INTO data_unified (tipe, nama_kepala_keluarga, alamat, latitude,
|
|
longitude, jumlah_anggota, kondisi_rumah, status)
|
|
VALUES ('poor_house', 'Budi Santoso', 'Jln Cendana', -0.0554, 109.3494,
|
|
5, 'BURUK', 'aktif')";
|
|
$runner->assertTrue($conn->query($sql) === TRUE, "Failed to insert poor_house");
|
|
$conn->close();
|
|
});
|
|
|
|
// ============ Data Retrieval Tests ============
|
|
$runner->test("Retrieve All Features", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$result = $conn->query("SELECT COUNT(*) as count FROM data_unified");
|
|
$row = $result->fetch_assoc();
|
|
$runner->assertTrue($row['count'] >= 0, "Failed to count features");
|
|
$conn->close();
|
|
});
|
|
|
|
$runner->test("Retrieve Worship Features Only", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$result = $conn->query("SELECT * FROM data_unified WHERE tipe = 'worship' LIMIT 1");
|
|
$runner->assertTrue($result !== FALSE, "Failed to retrieve worship features");
|
|
$conn->close();
|
|
});
|
|
|
|
$runner->test("Retrieve Poor House Features Only", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$result = $conn->query("SELECT * FROM data_unified WHERE tipe = 'poor_house' LIMIT 1");
|
|
$runner->assertTrue($result !== FALSE, "Failed to retrieve poor_house features");
|
|
$conn->close();
|
|
});
|
|
|
|
// ============ Data Validation Tests ============
|
|
$runner->test("Validate Required Fields - tipe", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$sql = "INSERT INTO data_unified (nama, alamat) VALUES ('Test', 'Jln Test')";
|
|
$result = $conn->query($sql);
|
|
$runner->assertFalse($result, "Should reject missing tipe");
|
|
$conn->close();
|
|
});
|
|
|
|
$runner->test("Validate Enum Values - tipe", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$sql = "INSERT INTO data_unified (tipe, nama) VALUES ('invalid_type', 'Test')";
|
|
$result = $conn->query($sql);
|
|
$runner->assertFalse($result, "Should reject invalid tipe value");
|
|
$conn->close();
|
|
});
|
|
|
|
// ============ Data Update Tests ============
|
|
$runner->test("Update Feature Data", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
|
|
// Insert test data
|
|
$insert_sql = "INSERT INTO data_unified (tipe, nama, status) VALUES ('point', 'Update Test', 'aktif')";
|
|
if ($conn->query($insert_sql)) {
|
|
$id = $conn->insert_id;
|
|
|
|
// Update the data
|
|
$update_sql = "UPDATE data_unified SET nama = 'Updated Name' WHERE id = $id";
|
|
$result = $conn->query($update_sql);
|
|
$runner->assertTrue($result === TRUE, "Failed to update feature");
|
|
|
|
// Verify update
|
|
$verify_sql = "SELECT nama FROM data_unified WHERE id = $id";
|
|
$verify_result = $conn->query($verify_sql);
|
|
$row = $verify_result->fetch_assoc();
|
|
$runner->assertEqual($row['nama'], 'Updated Name', "Update verification failed");
|
|
}
|
|
$conn->close();
|
|
});
|
|
|
|
// ============ Data Deletion Tests ============
|
|
$runner->test("Soft Delete Feature (Status Change)", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
|
|
// Insert test data
|
|
$insert_sql = "INSERT INTO data_unified (tipe, nama, status) VALUES ('point', 'Delete Test', 'aktif')";
|
|
if ($conn->query($insert_sql)) {
|
|
$id = $conn->insert_id;
|
|
|
|
// Soft delete
|
|
$delete_sql = "UPDATE data_unified SET status = 'nonaktif' WHERE id = $id";
|
|
$result = $conn->query($delete_sql);
|
|
$runner->assertTrue($result === TRUE, "Failed to soft delete");
|
|
|
|
// Verify soft delete
|
|
$verify_sql = "SELECT status FROM data_unified WHERE id = $id";
|
|
$verify_result = $conn->query($verify_sql);
|
|
$row = $verify_result->fetch_assoc();
|
|
$runner->assertEqual($row['status'], 'nonaktif', "Soft delete verification failed");
|
|
}
|
|
$conn->close();
|
|
});
|
|
|
|
$runner->test("Hard Delete Feature", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
|
|
// Insert test data
|
|
$insert_sql = "INSERT INTO data_unified (tipe, nama) VALUES ('point', 'Hard Delete Test')";
|
|
if ($conn->query($insert_sql)) {
|
|
$id = $conn->insert_id;
|
|
|
|
// Hard delete
|
|
$delete_sql = "DELETE FROM data_unified WHERE id = $id";
|
|
$result = $conn->query($delete_sql);
|
|
$runner->assertTrue($result === TRUE, "Failed to hard delete");
|
|
|
|
// Verify hard delete
|
|
$verify_sql = "SELECT COUNT(*) as count FROM data_unified WHERE id = $id";
|
|
$verify_result = $conn->query($verify_sql);
|
|
$row = $verify_result->fetch_assoc();
|
|
$runner->assertEqual($row['count'], 0, "Hard delete verification failed");
|
|
}
|
|
$conn->close();
|
|
});
|
|
|
|
// ============ Audit Trail Tests ============
|
|
$runner->test("Audit Log Table Has Triggers", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
|
|
// Check triggers exist
|
|
$result = $conn->query("SHOW TRIGGERS LIKE 'trg_data_unified%'");
|
|
$runner->assertTrue($result && $result->num_rows > 0, "Triggers not found");
|
|
$conn->close();
|
|
});
|
|
|
|
$runner->test("Audit Log Records Insertions", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
|
|
// Clear audit log
|
|
$conn->query("DELETE FROM audit_log");
|
|
|
|
// Insert test data
|
|
$insert_sql = "INSERT INTO data_unified (tipe, nama) VALUES ('point', 'Audit Test')";
|
|
$conn->query($insert_sql);
|
|
|
|
// Check if audit logged
|
|
$audit_result = $conn->query("SELECT COUNT(*) as count FROM audit_log WHERE action = 'INSERT'");
|
|
$row = $audit_result->fetch_assoc();
|
|
$runner->assertTrue($row['count'] > 0, "Audit trail not recording insertions");
|
|
|
|
$conn->close();
|
|
});
|
|
|
|
// ============ Query Performance Tests ============
|
|
$runner->test("Query Performance - Count Records", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
|
|
$start_time = microtime(true);
|
|
$result = $conn->query("SELECT COUNT(*) FROM data_unified");
|
|
$end_time = microtime(true);
|
|
|
|
$duration = ($end_time - $start_time) * 1000; // milliseconds
|
|
$runner->assertTrue($duration < 1000, "Query too slow: {$duration}ms");
|
|
|
|
$conn->close();
|
|
});
|
|
|
|
$runner->test("Query Performance - Filter by Type", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
|
|
$start_time = microtime(true);
|
|
$result = $conn->query("SELECT * FROM data_unified WHERE tipe = 'worship' LIMIT 100");
|
|
$end_time = microtime(true);
|
|
|
|
$duration = ($end_time - $start_time) * 1000;
|
|
$runner->assertTrue($duration < 1000, "Filter query too slow: {$duration}ms");
|
|
|
|
$conn->close();
|
|
});
|
|
|
|
// ============ Reference Data Tests ============
|
|
$runner->test("Reference Data - Kondisi Rumah", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$result = $conn->query("SELECT COUNT(*) as count FROM ref_kondisi_rumah");
|
|
$row = $result->fetch_assoc();
|
|
$runner->assertTrue($row['count'] === 4, "Kondisi Rumah reference data incomplete");
|
|
$conn->close();
|
|
});
|
|
|
|
$runner->test("Reference Data - Status Bantuan", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$result = $conn->query("SELECT COUNT(*) as count FROM ref_status_bantuan");
|
|
$row = $result->fetch_assoc();
|
|
$runner->assertTrue($row['count'] === 4, "Status Bantuan reference data incomplete");
|
|
$conn->close();
|
|
});
|
|
|
|
$runner->test("Reference Data - Sumber Penghasilan", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$result = $conn->query("SELECT COUNT(*) as count FROM ref_sumber_penghasilan");
|
|
$row = $result->fetch_assoc();
|
|
$runner->assertTrue($row['count'] === 8, "Sumber Penghasilan reference data incomplete");
|
|
$conn->close();
|
|
});
|
|
|
|
// ============ Views Tests ============
|
|
$runner->test("View - v_data_summary Exists", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$result = $conn->query("SELECT * FROM v_data_summary LIMIT 1");
|
|
$runner->assertTrue($result !== FALSE, "View v_data_summary not found");
|
|
$conn->close();
|
|
});
|
|
|
|
$runner->test("View - v_poor_house_analysis Exists", function() use ($runner) {
|
|
$conn = getTestConnection();
|
|
$result = $conn->query("SELECT * FROM v_poor_house_analysis LIMIT 1");
|
|
$runner->assertTrue($result !== FALSE, "View v_poor_house_analysis not found");
|
|
$conn->close();
|
|
});
|
|
|
|
// Display test results
|
|
$success = $runner->report();
|
|
|
|
// Return exit code
|
|
exit($success ? 0 : 1);
|
|
?>
|