+2

Hướng Dẫn Tính Code Coverage Bằng Kover và Hiển Thị Badge Trên GitHub

Hôm nay, mình sẽ bật mí một bí kíp giúp dự án của bạn trở nên chuyên nghiệp hơn, xịn sò hơn chỉ trong một nốt nhạc!

Bạn sẽ học cách:

  • Tính code coverage bằng Kover,
  • Đẩy kết quả lên Gist bằng GitHub Actions,
  • Hiển thị badge siêu sang chảnh ngay trên README.

Bạn đã sẵn sàng để biến hóa dự án của mình thành một bậc thầy chưa? 🚀 coverage badge Xem cái badge xịn sò này kìa! Với hướng dẫn này, bạn không chỉ biết cách tính code coverage chính xác mà còn có ngay biểu tượng tuyệt vời để khoe thành quả với cả thế giới. Chúng ta cùng bắt đầu chuyến hành trình lập trình đáng nhớ này nhé! 🎉

Giới Thiệu Về Kover

JetBrains Kover là một plugin Gradle với giải pháp tối giản cho việc tính toán độ bao phủ mã cho dự án Kotlin của bạn. Thực tế, trong nhiều trường hợp, nó có thể hoạt động ngay lập tức mà không cần cấu hình phức tạp.

Chỉ cần áp dụng plugin này, và sẽ có một task koverReport mới khả dụng. Khi chạy, nó sẽ tạo ra một báo cáo HTML hoặc XML về độ bao phủ mã mà bạn có thể mở và duyệt qua.

Tuy nhiên, dù hữu ích, cảm giác chinh phục chỉ thực sự bắt đầu khi bạn muốn "đẩy" kết quả này lên một tầm cao mới!

Bước 1: Kover - "Ngôi sao" của chúng ta!

Đầu tiên, chúng ta cần "mời" Kover - "ngôi sao" chính của ngày hôm nay - vào dự án. Mở file libs.versions.toml và thêm đoạn mã sau:

[versions]
...
kover = "0.8.0"
[plugins]
...
kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }

Sau đó, mở build.gradle.kts của module và thêm plugin Kover:

plugins {
   ...
   id(libs.plugins.kover.get().pluginId)
}

Nhìn đơn giản thế thôi nhưng đây là bước quan trọng để Kover cảm nhận yêu thương từ dự án của bạn nhé!

Bước 2: Tạo Task cho Kover - "Kịch bản" hoàn hảo!

Giờ là lúc tạo "kịch bản" cho Kover để tính toán độ bao phủ dòng từ file báo cáo report.xml. Thêm đoạn mã sau vào build.gradle.kts:

tasks.register("printLineCoverage") {
    group = "verification" // Đặt vào cùng nhóm với các task `kover`
    dependsOn("koverXmlReport")
    doLast {
        val report = file("$projectDir/build/reports/kover/report.xml")

        // Đọc file XML và lấy giá trị coverage
        val doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(report)
        val rootNode = doc.firstChild
        var childNode = rootNode.firstChild

        var coveragePercent = 0.0

        while (childNode != null) {
            if (childNode.nodeName == "counter") {
                val typeAttr = childNode.attributes.getNamedItem("type")
                if (typeAttr.textContent == "LINE") {
                    val missedAttr = childNode.attributes.getNamedItem("missed")
                    val coveredAttr = childNode.attributes.getNamedItem("covered")

                    val missed = missedAttr.textContent.toLong()
                    val covered = coveredAttr.textContent.toLong()

                    coveragePercent = (covered * 100.0) / (missed + covered)

                    break
                }
            }
            childNode = childNode.nextSibling
        }

        println("%.1f".format(coveragePercent))
    }
}

Nôm na là task này sẽ đọc file report.xml, tìm số dòng code đã được và chưa được bao phủ, rồi tính toán phần trăm cho bạn.

Bước 3: Gist - "Sân khấu" cho Kover tỏa sáng!

Giờ chúng ta cần dọn sẵn "sân khấu" cho kết quả của Kover. Gists của GitHub chính là sân khấu hoàn hảo!

  1. Truy cập vào Gists.

  2. Tạo một Gist mới với một file JSON. Bạn có thể đặt tên file là <yourproject>-coverage-badge.json. Nhớ lưu lại ID của Gist từ URL, vì bạn sẽ cần dùng nó sau.

  3. Ghi đại vào file một đoạn text như TEMPORARY_TEXT chẳng hạn, đừng lo lắng nội dung lúc này vì sẽ được cập nhật tự động sau.

    image.png

Bước 4: Personal Access Token - "Vé VIP" để Kover "lên sân khấu"!

Để cập nhật Gist bằng GitHub Action, bạn cần một "vé VIP" đặc biệt - Personal Access Token (PAT).

  1. Truy cập vào GitHub Settings.
  2. Tạo một token mới với quyền gist.
  3. Lưu token này vào GitHub Secret của repository với tên key là GH_GIST_TOKEN.

Bước 5: GitHub Action - "Biên đạo" cho Kover "biểu diễn" hoàn hảo!

Lần này đến bước "siêu tự động hóa"! Tạo một GitHub Action để mỗi khi bạn push code vào nhánh main, action này sẽ tính toán code coverage và cập nhật kết quả lên Gist. Tạo file .github/workflows/coverage-badge.yml với nội dung sau:

name: Tạo Badge cho Code Coverage

on:
  push: 
    branches: [ main ] # Chạy khi bạn push code vào nhánh `main`

env:
  JAVA_VERSION: '17'

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4 # Checkout project

      - name: Setup Java # Thiết lập môi trường Java
        uses: actions/setup-java@v4
        with:
          java-version: ${{ env.JAVA_VERSION }}
          distribution: 'temurin'

      - name: Grant execute permission for gradlew # Cấp quyền thực thi cho gradlew
        run: chmod +x gradlew

      - name: Generate coverage output # Tạo kết quả coverage
        run: |
          COVERAGE=$(./gradlew -q printLineCoverage | tail -n 1)
          echo "COVERAGE=$COVERAGE" >> $GITHUB_ENV

      - name: Update dynamic badge gist # Cập nhật biểu tượng badge trong Gist
        uses: schneegans/dynamic-badges-action@v1.7.0
        with:
          auth: ${{secrets.GH_GIST_TOKEN}}
          gistID: <Your Gist ID>
          filename: <yourproject>-coverage-badge.json
          label: coverage
          message: ${{env.COVERAGE}}%
          valColorRange: ${{env.COVERAGE}}
          minColorRange: 0
          maxColorRange: 100

Nhớ thay <Your Gist ID> và tên file yourproject bằng thông tin thật của bạn nhé.

Bước 6: Thêm Badge vào README - "Khoe" thành quả!

Giờ thì ta hãy khoe thành quả nào! Thêm đoạn mã sau vào file README.md để hiển thị badge kết quả code coverage:

![coverage badge](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/<userId>/<gits id>/raw/<file_gits_name>.json)

Đừng quên thay <userId>, <gits id><file_gits_name> bằng giá trị của bạn từ Gist.

Kết quả:

Vậy là xong! Giờ đây mỗi khi bạn push code mới lên nhánh main, GitHub Action sẽ tự động tính toán code coverage, cập nhật kết quả lên Gist và hiển thị badge trên README của bạn. Tự động hóa và chuyên nghiệp chưa nào?

Lưu ý:

Bạn có thể tùy chỉnh màu sắc của badge bằng cách thay đổi valColorRange, minColorRangemaxColorRange trong file coverage-badge.yml.

Hãy thử nghiệm và điều chỉnh các bước trên để phù hợp với dự án của bạn. Chúc bạn thành công!

Khám Phá Thêm

Nếu bạn muốn xem ở một dự án thực tế? Hãy khám phá ngay repository open-sources của mình: blockfrost-kotlin-sdk.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí