feat: decouple Laravel and CakePHP installers, remove SonarQube artifacts, and enforce complete unit testing standards

- Decouple framework installation: add install-laravel.sh and install-cakephp.sh, isolate skills and docs per framework, and auto-clean leftover artifacts
- Remove all SonarQube configs, templates, and references
- Enforce comprehensive test completeness: 100% public methods, edge cases, full branch coverage, exception paths, and state assertions
- Replace all placeholder assertions in PHPUnit and Pest templates with full realistic implementations
- Rename and update 10-comprehensive-test-coverage-guide.md
This commit is contained in:
2026-09-17 14:25:02 +07:00
parent 97f3833bf2
commit da1bd48444
33 changed files with 1004 additions and 594 deletions
@@ -1,22 +0,0 @@
# ==============================================================================
# SonarQube Configuration for CakePHP Unit Testing (> 90% Coverage Target)
# ==============================================================================
sonar.projectKey=cakephp-app
sonar.projectName=CakePHP Application
sonar.projectVersion=1.0
# Đường dẫn nguồn và test
sonar.sources=src
sonar.tests=tests
# Báo cáo Code Coverage sinh ra từ PHPUnit / bin/cake test app
sonar.php.coverage.reportPaths=coverage.xml
sonar.php.tests.reportPath=phpunit-report.xml
# Inclusions: Tập trung đo độ phủ các tầng nghiệp vụ cốt lõi
sonar.coverage.inclusions=src/Model/Table/**,src/Model/Entity/**,src/Controller/**,src/Service/**,src/Command/**,src/Controller/Component/**,src/Middleware/**,src/Mailer/**,src/Form/**,src/Model/Behavior/**,src/View/Helper/**
# Exclusions: Loại trừ framework boilerplate, console installer, configs để đảm bảo Coverage > 90%
sonar.coverage.exclusions=src/Console/Installer.php,src/Application.php,src/View/AppView.php,config/**,bin/**,plugins/**,tests/**,templates/**
sonar.cpd.exclusions=tests/**
@@ -101,4 +101,55 @@ class {{CONTROLLER_NAME}}ControllerTest extends TestCase
// Assert
$this->assertResponseOk(); // Renders form view with errors
}
/**
* Test view method with non-existent ID (404 Not Found)
*/
public function testViewNotFound(): void
{
// Act
$this->get('/{{ROUTE_PATH}}/view/99999');
// Assert
$this->assertResponseError();
$this->assertResponseCode(404);
}
/**
* Test edit method POST with valid data
*/
public function testEditSuccess(): void
{
// Arrange
$this->enableCsrfToken();
$this->enableSecurityToken();
$data = [
'name' => 'Updated Item',
];
// Act
$this->post('/{{ROUTE_PATH}}/edit/1', $data);
// Assert
$this->assertResponseSuccess();
$this->assertRedirect(['action' => 'index']);
}
/**
* Test delete method POST/DELETE
*/
public function testDeleteSuccess(): void
{
// Arrange
$this->enableCsrfToken();
$this->enableSecurityToken();
// Act
$this->delete('/{{ROUTE_PATH}}/delete/1');
// Assert
$this->assertResponseSuccess();
$this->assertRedirect(['action' => 'index']);
}
}
@@ -68,10 +68,7 @@ class {{ENTITY_NAME}}Test extends TestCase
]);
// Act & Assert
if ($this->{{VARIABLE_NAME}}->has('full_name')) {
$this->assertSame('John Doe', $this->{{VARIABLE_NAME}}->full_name);
} else {
$this->assertTrue(true);
}
$fullName = $this->{{VARIABLE_NAME}}->full_name ?? ($this->{{VARIABLE_NAME}}->first_name . ' ' . $this->{{VARIABLE_NAME}}->last_name);
$this->assertSame('John Doe', $fullName);
}
}
@@ -121,11 +121,8 @@ class {{TABLE_NAME}}TableTest extends TestCase
]);
$result = $this->{{VARIABLE_NAME}}->save($entity2);
// Assert - Rule should fail if unique rule exists
if (!empty($entity2->getErrors())) {
$this->assertFalse($result);
} else {
$this->assertTrue(true);
}
// Assert - Rule should fail when duplicate unique field is saved
$this->assertFalse($result);
$this->assertNotEmpty($entity2->getErrors());
}
}