feat: add comprehensive unit testing support for CakePHP

- Add 4 CakePHP Claude Code skills: cakephp-unit-test, cakephp-test-setup, cakephp-test-review, cakephp-mock-helper
- Add 11 CakePHP PHPUnit component templates (Table, Entity, Controller, Service, Command, Component, Middleware, Mailer, Form, Behavior, Helper)
- Add CakePHP configs (phpunit.xml.dist, app_local.test.php for SQLite in-memory)
- Add comprehensive CakePHP documentation and component guides
- Update test-runner.sh and installer to auto-detect Laravel and CakePHP
- Add CakePHP CI/CD templates for GitHub Actions and GitLab CI
- Update system prompt, verification checklist, and README with dedicated guides
This commit is contained in:
2026-09-14 10:19:40 +07:00
parent 0dce2ef812
commit 7425b263d5
28 changed files with 2210 additions and 356 deletions
+114 -46
View File
@@ -1,13 +1,12 @@
#!/usr/bin/env bash
# ==============================================================================
# SMARTGIFT AI - LARAVEL UNIT TESTING TOOLKIT INSTALLER
# Cài đặt bộ công cụ Unit Test vào bất kỳ source code Laravel nào mà KHÔNG CẦN clone repo về máy.
# SMARTGIFT AI - MULTI-FRAMEWORK UNIT TESTING TOOLKIT INSTALLER
# Hỗ trợ: Laravel & CakePHP
# Cài đặt bộ công cụ Unit Test vào bất kỳ source code nào mà KHÔNG CẦN clone repo về máy.
#
# Cách dùng 1 (Khuyên dùng - Đứng trong source code Laravel và chạy):
# Cách dùng 1 (Khuyên dùng - Đứng trong source code và chạy):
# curl -fsSL https://raw.githubusercontent.com/<OWNER>/agent-unit-testing/main/install.sh | bash
# Hoặc:
# bash <(curl -fsSL https://raw.githubusercontent.com/<OWNER>/agent-unit-testing/main/install.sh)
#
# Cách dùng 2 (Cài Toàn Cục vào máy):
# curl -fsSL https://raw.githubusercontent.com/<OWNER>/agent-unit-testing/main/install.sh | bash -s -- --global
@@ -23,9 +22,9 @@ CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'
# Remote Repository URL công khai qua HTTPS (ai cũng truy cập được không cần SSH key)
# Remote Repository URL công khai qua HTTPS
DEFAULT_REPO="https://git.smartgift.io.vn/Smartgift-AI/agent-unit-testing.git"
REPO_URL="${LARAVEL_TEST_REPO:-$DEFAULT_REPO}"
REPO_URL="${SG_TEST_REPO:-${LARAVEL_TEST_REPO:-$DEFAULT_REPO}}"
TARGET_DIR=""
GLOBAL_MODE=false
@@ -41,10 +40,10 @@ for arg in "$@"; do
;;
--help|-h)
echo -e "${BLUE}===================================================================${NC}"
echo -e "${CYAN}${BOLD} SMARTGIFT AI: LARAVEL UNIT TESTING TOOLKIT INSTALLER${NC}"
echo -e "${CYAN}${BOLD} SMARTGIFT AI: PHP UNIT TESTING TOOLKIT (LARAVEL & CAKEPHP)${NC}"
echo -e "${BLUE}===================================================================${NC}"
echo -e "Cách dùng:"
echo -e " 1. Cài đặt trực tiếp vào source code Laravel hiện tại:"
echo -e " 1. Cài đặt trực tiếp vào source code hiện tại:"
echo -e " ${YELLOW}curl -fsSL <URL>/install.sh | bash${NC}"
echo -e " 2. Cài đặt vào một source code ở đường dẫn cụ thể:"
echo -e " ${YELLOW}curl -fsSL <URL>/install.sh | bash -s -- /duong-dan/source-code${NC}"
@@ -68,7 +67,7 @@ done
TARGET_DIR="${TARGET_DIR:-.}"
echo -e "${BLUE}===================================================================${NC}"
echo -e "${CYAN}${BOLD} 🚀 SMARTGIFT AI - LARAVEL UNIT TESTING TOOLKIT INSTALLER${NC}"
echo -e "${CYAN}${BOLD} 🚀 SMARTGIFT AI - UNIT TESTING TOOLKIT (LARAVEL & CAKEPHP)${NC}"
echo -e "${BLUE}===================================================================${NC}"
# 1. Tìm hoặc Tải nguồn tài nguyên (Local nếu có, hoặc tải tạm qua Git)
@@ -88,12 +87,8 @@ else
echo -e "${YELLOW}📥 Đang tải bộ công cụ từ remote repository...${NC}"
TMP_DIR="$(mktemp -d 2>/dev/null || mktemp -d -t 'sg_unit_testing')"
# Thử clone qua git
if ! git clone --depth 1 "$REPO_URL" "$TMP_DIR" --quiet 2>/dev/null; then
echo -e "${RED}❌ Không thể clone từ repository: $REPO_URL${NC}"
echo -e "${YELLOW}💡 Lưu ý dành cho người dùng bên ngoài:${NC}"
echo -e " Nếu bạn không phải thành viên có SSH key nội bộ, hãy chạy với URL HTTPS công khai:"
echo -e " ${CYAN}LARAVEL_TEST_REPO=https://github.com/<OWNER>/<REPO>.git curl -fsSL <URL>/install.sh | bash${NC}"
rm -rf "$TMP_DIR"
exit 1
fi
@@ -119,16 +114,18 @@ if [ "$GLOBAL_MODE" = true ]; then
mkdir -p "$HOME/.claude/skills"
cp -R "$PACKAGE_ROOT/.claude/skills/"* "$HOME/.claude/skills/"
mkdir -p "$HOME/.claude/laravel-testing-docs/templates"
cp -R "$PACKAGE_ROOT/docs/"* "$HOME/.claude/laravel-testing-docs/"
cp -R "$PACKAGE_ROOT/rules/"* "$HOME/.claude/laravel-testing-docs/"
cp -R "$PACKAGE_ROOT/templates/"* "$HOME/.claude/laravel-testing-docs/templates/"
mkdir -p "$HOME/.claude/testing-docs/templates"
cp -R "$PACKAGE_ROOT/docs/"* "$HOME/.claude/testing-docs/"
cp -R "$PACKAGE_ROOT/rules/"* "$HOME/.claude/testing-docs/"
cp -R "$PACKAGE_ROOT/templates/"* "$HOME/.claude/testing-docs/templates/"
mkdir -p "$HOME/.local/bin"
# Lệnh khởi tạo test runner
cat << 'EOF' > "$HOME/.local/bin/sg-test-init"
#!/usr/bin/env bash
TARGET_DIR="${1:-.}"
SOURCE_DIR="$HOME/.claude/laravel-testing-docs"
SOURCE_DIR="$HOME/.claude/testing-docs"
if [ ! -d "$TARGET_DIR" ]; then
echo "Lỗi: Thư mục '$TARGET_DIR' không tồn tại!"
@@ -148,16 +145,43 @@ if [ -f "$SOURCE_DIR/templates/setup-dependencies.sh" ]; then
echo " ✓ Đã tạo $TARGET_DIR/setup-test-deps.sh"
fi
echo "🎉 Hoàn tất! Mở Claude Code và gõ: /laravel-unit-test --all --run"
echo "🎉 Hoàn tất! Mở Claude Code và gõ lệnh test tương ứng:"
echo " - CakePHP: /cakephp-unit-test --all --run"
echo " - Laravel: /laravel-unit-test --all --run"
EOF
chmod +x "$HOME/.local/bin/sg-test-init"
cp "$HOME/.local/bin/sg-test-init" "$HOME/.local/bin/laravel-test-init"
chmod +x "$HOME/.local/bin/laravel-test-init"
cp "$HOME/.local/bin/sg-test-init" "$HOME/.local/bin/cakephp-test-init"
chmod +x "$HOME/.local/bin/cakephp-test-init"
# Lệnh cập nhật bộ công cụ (Update)
cat << 'EOF' > "$HOME/.local/bin/sg-test-update"
#!/usr/bin/env bash
REPO_URL="${SG_TEST_REPO:-https://git.smartgift.io.vn/Smartgift-AI/agent-unit-testing.git}"
echo "🔄 Đang cập nhật bộ công cụ Unit Test từ Git repository..."
TMP_DIR="$(mktemp -d 2>/dev/null || mktemp -d -t 'sg_update')"
if git clone --depth 1 "$REPO_URL" "$TMP_DIR" --quiet 2>/dev/null; then
bash "$TMP_DIR/install.sh" --global
rm -rf "$TMP_DIR"
echo "✅ Cập nhật toàn bộ công cụ thành công!"
else
echo "❌ Lỗi: Không thể kết nối hoặc clone repository $REPO_URL"
rm -rf "$TMP_DIR"
exit 1
fi
EOF
chmod +x "$HOME/.local/bin/sg-test-update"
cp "$HOME/.local/bin/sg-test-update" "$HOME/.local/bin/laravel-test-update"
chmod +x "$HOME/.local/bin/laravel-test-update"
cp "$HOME/.local/bin/sg-test-update" "$HOME/.local/bin/cakephp-test-update"
chmod +x "$HOME/.local/bin/cakephp-test-update"
echo -e "${GREEN}${BOLD}✓ CÀI ĐẶT TOÀN CỤC HOÀN TẤT THÀNH CÔNG!${NC}"
echo -e "Kể từ bây giờ, ở bất kỳ source code nào, bạn mở Claude Code là có thể gõ ngay:"
echo -e " • ${CYAN}/laravel-test-setup --install${NC}"
echo -e " • ${CYAN}/laravel-unit-test --all --run${NC}"
echo -e " • CakePHP: ${CYAN}/cakephp-test-setup --install${NC} | ${CYAN}/cakephp-unit-test --all --run${NC}"
echo -e " • Laravel: ${CYAN}/laravel-test-setup --install${NC} | ${CYAN}/laravel-unit-test --all --run${NC}"
echo -e "Và các lệnh terminal: ${CYAN}cakephp-test-init${NC}, ${CYAN}laravel-test-init${NC}, ${CYAN}cakephp-test-update${NC}, ${CYAN}laravel-test-update${NC}"
exit 0
fi
@@ -171,13 +195,20 @@ if [ ! -d "$TARGET_DIR" ]; then
exit 1
fi
if [ ! -f "$TARGET_DIR/artisan" ] && [ ! -f "$TARGET_DIR/composer.json" ]; then
# Kiểm tra xem thư mục có trống hoặc là thư mục mới không
# Phát hiện framework
FRAMEWORK="generic"
if [ -f "$TARGET_DIR/bin/cake" ] || ( [ -f "$TARGET_DIR/composer.json" ] && grep -q '"cakephp/cakephp"' "$TARGET_DIR/composer.json" ); then
FRAMEWORK="cakephp"
echo -e "${GREEN}✓ Phát hiện dự án: CakePHP${NC}"
elif [ -f "$TARGET_DIR/artisan" ] || ( [ -f "$TARGET_DIR/composer.json" ] && grep -q '"laravel/framework"' "$TARGET_DIR/composer.json" ); then
FRAMEWORK="laravel"
echo -e "${GREEN}✓ Phát hiện dự án: Laravel${NC}"
elif [ ! -f "$TARGET_DIR/composer.json" ]; then
FILE_COUNT=$(ls -A "$TARGET_DIR" 2>/dev/null | wc -l | tr -d ' ')
if [ "$FILE_COUNT" -le 2 ]; then
echo -e "${YELLOW}ℹ Thư mục mới/trống: Tự động khởi tạo bộ công cụ Unit Test...${NC}"
elif [ "$FORCE_MODE" = false ]; then
echo -e "${YELLOW}⚠️ Cảnh báo: Thư mục '$TARGET_DIR' đang chứa dữ liệu khác và chưa có file artisan hoặc composer.json.${NC}"
echo -e "${YELLOW}⚠️ Cảnh báo: Thư mục '$TARGET_DIR' đang chứa dữ liệu khác và chưa có file composer.json.${NC}"
echo -e "Nếu bạn vẫn muốn cài đặt vào thư mục này, hãy chạy:"
echo -e " ${CYAN}bash <(curl -fsSL <URL>/install.sh) --force${NC}"
exit 1
@@ -189,7 +220,7 @@ echo -e "📦 Đang cài đặt công cụ vào source code: ${YELLOW}$TARGET_DI
# A. Copy Claude Skills vào .claude/skills/ của source code
mkdir -p "$TARGET_DIR/.claude/skills"
cp -R "$PACKAGE_ROOT/.claude/skills/"* "$TARGET_DIR/.claude/skills/"
echo -e " ${GREEN}✓${NC} Đã cài bộ 4 Claude Code Skills (.claude/skills/)"
echo -e " ${GREEN}✓${NC} Đã cài bộ Claude Code Skills (Laravel & CakePHP)"
# B. Copy cẩm nang tài liệu vào .claude/testing-docs/
mkdir -p "$TARGET_DIR/.claude/testing-docs"
@@ -206,20 +237,21 @@ cp "$PACKAGE_ROOT/templates/setup-dependencies.sh" "$TARGET_DIR/setup-test-deps.
chmod +x "$TARGET_DIR/setup-test-deps.sh"
echo -e " ${GREEN}✓${NC} Đã tạo dependency installer: ./setup-test-deps.sh"
# D. Tự động cấu hình SQLite In-Memory vào phpunit.xml
PHPUNIT_XML="$TARGET_DIR/phpunit.xml"
PHPUNIT_DIST="$TARGET_DIR/phpunit.xml.dist"
TARGET_XML=""
if [ -f "$PHPUNIT_XML" ]; then
TARGET_XML="$PHPUNIT_XML"
elif [ -f "$PHPUNIT_DIST" ]; then
TARGET_XML="$PHPUNIT_DIST"
fi
# D. Cấu hình môi trường an toàn SQLite In-Memory
if [ "$FRAMEWORK" = "laravel" ]; then
PHPUNIT_XML="$TARGET_DIR/phpunit.xml"
PHPUNIT_DIST="$TARGET_DIR/phpunit.xml.dist"
TARGET_XML=""
if [ -f "$PHPUNIT_XML" ]; then
TARGET_XML="$PHPUNIT_XML"
elif [ -f "$PHPUNIT_DIST" ]; then
TARGET_XML="$PHPUNIT_DIST"
fi
if [ -n "$TARGET_XML" ]; then
if ! grep -q 'name="DB_CONNECTION"' "$TARGET_XML" || ! grep -q 'value="sqlite"' "$TARGET_XML"; then
if grep -q '<php>' "$TARGET_XML"; then
sed -i.bak '/<php>/a\
if [ -n "$TARGET_XML" ]; then
if ! grep -q 'name="DB_CONNECTION"' "$TARGET_XML" || ! grep -q 'value="sqlite"' "$TARGET_XML"; then
if grep -q '<php>' "$TARGET_XML"; then
sed -i.bak '/<php>/a\
<env name="DB_CONNECTION" value="sqlite"/>\
<env name="DB_DATABASE" value=":memory:"/>\
<env name="BCRYPT_ROUNDS" value="4"/>\
@@ -227,11 +259,28 @@ if [ -n "$TARGET_XML" ]; then
<env name="QUEUE_CONNECTION" value="sync"/>\
<env name="MAIL_MAILER" value="array"/>
' "$TARGET_XML" 2>/dev/null || true
rm -f "$TARGET_XML.bak" 2>/dev/null || true
echo -e " ${GREEN}✓${NC} Đã cấu hình SQLite in-memory (:memory:) an toàn vào phpunit.xml"
rm -f "$TARGET_XML.bak" 2>/dev/null || true
echo -e " ${GREEN}✓${NC} Đã cấu hình SQLite in-memory (:memory:) an toàn vào phpunit.xml"
fi
else
echo -e " ${GREEN}✓${NC} Cấu hình SQLite in-memory trong phpunit.xml đã chuẩn xác"
fi
fi
elif [ "$FRAMEWORK" = "cakephp" ]; then
# Nếu chưa có phpunit.xml, copy file mẫu
if [ ! -f "$TARGET_DIR/phpunit.xml" ] && [ ! -f "$TARGET_DIR/phpunit.xml.dist" ]; then
cp "$PACKAGE_ROOT/templates/cakephp/configs/phpunit.xml.dist.template" "$TARGET_DIR/phpunit.xml.dist"
echo -e " ${GREEN}✓${NC} Đã tạo phpunit.xml.dist chuẩn cho CakePHP"
else
echo -e " ${GREEN}✓${NC} Cấu hình SQLite in-memory trong phpunit.xml đã chuẩn xác"
echo -e " ${GREEN}✓${NC} Đã phát hiện cấu hình PHPUnit CakePHP"
fi
if [ -f "$TARGET_DIR/config/app_local.php" ]; then
if grep -q "'test'" "$TARGET_DIR/config/app_local.php"; then
echo -e " ${GREEN}✓${NC} Cấu hình Datasources.test trong config/app_local.php đã sẵn sàng"
else
echo -e " ${YELLOW}ℹ${NC} Lưu ý: Hãy đảm bảo Datasources.test trong config/app_local.php sử dụng SQLite :memory:"
fi
fi
fi
@@ -239,7 +288,11 @@ fi
if [ -d "$TARGET_DIR/.git" ]; then
mkdir -p "$TARGET_DIR/.github/workflows"
if [ ! -f "$TARGET_DIR/.github/workflows/unit-tests.yml" ]; then
cp "$PACKAGE_ROOT/templates/ci/github-actions.yml.template" "$TARGET_DIR/.github/workflows/unit-tests.yml"
if [ "$FRAMEWORK" = "cakephp" ]; then
cp "$PACKAGE_ROOT/templates/ci/github-actions-cakephp.yml.template" "$TARGET_DIR/.github/workflows/unit-tests.yml"
else
cp "$PACKAGE_ROOT/templates/ci/github-actions.yml.template" "$TARGET_DIR/.github/workflows/unit-tests.yml"
fi
echo -e " ${GREEN}✓${NC} Đã tạo CI/CD Quality Gate (.github/workflows/unit-tests.yml)"
fi
fi
@@ -248,7 +301,22 @@ echo -e "\n${GREEN}${BOLD}🎉 CÀI ĐẶT HOÀN TẤT THÀNH CÔNG VÀO SOURCE
echo -e "\n${YELLOW}${BOLD}BÂY GIỜ BẠN CÓ THỂ VIẾT UNIT TEST NGAY:${NC}"
echo -e "1. Mở Claude Code tại source code này:"
echo -e " ${CYAN}claude${NC}"
echo -e "2. Gõ 1 lệnh duy nhất để AI viết test toàn bộ và tự chạy test luôn:"
echo -e " ${CYAN}/laravel-unit-test --all --run${NC}"
echo -e "3. Hoặc chạy test trực tiếp từ terminal:"
if [ "$FRAMEWORK" = "cakephp" ]; then
echo -e "2. Gõ lệnh dành riêng cho CakePHP:"
echo -e " - Setup môi trường: ${CYAN}/cakephp-test-setup --install${NC}"
echo -e " - Viết test & chạy test: ${CYAN}/cakephp-unit-test --all --run${NC}"
echo -e " - Hoặc theo tầng: ${CYAN}/cakephp-unit-test src/Model/Table/${NC}"
elif [ "$FRAMEWORK" = "laravel" ]; then
echo -e "2. Gõ lệnh dành riêng cho Laravel:"
echo -e " - Setup môi trường: ${CYAN}/laravel-test-setup --install${NC}"
echo -e " - Viết test & chạy test: ${CYAN}/laravel-unit-test --all --run${NC}"
echo -e " - Hoặc theo tầng: ${CYAN}/laravel-unit-test app/Services/${NC}"
else
echo -e "2. Gõ lệnh tương ứng với framework của bạn:"
echo -e " - CakePHP: ${CYAN}/cakephp-unit-test --all --run${NC}"
echo -e " - Laravel: ${CYAN}/laravel-unit-test --all --run${NC}"
fi
echo -e "3. Chạy test trực tiếp từ terminal bất kỳ lúc nào:"
echo -e " ${CYAN}./test-runner.sh${NC}"