Skip to content

Commit

Permalink
Improve assertTableEquals usability (#2567)
Browse files Browse the repository at this point in the history
Make a few improvements to the assertTableEquals functions:

* The "include primary keys" flag is now inferred from the list of expected
  records; callers no longer have to specify it explicitly.

* The expected records can now be any kind of collection, not just a Set.

* The lists of expected and actual records are now sorted before they're passed
  to assertEquals, rather than passed as sets. This should make it easier to
  spot the differences in assertion failure messages, especially when the test
  is run in an IDE that can diff the expected and actual values.
  • Loading branch information
sgrimm authored Nov 4, 2024
1 parent 7f37bc9 commit a86e686
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,7 @@ class ParticipantProjectSpeciesServiceTest : DatabaseTest(), RunsAsUser {
modifiedBy = userId,
modifiedTime = now,
projectId = projectId,
submissionStatusId = SubmissionStatus.NotSubmitted),
includePrimaryKeys = false)
submissionStatusId = SubmissionStatus.NotSubmitted))

assertTableEquals(
ParticipantProjectSpeciesRecord(
Expand All @@ -134,8 +133,7 @@ class ParticipantProjectSpeciesServiceTest : DatabaseTest(), RunsAsUser {
projectId = projectId,
rationale = "rationale",
speciesId = speciesId,
submissionStatusId = SubmissionStatus.NotSubmitted),
includePrimaryKeys = false)
submissionStatusId = SubmissionStatus.NotSubmitted))

eventPublisher.assertEventPublished(
ParticipantProjectSpeciesAddedEvent(
Expand Down
46 changes: 19 additions & 27 deletions src/test/kotlin/com/terraformation/backend/db/DatabaseBackedTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3102,25 +3102,29 @@ abstract class DatabaseBackedTest {
* You will usually want one of the other variants of this that require fewer parameters.
*
* @param table The table whose contents should be examined.
* @param expected The set of records the table should contain.
* @param expected The records the table should contain. If the records' primary key fields are
* null, the primary keys of the table records will be ignored.
* @param message Assertion failure message; defaults to the table name.
* @param where Optional query condition to assert on a subset of a table's contents. Only rows
* matching the condition will be considered.
* @param includePrimaryKeys If false, the primary key field(s) of the records from the database
* will be cleared before comparing against [expected]. This can be used to ignore
* database-generated IDs.
* @param transform Function to apply to records from the database before comparing them to
* [expected]. Can be used to clear or hardwire specific fields that aren't relevant to the
* behavior being tested.
*/
protected fun <R : UpdatableRecord<R>> assertTableEquals(
table: Table<R>,
expected: Set<R>,
expected: Collection<R>,
message: String = table.name,
where: Condition? = null,
includePrimaryKeys: Boolean = true,
transform: ((R) -> R)? = null,
) {
val sampleExpected = expected.firstOrNull()

// If the expected records have primary key values, then include primary keys in the records
// that get pulled from the database. This is not the Kotlin data class copy(), but the one from
// UpdatableRecord, which clears primary key fields.
val includePrimaryKeys = sampleExpected != sampleExpected?.copy()

val actual =
dslContext
.selectFrom(table)
Expand All @@ -3131,36 +3135,32 @@ abstract class DatabaseBackedTest {
if (includePrimaryKeys) {
transformed
} else {
// This is not the Kotlin data class copy(), but the one from UpdatableRecord, which
// clears primary key fields.
// This is UpdatableRecord.copy(). which clears primary key fields.
transformed.copy()
}
}
.toSet()
.sorted()

assertEquals(expected, actual, message)
assertEquals(expected.sorted(), actual, message)
}

/**
* Asserts that a table (or a filtered subset of it) contains an expected set of records and
* nothing else.
*
* @param expected The set of records the table should contain. Must be non-empty.
* @param expected The records the table should contain. Must be non-empty. If the records'
* primary key fields are null, the primary keys of the table records will be ignored.
* @param message Assertion failure message; defaults to the table name.
* @param where Optional query condition to assert on a subset of a table's contents. Only rows
* matching the condition will be considered.
* @param includePrimaryKeys If false, the primary key field(s) of the records from the database
* will be cleared before comparing against [expected]. This can be used to ignore
* database-generated IDs.
* @param transform Function to apply to records from the database before comparing them to
* [expected]. Can be used to clear or hardwire specific fields that aren't relevant to the
* behavior being tested.
*/
protected fun <R : UpdatableRecord<R>> assertTableEquals(
expected: Set<R>,
expected: Collection<R>,
message: String? = null,
where: Condition? = null,
includePrimaryKeys: Boolean = true,
transform: ((R) -> R)? = null,
) {
val table =
Expand All @@ -3172,21 +3172,18 @@ abstract class DatabaseBackedTest {
expected = expected,
message = message ?: table.name,
where = where,
includePrimaryKeys = includePrimaryKeys,
transform = transform,
)
}

/**
* Asserts that a table (or a filtered subset of it) contains exactly one row.
*
* @param expected The single row that the table should contain.
* @param expected The single record that the table should contain. If its primary key field(s)
* are null, the primary keys of the table records will be ignored.
* @param message Assertion failure message; defaults to the table name.
* @param where Optional query condition to assert on a subset of a table's contents. Only rows
* matching the condition will be considered.
* @param includePrimaryKeys If false, the primary key field(s) of the records from the database
* will be cleared before comparing against [expected]. This can be used to ignore
* database-generated IDs.
* @param transform Function to apply to records from the database before comparing them to
* [expected]. Can be used to clear or hardwire specific fields that aren't relevant to the
* behavior being tested.
Expand All @@ -3195,15 +3192,10 @@ abstract class DatabaseBackedTest {
expected: R,
message: String? = null,
where: Condition? = null,
includePrimaryKeys: Boolean = true,
transform: ((R) -> R)? = null,
) {
assertTableEquals(
expected = setOf(expected),
message = message,
where = where,
includePrimaryKeys = includePrimaryKeys,
transform = transform)
expected = listOf(expected), message = message, where = where, transform = transform)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,7 @@ internal class BatchImporterTest : DatabaseTest(), RunsAsUser {
position = 2,
typeId = UploadProblemType.MalformedValue,
uploadId = uploadId,
value = "ShortName",
),
includePrimaryKeys = false)
value = "ShortName"))

assertStatus(UploadStatus.Invalid)
}
Expand Down

0 comments on commit a86e686

Please sign in to comment.