#การรัน Maven Test ด้วย GitHub Actions

GitHub Actions สามารถนำมาใช้สร้าง Continuous Integration (CI) สำหรับโปรเจกต์ Java/Maven เพื่อให้ระบบรันชุดทดสอบอัตโนมัติทุกครั้งที่มีการ push หรือเปิด pull request

แนวคิดหลักคือ เมื่อมีการเปลี่ยนแปลง source code GitHub Actions จะสร้าง runner ขึ้นมา จากนั้น checkout โค้ด ติดตั้ง JDK และสั่ง:

mvn test

หาก Test ผ่าน Workflow จะแสดงสถานะสำเร็จ แต่หาก Test ใดล้มเหลว Workflow จะถูกระบุว่า Failed ทำให้ทีมตรวจพบปัญหาก่อน merge หรือ deploy ได้


#1. ภาพรวมการทำงาน

Workflow พื้นฐานมีลำดับดังนี้:

Developer
   |
   | git push / pull request
   v
GitHub Repository
   |
   v
GitHub Actions
   |
   +--> Checkout Source Code
   |
   +--> Setup JDK
   |
   +--> Restore Maven Cache
   |
   +--> mvn test
            |
            +--> Compile Source
            +--> Compile Test
            +--> Run Tests
                    |
                    +--> PASS -> Workflow Success
                    |
                    +--> FAIL -> Workflow Failed

#2. สิ่งที่ต้องมี

โปรเจกต์ควรเป็น Maven project และมีไฟล์ pom.xml เช่น:

my-project/
├── pom.xml
├── src/
│   ├── main/
│   │   └── java/
│   └── test/
│       └── java/
└── README.md

ตรวจสอบ Maven ในเครื่องได้ด้วย:

mvn -version

และทดลองรัน Test ก่อน:

mvn test

ถ้ารันในเครื่องผ่านแล้ว จึงนำคำสั่งเดียวกันไปใช้บน GitHub Actions


#3. Maven test ทำอะไร

คำสั่ง:

mvn test

จะทำงานตาม Maven lifecycle จนถึง test phase โดยขั้นตอนสำคัญประกอบด้วย:

validate
   ↓
compile
   ↓
test-compile
   ↓
test

ดังนั้น Maven จะ compile source code, compile test code และรัน Unit Test ที่กำหนดไว้ในโปรเจกต์

สำหรับโปรเจกต์ Java มักใช้ร่วมกับ JUnit 5 และ Maven Surefire Plugin


#4. สร้าง GitHub Actions Workflow

สร้าง directory:

.github/workflows/

จากนั้นสร้างไฟล์:

.github/workflows/maven-test.yml

โครงสร้างโปรเจกต์จะเป็น:

my-project/
├── .github/
│   └── workflows/
│       └── maven-test.yml
├── src/
│   ├── main/
│   └── test/
├── pom.xml
└── README.md

#5. Workflow สำหรับรัน mvn test

ใส่เนื้อหาต่อไปนี้ใน maven-test.yml

name: Maven Test

on:
  push:
    branches:
      - main

  pull_request:
    branches:
      - main

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source code
        uses: actions/checkout@v6

      - name: Set up JDK 17
        uses: actions/setup-java@v6
        with:
          distribution: temurin
          java-version: '17'
          cache: maven

      - name: Check Java version
        run: java -version

      - name: Run Maven Tests
        run: mvn --batch-mode test

หมายเหตุ: major version ของ GitHub Actions อาจเปลี่ยนในอนาคต ควรตรวจสอบเวอร์ชันปัจจุบันจาก Marketplace/เอกสารของ Action ก่อนใช้งานใน production


#6. อธิบาย Workflow

#กำหนดชื่อ

name: Maven Test

ชื่อ Workflow ที่จะแสดงในหน้า Actions ของ Repository

#Trigger เมื่อ Push

on:
  push:
    branches:
      - main

หมายความว่า Workflow จะทำงานเมื่อมีการ push เข้า main

#Trigger เมื่อ Pull Request

pull_request:
  branches:
    - main

ช่วยให้ Test ทำงานก่อน merge Pull Request เข้า main

