Skip to content

Add initial unit test coverage for Metrics event persistence#1439

Draft
firasrg wants to merge 1 commit intodevelopfrom
firasrg/setting-analytics-tests
Draft

Add initial unit test coverage for Metrics event persistence#1439
firasrg wants to merge 1 commit intodevelopfrom
firasrg/setting-analytics-tests

Conversation

@firasrg
Copy link
Contributor

@firasrg firasrg commented Mar 13, 2026

What

Adds the first unit test for the analytics system.

  • Added MetricsTests to verify Metrics#count(...) persists a metric event;
  • Asserted both the stored event name and the recorded timestamp;
  • Added async waiting/timeout handling for reliable verification of background writes;
  • Exposed the Metrics executor service so tests can shut it down cleanly;
  • Enabled debug logging for org.togetherjava.tjbot in test runs;
  • Added AssertJ for test assertions

Why

Metrics performs asynchronous database writes, so having direct test coverage here improves confidence in analytics persistence and makes future refactors safer.

Validation

  • ran :application:test --tests org.togetherjava.tjbot.features.MetricsTests

@firasrg firasrg requested a review from a team as a code owner March 13, 2026 18:34
@sonarqubecloud
Copy link

@firasrg firasrg marked this pull request as draft March 13, 2026 19:25
Comment on lines +16 to +17
<Logger name="org.togetherjava.tjbot" level="debug"/>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undo

implementation 'org.apache.commons:commons-text:1.15.0'
implementation 'com.apptasticsoftware:rssreader:3.12.0'

testImplementation 'org.assertj:assertj-core:3.27.7'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undo. we want to use raw junit in this project for now as it is easier for beginners and reflects more what they will see in the wild and might already be familiar with from their own projects and university etc

Comment on lines +56 to +58
public ExecutorService getExecutorService() {
return service;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undo, this won't be needed (see other comment why)

import static org.assertj.core.api.Assertions.within;
import static org.junit.jupiter.api.Assertions.fail;

final class MetricsTests {
Copy link
Member

@Zabuzard Zabuzard Mar 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test is too much in terms of complexity for no tangible benefit.

lets step back and create something simpler that beginners can understand and maintain while providing pretty much the same test-safety in terms of relevant coverage.

  1. create a package private method in Metrics called countBlocking. its identical to count but it won't use the executor service. so it creates the instant and then calls processEvent directly
  2. in ur unit test this will be the method ur testing against now. without the async stuff the test will simplify a lot
  3. the test should use a GWT structure (see other examples in the codebase, alternative patterns that share the same idea: 4-phases SEVT or AAA). try to aim for something like this:
@Test
void basicEventCount() {
  // GIVEN a test event
  String expectedEvent = "test";
  Instant expectedHappenedAt = Instant.now();

  // WHEN counting the event
  metrics.countBlocking(expectedEvent);

  // THEN the event was saved in the DB
  Foo entry = database...
  String actualEvent = entry.event();
  Instant actualHappenedAt = entry.happenedAt();

  assertEquals(expectedEvent, actualEvent);
  assertCloseEnough(expectedHappenedAt, actualHappenedAt);
} 

private static void assertCloseEnough(Instant expected, Instant actual) {
 ... // assert that its within 1min difference
} 

(double check the correct order of expected vs actual in assert, i never can remember it, lol)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants