Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Destinations CDK: better integration tests #45113

Conversation

edgao
Copy link
Contributor

@edgao edgao commented Sep 3, 2024

Implement the test framework, write a minimal set of base tests, and implement those tests for destination-e2e-test. I stuck with our existing abstract class + concrete per-destination implementation strategy, because:

  1. tests are opt-out
    1. like I mentioned in last (?) week's meeting - micronaut makes running the base class kind of wonky, so I think it's still best practice to have the override testFoo() { super.testFoo() } declarations. But even without that, we still get the test case.
  2. it gives us an ok way to run individual test cases from inside intellij

general review guide:

  1. DestinationMessage.kt has some simple convenience constructors
  2. Start with IntegrationTest.kt, which is where the meat of the PR lives
  3. Take a look at DestinationDataDumper, DestinationCleaner, ExpectedRecordMapper, and NameMapper - these are interfaces that destinations can/should implement. DataDumper doesn't have a noop implementation because every destination must implement it; everything else is optional.
  4. Check out DestinationProcess, which is how we launch the connector via micronaut (and eventually Docker). It's basically just a wrapper around CliRunner.
  5. CheckIntegrationTest + BasicFunctionalityIntegrationTest show how to write some basic tests.
  6. Then skim through all the destination-e2e-test code - it's hopefully pretty self-explanatory after everything else in this PR

Copy link

vercel bot commented Sep 3, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
airbyte-docs ⬜️ Ignored (Inspect) Visit Preview Sep 20, 2024 4:42pm