#Runner

runs-on: ubuntu-latest

กำหนดให้ Job ทำงานบน GitHub-hosted Ubuntu runner

#Checkout

- name: Checkout source code
  uses: actions/checkout@v6

นำ source code ของ repository มาไว้ใน runner เพื่อให้ขั้นตอนถัดไปสามารถ build และ test ได้

#Setup Java

- name: Set up JDK 17
  uses: actions/setup-java@v6
  with:
    distribution: temurin
    java-version: '17'
    cache: maven

ติดตั้ง Temurin JDK 17 และเปิด Maven dependency caching

ถ้าโปรเจกต์ใช้ Java 21 สามารถเปลี่ยนเป็น:

java-version: '21'

เวอร์ชัน Java ใน Workflow ควรสอดคล้องกับ pom.xml

#รัน Test

- name: Run Maven Tests
  run: mvn --batch-mode test

--batch-mode เหมาะกับ CI เพราะลด interactive/output ที่ไม่จำเป็นสำหรับ terminal แบบ CI


#7. ใช้ Maven Wrapper

ถ้า repository มี Maven Wrapper:

mvnw
mvnw.cmd
.mvn/

แนะนำให้ใช้ Wrapper เพราะโปรเจกต์สามารถควบคุม Maven version ที่ต้องการได้

บน Linux runner:

- name: Run Maven Tests
  run: ./mvnw --batch-mode test

หากพบ permission error สามารถเพิ่ม:

- name: Make Maven Wrapper executable
  run: chmod +x mvnw

- name: Run Maven Tests
  run: ./mvnw --batch-mode test

บน Windows runner:

- name: Run Maven Tests
  run: .\mvnw.cmd --batch-mode test

#8. Maven Cache

การตั้งค่า:

cache: maven

ช่วย cache dependency ของ Maven ทำให้ workflow รอบถัดไปไม่จำเป็นต้องดาวน์โหลด dependency ใหม่ทั้งหมด

ตัวอย่าง:

- name: Set up JDK 17
  uses: actions/setup-java@v6
  with:
    distribution: temurin
    java-version: '17'
    cache: maven

มีประโยชน์โดยเฉพาะกับโปรเจกต์ที่มี dependency จำนวนมาก


#9. ตัวอย่าง Unit Test ด้วย JUnit 5

สมมติมี class:

public class Calculator {

    public int add(int a, int b) {
        return a + b;
    }
}

สร้าง Test:

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

class CalculatorTest {

    @Test
    void shouldAddTwoNumbers() {
        Calculator calculator = new Calculator();

        int result = calculator.add(10, 20);

        assertEquals(30, result);
    }
}

เมื่อ GitHub Actions สั่ง:

mvn test

JUnit Test จะถูกรันโดยอัตโนมัติ


#10. ตัวอย่างสำหรับ Spring Boot

สำหรับ Spring Boot สามารถมี Test เช่น:

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class ApplicationTests {

    @Test
    void contextLoads() {
    }
}

Workflow สามารถใช้แบบเดิม:

- name: Run Maven Tests
  run: mvn --batch-mode test

หรือ:

- name: Run Maven Tests
  run: ./mvnw --batch-mode test

#11. Push Workflow ขึ้น GitHub

หลังสร้างไฟล์แล้ว:

git add .
git commit -m "ci: add Maven test workflow"
git push origin main

จากนั้นเปิด GitHub Repository และไปที่:

Actions
  ↓
Maven Test
  ↓
test
  ↓
Run Maven Tests

สามารถดู console log และผลการทดสอบได้จากหน้า Workflow Run


#12. เมื่อ Test ไม่ผ่าน

สมมติ Test:

assertEquals(30, calculator.add(10, 20));

แต่ implementation คืนค่าผิด GitHub Actions จะได้รับ exit code ที่ไม่สำเร็จจาก Maven และ Job จะ Failed

แนวทาง CI จึงเป็น:

Push Code
   ↓
Run Tests
   ↓
+------------------+
| Tests Passed ?   |
+------------------+
     |       |
    Yes      No
     |       |
     v       v
 Success   Failed
             |
             v
        Fix Source/Test

