Skip to content

Commit 98b8482

Browse files
petros-double-test1claude
authored andcommitted
test(datasets): assert the surviving rows, not just how many
Both OPIK-7891 tests checked stored.size() and left the row identities unasserted. On a de-duplication test that is the weakest possible check: the count is exactly what a bug is most likely to keep right. Keeping the wrong revision of the duplicate, or dropping the distinct row and keeping both duplicates, would each leave the size at 2 and pass. Now both name the rows that must survive and compare whole objects via the shared IGNORED_FIELDS_DATA_ITEM element comparator, so a wrong-winner bug fails. This also pins behaviour the tests previously only assumed: the last submitted revision of a repeated id is the one that survives. The itemsTotal assertion still ties the counter to stored.size() rather than a literal, which is only meaningful now that stored itself is pinned. Addresses review feedback on #7966. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 50aa19a commit 98b8482

1 file changed

Lines changed: 47 additions & 23 deletions

File tree

apps/opik-backend/src/test/java/com/comet/opik/api/resources/v1/priv/DatasetVersionResourceTest.java

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3801,22 +3801,31 @@ void putItems__whenCreatingBatchRepeatsStableId__thenCountedOnce() {
38013801
// (ClickHouse async inserts report 0 before commit). A stable id repeated inside that
38023802
// first batch is therefore counted twice, while ClickHouse collapses it to one row.
38033803
var duplicatedId = TestIdGeneratorFactory.create().generateId();
3804+
var distinctId = TestIdGeneratorFactory.create().generateId();
3805+
3806+
// The repeated id wins with its LAST submitted content: ClickHouse keeps one row per
3807+
// dataset_item_id and reads take the newest, so "second" survives and "first" does not.
3808+
var winningDuplicate = DatasetItem.builder()
3809+
.id(duplicatedId)
3810+
.datasetItemId(duplicatedId)
3811+
.source(DatasetItemSource.SDK)
3812+
.data(Map.of("value", JsonUtils.getJsonNodeFromString("\"second\"")))
3813+
.build();
3814+
var distinctItem = DatasetItem.builder()
3815+
.id(distinctId)
3816+
.datasetItemId(distinctId)
3817+
.source(DatasetItemSource.SDK)
3818+
.data(Map.of("value", JsonUtils.getJsonNodeFromString("\"third\"")))
3819+
.build();
3820+
38043821
var items = List.of(
38053822
DatasetItem.builder()
38063823
.id(duplicatedId)
38073824
.source(DatasetItemSource.SDK)
38083825
.data(Map.of("value", JsonUtils.getJsonNodeFromString("\"first\"")))
38093826
.build(),
3810-
DatasetItem.builder()
3811-
.id(duplicatedId)
3812-
.source(DatasetItemSource.SDK)
3813-
.data(Map.of("value", JsonUtils.getJsonNodeFromString("\"second\"")))
3814-
.build(),
3815-
DatasetItem.builder()
3816-
.id(TestIdGeneratorFactory.create().generateId())
3817-
.source(DatasetItemSource.SDK)
3818-
.data(Map.of("value", JsonUtils.getJsonNodeFromString("\"third\"")))
3819-
.build());
3827+
winningDuplicate,
3828+
distinctItem);
38203829

38213830
datasetResourceClient.createDatasetItems(DatasetItemBatch.builder()
38223831
.datasetId(datasetId)
@@ -3826,10 +3835,14 @@ void putItems__whenCreatingBatchRepeatsStableId__thenCountedOnce() {
38263835

38273836
var version = getLatestVersion(datasetId);
38283837

3829-
// Two distinct ids went in, so the version holds two rows.
3838+
// Assert on the rows themselves, not just how many: a bug that kept the wrong revision
3839+
// of the duplicate, or dropped the distinct item and kept both duplicates, would leave
3840+
// the count at 2 and slip through a size-only check.
38303841
var stored = datasetResourceClient.getDatasetItems(
38313842
datasetId, 1, 100, version.versionHash(), API_KEY, TEST_WORKSPACE).content();
3832-
assertThat(stored).hasSize(2);
3843+
assertThat(stored)
3844+
.usingRecursiveFieldByFieldElementComparatorIgnoringFields(IGNORED_FIELDS_DATA_ITEM)
3845+
.containsExactlyInAnyOrder(winningDuplicate, distinctItem);
38333846

38343847
// items_total must agree with what is actually stored.
38353848
assertThat(version.itemsTotal()).isEqualTo(stored.size());
@@ -3845,6 +3858,14 @@ void putItems__whenDuplicateStableIdSpansBatchesInGroup__thenCountedOnce() {
38453858
// one version. The first batch creates it, later batches append. A stable id present in
38463859
// both must contribute exactly one item to the total.
38473860
var sharedId = TestIdGeneratorFactory.create().generateId();
3861+
var otherId = TestIdGeneratorFactory.create().generateId();
3862+
3863+
var otherItem = DatasetItem.builder()
3864+
.id(otherId)
3865+
.datasetItemId(otherId)
3866+
.source(DatasetItemSource.SDK)
3867+
.data(Map.of("value", JsonUtils.getJsonNodeFromString("\"other\"")))
3868+
.build();
38483869

38493870
datasetResourceClient.createDatasetItems(DatasetItemBatch.builder()
38503871
.datasetId(datasetId)
@@ -3855,28 +3876,31 @@ void putItems__whenDuplicateStableIdSpansBatchesInGroup__thenCountedOnce() {
38553876
.source(DatasetItemSource.SDK)
38563877
.data(Map.of("value", JsonUtils.getJsonNodeFromString("\"first\"")))
38573878
.build(),
3858-
DatasetItem.builder()
3859-
.id(TestIdGeneratorFactory.create().generateId())
3860-
.source(DatasetItemSource.SDK)
3861-
.data(Map.of("value", JsonUtils.getJsonNodeFromString("\"other\"")))
3862-
.build()))
3879+
otherItem))
38633880
.build(), TEST_WORKSPACE, API_KEY);
38643881

3882+
// The second batch re-sends the shared id with new content, so it is an update:
3883+
// one row, holding the later revision.
3884+
var updatedShared = DatasetItem.builder()
3885+
.id(sharedId)
3886+
.datasetItemId(sharedId)
3887+
.source(DatasetItemSource.SDK)
3888+
.data(Map.of("value", JsonUtils.getJsonNodeFromString("\"updated\"")))
3889+
.build();
3890+
38653891
datasetResourceClient.createDatasetItems(DatasetItemBatch.builder()
38663892
.datasetId(datasetId)
38673893
.batchGroupId(batchGroupId)
3868-
.items(List.of(DatasetItem.builder()
3869-
.id(sharedId)
3870-
.source(DatasetItemSource.SDK)
3871-
.data(Map.of("value", JsonUtils.getJsonNodeFromString("\"updated\"")))
3872-
.build()))
3894+
.items(List.of(updatedShared))
38733895
.build(), TEST_WORKSPACE, API_KEY);
38743896

38753897
var version = getLatestVersion(datasetId);
38763898
var stored = datasetResourceClient.getDatasetItems(
38773899
datasetId, 1, 100, version.versionHash(), API_KEY, TEST_WORKSPACE).content();
38783900

3879-
assertThat(stored).hasSize(2);
3901+
assertThat(stored)
3902+
.usingRecursiveFieldByFieldElementComparatorIgnoringFields(IGNORED_FIELDS_DATA_ITEM)
3903+
.containsExactlyInAnyOrder(updatedShared, otherItem);
38803904
assertThat(version.itemsTotal()).isEqualTo(stored.size());
38813905
}
38823906

0 commit comments

Comments
 (0)