Operations 15 min read

How Huolala Built a Scalable Unit Testing Platform with Tekton, SonarQube, and GitLab

This article describes Huolala's journey from a legacy PHP codebase to a Java‑centric microservice architecture, the common misconceptions and difficulties of unit testing, and the design of an automated CI/CD pipeline that integrates Tekton, SonarQube, GitLab Runner, JUnit5, and Mockito to enforce coverage gates and improve code quality.

Huolala Tech
Huolala Tech
Huolala Tech
How Huolala Built a Scalable Unit Testing Platform with Tekton, SonarQube, and GitLab

Background

As Huolala's technology team expanded and migrated its stack from PHP to Java, core business logic grew more complex and code changed frequently, increasing the demand for engineering standards. Because the logistics platform runs 24/7, bugs can cause huge financial loss and brand damage, especially in services that calculate fees and coordinate drivers.

Misconceptions and Challenges of Unit Testing

Why is unit testing often called the "lice on a bald head" yet also the "elephant in the room"? Adding a single test case feels like a burden, but writing thousands of tests and meeting 80% coverage standards seems equally daunting.

Although unit testing has been advocated for years, best practices remain hard to adopt. Common pitfalls include the belief that 100% coverage is required, treating tests only as bug detectors rather than correctness validators, and assuming tests never need to be updated.

Common Misconceptions

Full‑coverage myth: Not every line needs a test; focus on core services.

Goal misunderstanding: Tests verify correctness, especially after refactoring.

One‑time effort fallacy: Tests must evolve with the code.

Key Difficulties

Code coupling: Highly coupled code is hard to test.

Time pressure: Teams view testing as a time sink.

Cost concerns: Maintaining tests can increase development cost.

To unlock the value of unit testing, teams must clarify its purpose, choose appropriate scenarios, and address these challenges.

Unit‑Testing Capability Thinking and Construction

Java provides mature testing frameworks. Using Tekton, we automated CI/CD where unit tests form the first quality gate. SonarQube monitors coverage, and GitLab Merge Requests enforce that every change passes the test suite.

System Overview

Technology Selection

We preferred open‑source solutions and reused existing infrastructure.

Tekton: Cloud‑native pipeline tool used to run unit‑test jobs and collect coverage.

GitLab Runner: Triggers Tekton tasks and evaluates gate results.

SonarQube: Performs static analysis, tracks coverage, and provides a gateway gate.

Test framework: JUnit5 was chosen for its parameterized tests and extensions such as JSON handling.

Mock framework: Mockito offers elegant syntax for mocking container‑type classes and asserting null returns.

Unit‑Test Process

Initial Step

Developers create a feature branch for a new feature or bug fix.

Code Development

All work happens on the feature branch.

After coding, developers compile locally and run unit tests to ensure no obvious defects.

Code Review

Developers push the branch and open a Merge Request (MR).

The MR triggers the unit‑test pipeline; if tests fail, developers fix the code and resubmit.

Merge

Only when all tests pass is the code merged into the release branch, then eventually into the master branch.

Huolala‑Specific Features

Three‑Layer Architecture

Platform Highlights

Pipeline Management: One pipeline runs unit tests and aggregates coverage; another triggers tests and evaluates gate compliance.

Configuration Management: Supports coverage thresholds, pre‑execution scripts, and exclude directories.

Coverage Management: Summarizes reports, tracks new coverage, and updates metrics automatically.

Quality Gate: All unit tests must pass and new‑line coverage must reach 80%.

Platform Implementation

GitLab Pipeline Configuration

filter-job:
  only:
    - merge_requests
  tags:
    - qaci
  stage: test
  image: harbor.xxx.cn/basic/unit-test:latest
  script:
    - python /workspace/trigger.py $CI_COMMIT_REF_NAME $CI_COMMIT_SHORT_SHA $GITLAB_USER_LOGIN $CI_REPOSITORY_URL $CI_PROJECT_NAME master $CI_PROJECT_ID $CI_MERGE_REQUEST_IID
    - python /workspace/filter.py $CI_COMMIT_REF_NAME
only:

Run only on merge‑request events. tags: Use runners labeled qaci. stage: Test stage. script: Executes Python scripts; environment variables are injected by GitLab.

Coverage Collection and Comparison

mvn install -Dmaven.test.failure.ignore=true sonar:sonar \
  -Dsonar.host.url=http://xxxx.huolala.com \
  -Dsonar.login=xxxxx \
  -Dsonar.projectKey=${params.projectKey} \
  -Dsonar.branch.name=${params.revision} \
  -Dsonar.analysis.tektonId=${params.tektonId} \
  -Dsonar.analysis.branch=${params.revision} \
  -Dsonar.branch.target=$TARGET -DskipTests

Additional SonarQube settings control exclusions, target branch, and webhook notifications.

Custom Quality Gate

Standard SonarQube gates ignore low‑volume new code, causing false‑positive passes. We modified the gate to require at least 80% new‑line coverage, preventing accumulation of uncovered code.

String metricKeys = "new_line_coverage,alert_status,bugs,new_bugs,vulnerabilities,code_smells,coverage,new_coverage,new_lines,new_branch_coverage,duplicated_lines_density,duplicated_blocks,projects";
HttpRequest.get(host + "/api/qualitygates/project_status?projectKey=" + sonarProjectKey + "&branch=" + branch)
    .basicAuth(user, password)
    .form("login", user)
    .form("password", password)
    .form("component", sonarProjectKey)
    .form("metricKeys", metricKeys)
    .form("branch", branch)
    .execute().body();

The response is parsed to extract newLineCoverage and compare it against the 80% threshold.

Results and Benefits

Overall Data Overview

Best‑Project Implementation Comparison

Reduced Development Cost

GitLab Test Result Visualization Plugin

Conclusion and Outlook

All components reuse existing platform tools without introducing new services. SonarQube, traditionally used for static analysis, is extended to manage coverage and enforce quality gates. GitLab is leveraged for code management, while MR and GitLab Runner orchestrate the end‑to‑end testing workflow.

Future work includes exploring AI‑driven test generation to reduce the manual effort of writing unit tests and further refining the pipeline for a smoother developer experience.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaci/cdautomationGitLabunit testingSonarQubetekton
Huolala Tech
Written by

Huolala Tech

Technology reshapes logistics

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.