@octavia-squidington-iii octavia-squidington-iii added the CDK Connector Development Kit label Sep 3, 2024
@edgao edgao force-pushed the edgao/better_record_differ branch from da9d896 to 7e3fa25 Compare September 4, 2024 22:38
@edgao edgao force-pushed the edgao/cdk_integration_tests branch from b0b856d to 8d9871f Compare September 4, 2024 22:38
@edgao edgao force-pushed the edgao/better_record_differ branch from 7e3fa25 to 48ca85d Compare September 5, 2024 16:31
@edgao edgao force-pushed the edgao/cdk_integration_tests branch from 8d9871f to 228765c Compare September 5, 2024 16:31
@edgao edgao force-pushed the edgao/cdk_integration_tests branch 2 times, most recently from 236be41 to 70b9a9c Compare September 5, 2024 17:49
build.gradle Outdated
@@ -55,16 +55,16 @@ allprojects {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
compileJava {
options.compilerArgs += ["-Werror", "-Xlint:all,-serial,-processing"]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll revert this before merging, this was just driving me nuts locally

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

public class TestingSilentDestinationAcceptanceTest extends DestinationAcceptanceTest {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't check what these two classes are doing, but will revive these tests before merging this PR

@edgao edgao force-pushed the edgao/cdk_integration_tests branch from 70b9a9c to 6384e77 Compare September 5, 2024 23:18
@edgao edgao force-pushed the edgao/better_record_differ branch from 48ca85d to 26b418a Compare September 9, 2024 23:43
@edgao edgao force-pushed the edgao/cdk_integration_tests branch from e476fcc to 617d533 Compare September 9, 2024 23:43
@edgao edgao force-pushed the edgao/better_record_differ branch from 26b418a to 1930d44 Compare September 10, 2024 19:49
@edgao edgao force-pushed the edgao/cdk_integration_tests branch from ab66980 to 70220ef Compare September 10, 2024 19:49
@edgao edgao force-pushed the edgao/better_record_differ branch from 1930d44 to e0b98f1 Compare September 11, 2024 15:44
@edgao edgao force-pushed the edgao/cdk_integration_tests branch from 70220ef to bde7d82 Compare September 11, 2024 15:45
@edgao edgao force-pushed the edgao/better_record_differ branch from e0b98f1 to 0feb717 Compare September 11, 2024 21:09
@edgao edgao force-pushed the edgao/cdk_integration_tests branch 5 times, most recently from 0b18a1a to 7eedfd8 Compare September 11, 2024 22:32
@edgao edgao force-pushed the edgao/cdk_integration_tests branch from f8e49cf to 4cdec03 Compare September 17, 2024 16:35
}

@Test
open fun testBasicWrite() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this test case is mostly here to (a) be a quick smoke test on our state handling, and (b) show the typical interaction with DestinationProcess. Most tests we'll actually write don't need any of the state stuff, and would look more like:

runSync(config, stream, listOf(records...))
dumpAndDiffRecords(...)
// (potentially more syncs, if we're e.g. testing refreshes)

@edgao edgao marked this pull request as ready for review September 17, 2024 16:45
@edgao edgao requested a review from a team as a September 17, 2024 16:45
@edgao edgao force-pushed the edgao/buffering_output_consumer_tracks_message_consumption branch from 28207e7 to 1508fa6 Compare September 17, 2024 17:09
@edgao edgao requested a review from a team as a code owner September 17, 2024 17:09
@edgao edgao force-pushed the edgao/cdk_integration_tests branch 2 times, most recently from c2f4b23 to 30b24fb Compare September 17, 2024 21:45
@edgao edgao force-pushed the edgao/cdk_integration_tests branch from 30b24fb to 43cbd5c Compare September 17, 2024 22:23
@edgao edgao force-pushed the edgao/buffering_output_consumer_tracks_message_consumption branch from 1508fa6 to a30248e Compare September 19, 2024 21:49
@edgao edgao force-pushed the edgao/cdk_integration_tests branch 2 times, most recently from c36924e to cd7a833 Compare September 19, 2024 21:53
@edgao edgao force-pushed the edgao/buffering_output_consumer_tracks_message_consumption branch from a30248e to 2b8def0 Compare September 19, 2024 21:56
@edgao edgao force-pushed the edgao/cdk_integration_tests branch from cd7a833 to 78dc640 Compare September 19, 2024 21:56
@edgao edgao force-pushed the edgao/buffering_output_consumer_tracks_message_consumption branch from 2b8def0 to e905aed Compare September 19, 2024 21:59
@edgao edgao force-pushed the edgao/cdk_integration_tests branch from 78dc640 to 2d3af61 Compare September 19, 2024 21:59
LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC)
.format(DateTimeFormatter.ofPattern("YYYYMMDD"))
// stream name doesn't need to be randomized, only the namespace.
val randomizedNamespace = "test$timestampString$randomSuffix"
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this mean that we never test the null namespace case?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we can still do that. Something along these lines, specifics of config.setDefaultNamespace tbd:

val modifiedConfig = config.setDefaultNamespace(randomizedNamespace)
runSync(modifiedConfig, records = listOf(Record(namespace=null, ...)))
verify(namespace=randomizedNamespace, ...)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

though it's a bit trickier for s3, where namespace=null is an actual thing :/ I think we'd just disregard randomizedNamespace for that:

runSync(config, records=[Record(namespace = null, name = "test_stream_with_random_chars1234")])

(i.e. this field is purely advisory, it's up to each individual test to use it or not)


package io.airbyte.cdk.test.util

fun interface DestinationCleaner {
Copy link
Contributor

Choose a reason for hiding this comment

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

Dq, why is the cleaner its own thing and not an entry point into the process?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

like why not have a cleanup method on DestinationProcess? I think they're pretty separate concerns - the dest process is just the connector (i.e. it supports spec/check/write)

but the cleaner is a weird out-of-connector thing. @stephane-airbyte 's recent Snowflake PR actually has a good example of what I want this class to do - https://github.com/airbytehq/airbyte/pull/45370/files#diff-c86b086ef3cc7bf564aedd699868dcc38661d51b3cc1bf34616720971866c6f6

(i.e. show schemas -> drop schema/etc)

Copy link
Contributor

@johnny-schmidt johnny-schmidt left a comment

Choose a reason for hiding this comment

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

This looks solid to me. If you want to merge it down into e2e I'll start working on the final productionalization.

I think overall we'll want to iterate on these interfaces (mine and yours) and work out how we want to handle configs, injection in general, mapping to and from schemas and records, all that. But we can learn as we go.

@edgao edgao force-pushed the edgao/cdk_integration_tests branch from 2d3af61 to d8e2b9e Compare September 20, 2024 15:24
@edgao edgao force-pushed the edgao/cdk_integration_tests branch from d8e2b9e to d55ec66 Compare September 20, 2024 16:42
// so we have to suppress the entire class.
// Thanks, spotbugs.
@SuppressFBWarnings("NP_NONNULL_RETURN_VIOLATION", justification = "Micronaut DI")
abstract class IntegrationTest(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@johnny-schmidt / @stephane-airbyte I do want to call this piece out specifically - I copied this pattern from existing tests, but it could (/should) just be some utility class that gets constructed by test classes, instead of an extra layer of inheritance.

I'm basically reserving my next couple weeks to work on testing stuff (and probably won't have time to make big changes b/c OC)... so I'd prefer to just leave that debate for later, so we can at least get things merged + unblock further development? It should be a pretty simple switch, just a bit tedious.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm fine with this as a foundation. We can talk through some of the implications of this stuff at the next CDK meeting?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sgtm!

@edgao
Copy link
Contributor Author

edgao commented Sep 20, 2024

I think overall we'll want to iterate on these interfaces (mine and yours) and work out how we want to handle configs, injection in general, mapping to and from schemas and records, all that. But we can learn as we go.

+1. This is just the bare minimum to show what I want to do + get some basic demonstrations working, I fully expect we'll be tweaking/adding stuff as we go.

Base automatically changed from edgao/buffering_output_consumer_tracks_message_consumption to issue-9361/load-cdk-with-e2e-dest-post-refactor September 20, 2024 20:02
@edgao edgao merged commit d55ec66 into issue-9361/load-cdk-with-e2e-dest-post-refactor Sep 20, 2024
34 of 43 checks passed
@edgao edgao deleted the edgao/cdk_integration_tests branch September 20, 2024 20:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/connectors Connector related issues CDK Connector Development Kit connectors/destination/e2e-test
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants