Build and Test

This page explains how to build Fess, run tests, and create distribution packages.

Build System Overview

Fess uses Maven as its build tool. Maven automates dependency management, compilation, testing, and packaging.

pom.xml

This is Maven’s configuration file, located in the project root directory.

Main configuration contents:

  • Project information (groupId, artifactId, version)

  • Dependency libraries

  • Build plugins

  • Profiles

Basic Build Commands

Clean Build

Remove build artifacts and rebuild:

mvn clean compile

Creating Packages

Create a WAR file and distribution zip package:

mvn package

Artifacts are generated in the target/ directory:

target/
├── fess.war
└── releases/
    └── fess-{version}.zip

Full Build

Execute all: clean, compile, test, and package:

mvn clean package

Downloading Dependencies

Download dependency libraries:

mvn dependency:resolve

Downloading OpenSearch Plugins

Download OpenSearch and required plugins:

mvn antrun:run

Note

Execute this command when setting up the development environment or when updating plugins.

Testing

Fess uses JUnit for implementing tests.

Running Unit Tests

Running All Unit Tests

mvn test

Running Specific Test Classes

mvn test -Dtest=SearchServiceTest

Running Specific Test Methods

mvn test -Dtest=SearchServiceTest#testSearch

Running Multiple Test Classes

mvn test -Dtest=SearchServiceTest,CrawlerTest

Skipping Tests

To build without running tests:

mvn package -DskipTests

Warning

Do not skip tests during development. Before creating a PR, ensure all tests pass.

Running Integration Tests

Integration tests require the integrationTests profile. A running Fess server and OpenSearch are required:

mvn test -P integrationTests \
    -Dtest.fess.url="http://localhost:8080" \
    -Dtest.search_engine.url="http://localhost:9201"

Note

Integration test classes use the *Tests.java naming pattern (unit tests use *Test.java).

Writing Tests

Creating Unit Tests

Test Class Placement

Place test classes under src/test/java/. Use the same package structure as the main code.

src/
├── main/java/org/codelibs/fess/app/service/SearchService.java
└── test/java/org/codelibs/fess/app/service/SearchServiceTest.java

Basic Test Class Structure

package org.codelibs.fess.app.service;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class SearchServiceTest {

    @Test
    public void testSearch() {
        // Given: Test preconditions
        SearchService service = new SearchService();
        String query = "test";

        // When: Execute test target
        SearchResponse response = service.search(query);

        // Then: Verify results
        assertNotNull(response);
        assertTrue(response.getResultCount() > 0);
    }
}

Test Lifecycle

import org.junit.jupiter.api.*;

public class MyServiceTest {

    @BeforeAll
    static void setUpClass() {
        // Execute once before all tests
    }

    @BeforeEach
    void setUp() {
        // Execute before each test
    }

    @Test
    void testSomething() {
        // Test
    }

    @AfterEach
    void tearDown() {
        // Execute after each test
    }

    @AfterAll
    static void tearDownClass() {
        // Execute once after all tests
    }
}

Assertions

Use JUnit 5 assertions:

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

// Equality
assertEquals(expected, actual);
assertNotEquals(unexpected, actual);

// null check
assertNull(obj);
assertNotNull(obj);

// Boolean
assertTrue(condition);
assertFalse(condition);

// Exception
assertThrows(IllegalArgumentException.class, () -> {
    service.doSomething();
});

// Collection
assertIterableEquals(expectedList, actualList);

Test Coverage

Measure test coverage with JaCoCo:

mvn clean test jacoco:report

The report is generated at target/site/jacoco/index.html.

Code Formatting

Fess uses the following tools to maintain code quality.

Code Formatter

Unify coding style:

mvn formatter:format

License Headers

Add license headers to source files:

mvn license:format

Pre-commit Checks

Run both before committing:

mvn formatter:format
mvn license:format

Creating Distribution Packages

Creating zip Packages

Create a zip package for distribution:

mvn clean package

Generated artifacts:

target/releases/
└── fess-{version}.zip

Creating RPM Packages

mvn rpm:rpm

Creating DEB Packages

mvn jdeb:jdeb

Profiles

Maven profiles allow you to switch between test types.

build (default)

The default profile. Runs unit tests (*Test.java):

mvn package

integrationTests

Profile for running integration tests (*Tests.java):

mvn test -P integrationTests \
    -Dtest.fess.url="http://localhost:8080" \
    -Dtest.search_engine.url="http://localhost:9201"

CI/CD

Fess uses GitHub Actions for CI/CD.

GitHub Actions

Configuration files are in the .github/workflows/ directory.

Automatically executed checks:

  • Build

  • Unit tests

  • Package creation

Local CI Checks

Before creating a PR, you can run checks similar to CI locally:

mvn clean package

Troubleshooting

Build Errors

Error: Failed to download dependencies

# Clear Maven local repository
rm -rf ~/.m2/repository
mvn clean compile

Error: Out of memory

# Increase Maven memory
export MAVEN_OPTS="-Xmx2g"
mvn clean package

Error: Java version is old

Use Java 21 or later:

java -version

Test Errors

Tests timeout

Extend test timeout:

mvn test -Dmaven.test.timeout=600

OpenSearch won’t start

Check ports and change if in use:

lsof -i :9201

Dependency Issues

Dependency conflicts

Check dependency tree:

mvn dependency:tree

Exclude specific dependencies:

<dependency>
    <groupId>org.example</groupId>
    <artifactId>example-lib</artifactId>
    <version>1.0</version>
    <exclusions>
        <exclusion>
            <groupId>conflicting-lib</groupId>
            <artifactId>conflicting-lib</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Build Best Practices

Regular Clean Builds

Regularly perform clean builds to avoid build cache issues:

mvn clean package

Running Tests

Always run tests before committing:

mvn test

Running Code Formatting

Run code formatting before creating a PR:

mvn formatter:format
mvn license:format

Updating Dependencies

Regularly update dependencies:

mvn versions:display-dependency-updates

Leveraging Build Cache

Leverage Maven cache to reduce build time:

# Skip if already compiled
mvn compile

Maven Command Reference

Frequently Used Commands

# Clean
mvn clean

# Compile
mvn compile

# Test
mvn test

# Package
mvn package

# Install (register to local repository)
mvn install

# Verify (including integration tests)
mvn verify

# Resolve dependencies
mvn dependency:resolve

# Display dependency tree
mvn dependency:tree

# Display project information
mvn help:effective-pom

# Code formatting
mvn formatter:format

# Add license headers
mvn license:format

Next Steps

After understanding build and test methods, refer to the following documents:

References