#13. mvn test กับ mvn verify

ถ้าต้องการรันเฉพาะ lifecycle ถึง Test:

mvn test

แต่ใน CI ที่ต้องการตรวจสอบ lifecycle ต่อไปจนถึง verification สามารถใช้:

mvn verify

ตัวอย่าง:

- name: Maven Verify
  run: mvn --batch-mode verify

verify จะเดิน Maven lifecycle ต่อจาก test ผ่าน phase เช่น package, integration-test และ verify จึงเหมาะเมื่อโปรเจกต์กำหนด integration tests หรือ quality checks ไว้ใน lifecycle ดังกล่าว


#14. Workflow แบบแนะนำ

หาก repository มี Maven Wrapper:

name: Java CI with Maven

on:
  push:
    branches:
      - main
      - develop

  pull_request:
    branches:
      - main
      - develop

jobs:
  test:
    name: Maven Test
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source code
        uses: actions/checkout@v6

      - name: Set up JDK
        uses: actions/setup-java@v6
        with:
          java-version: '17'
          distribution: temurin
          cache: maven

      - name: Make Maven Wrapper executable
        run: chmod +x mvnw

      - name: Display Java version
        run: java -version

      - name: Run Maven Tests
        run: ./mvnw --batch-mode test

ถ้าไม่มี Maven Wrapper เปลี่ยนขั้นตอนสุดท้ายเป็น:

- name: Run Maven Tests
  run: mvn --batch-mode test

#15. ใช้กับ Branch Protection

หลังจาก Workflow ทำงานได้แล้ว สามารถนำผล CI ไปใช้เป็น Required Status Check ใน branch protection/ruleset ของ GitHub เพื่อกำหนดกระบวนการประมาณนี้:

Feature Branch
      |
      v
Pull Request
      |
      v
Maven Test
      |
  +---+---+
  |       |
PASS     FAIL
  |       |
  v       v
Merge   Fix Code

แนวทางนี้ช่วยป้องกันการ merge การเปลี่ยนแปลงที่ยังไม่ผ่านชุดทดสอบตามเงื่อนไขของ repository


#16. แนวทางที่ควรใช้ในโปรเจกต์จริง

  • รัน Test ทั้ง push และ pull_request
  • ใช้ Maven Wrapper เมื่อ repository รองรับ
  • ใช้ Java version เดียวกับที่โปรเจกต์กำหนด
  • เปิด Maven cache เพื่อลดเวลาการดาวน์โหลด dependency
  • ใช้ --batch-mode สำหรับ CI
  • พิจารณาใช้ mvn verify เมื่อมี Integration Test หรือ verification plugins
  • ตั้ง Required Status Checks สำหรับ branch สำคัญ
  • ไม่เก็บ password, token หรือ credential ไว้ใน YAML โดยตรง ให้ใช้ GitHub Secrets

#สรุป

การนำ Maven Test ไปทำงานบน GitHub Actions เป็นจุดเริ่มต้นของ CI สำหรับ Java และ Spring Boot ที่ทำได้ไม่ซับซ้อน โดย workflow หลักประกอบด้วย:

Checkout
   ↓
Setup Java
   ↓
Maven Cache
   ↓
mvn test
   ↓
JUnit Tests
   ↓
PASS / FAIL

Workflow ขั้นต่ำที่จำเป็นคือ:

name: Maven Test

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v6

      - uses: actions/setup-java@v6
        with:
          distribution: temurin
          java-version: '17'
          cache: maven

      - name: Run Maven Tests
        run: mvn --batch-mode test

เมื่อวางไฟล์นี้ไว้ที่ .github/workflows/maven-test.yml ทุกครั้งที่ push หรือสร้าง Pull Request ตาม branch ที่กำหนด GitHub Actions จะรัน Maven Test ให้อัตโนมัติ ซึ่งช่วยให้ตรวจพบ regression ได้เร็วขึ้นและเป็นพื้นฐานสำหรับต่อยอดไปสู่ build, code quality scan, packaging และ deployment ใน CI/CD pipeline


#เอกสารอ้างอิง