feat: Add Testing suite for destination plugins#369
Conversation
hermanschaaf
left a comment
There was a problem hiding this comment.
There's quite a bit to unpack here, so I haven't reviewed it in great detail, but noticed a few small testing-related bugs
Co-authored-by: Herman Schaaf <hermanschaaf@gmail.com>
Co-authored-by: Herman Schaaf <hermanschaaf@gmail.com>
Co-authored-by: Herman Schaaf <hermanschaaf@gmail.com>
Co-authored-by: Herman Schaaf <hermanschaaf@gmail.com>
Co-authored-by: Herman Schaaf <hermanschaaf@gmail.com>
Co-authored-by: Herman Schaaf <hermanschaaf@gmail.com>
Co-authored-by: Herman Schaaf <hermanschaaf@gmail.com>
Co-authored-by: Herman Schaaf <hermanschaaf@gmail.com>
|
Looks like the newly added tests on Windows are failing https://github.com/cloudquery/plugin-sdk/actions/runs/3412572062/jobs/5678256683 |
wow so weird. maybe something related to |
|
Ok I think found the bug on windows actions. seems like either it is "too fast" but more likely |
erezrokah
left a comment
There was a problem hiding this comment.
I think the helper methods and memory plugin make sense.
I might be missing something with the test suites. Maybe we could make them more readable by having a clear structure of setup, act, assert, and splitting the suites (especially the overwrite one), so each one tests a single use case?
| ctx := context.Background() | ||
| logger := getTestLogger(t) | ||
|
|
||
| t.Run("TestWriteOverwrite", func(t *testing.T) { |
There was a problem hiding this comment.
Maybe we should use a list of enums instead of multiple booleans? Then this should will be a for loop of the suites we want to run (instead of running, then skipping).
We can default to all if the list is nil
There was a problem hiding this comment.
Tried a different approach now.
plugins/destination_testing.go
Outdated
| expectedResource := &schema.DestinationResource{ | ||
| TableName: tables[0].Name, | ||
| Data: TestData(), | ||
| if !s.skipTestOverWriteDeleteStale { |
There was a problem hiding this comment.
These lines don't impact the outcome of the test (you can remove them and TestDestinationPlugin passes
There was a problem hiding this comment.
Not sure I understand. some plugins dont support DeleteStale
There was a problem hiding this comment.
I mean you can remove the entire block (including DeleteStale) and the test still passes
There was a problem hiding this comment.
But I want to run deletestale for plugins that support it so why remove it? or we are talking about a different block.
There was a problem hiding this comment.
That is what's confusing for me, why do we need it if the test passes without it?
There was a problem hiding this comment.
I removed it I was referring to a deletestale lateron where I check if it was deleted after that via read
| sourceName := uuid.NewString() | ||
| resource := schema.DestinationResource{ | ||
| TableName: table.Name, | ||
| Data: testdata.TestData(), |
There was a problem hiding this comment.
I'm not that happy about different tests sharing the same data. I think it's better to have it duplicated than creating a dependency between the different tests, WDYT?
There was a problem hiding this comment.
They dont share it. it creates new data every call to TestData
There was a problem hiding this comment.
By share I mean if someone changes TestData it impacts all tests (i.e. I can add data to test something and it will break other tests accidentally)
There was a problem hiding this comment.
It wont impact as it creates a new struct or we are talking about something else. Each test creates it's own testdata.
There was a problem hiding this comment.
Oh you mean the function itself. yes but no one else is using it so let's keep it as is now given we didn't have tests before.
| TableName: table.Name, | ||
| Data: testdata.TestData(), | ||
| } | ||
| _ = resource2.Data[5].Set("00000000-0000-0000-0000-000000000007") |
There was a problem hiding this comment.
This might a bit hard to read. Maybe we can struct the test data in a way that it's clear what is its type?
There was a problem hiding this comment.
Agree, there is no good way here. maybe we need some support from the SDK but I would leave this out for now as it turns a bit into an "ORM" given read abilities.
plugins/destination_testing.go
Outdated
| } | ||
|
|
||
| func DestinationPluginTestHelper(ctx context.Context, p *DestinationPlugin, logger zerolog.Logger, spec specs.Destination) error { | ||
| func (s *DestinationPluginTestSuite) destinationPluginTestWriteOverwrite(ctx context.Context, p *DestinationPlugin, logger zerolog.Logger, spec specs.Destination) error { |
There was a problem hiding this comment.
Doesn't this test only OverWriteDeleteStale?
If I remove the code that handles skipTestOverWriteDeleteStale (both sections of it) the test fails.
I'm not sure how this tests only overwrite mode.
May I suggest splitting this suite to 2 distinct suites, 1 for overwrite mode and another for overwrite with delete stale?
There was a problem hiding this comment.
I added a struct with options instead of with
plugins/destination_test.go
Outdated
|
|
||
| func TestDestinationPlugin(t *testing.T) { | ||
| p := NewDestinationPlugin("test", "development", NewTestDestinationMemDBClient) | ||
| DestinationPluginTestSuiteRunner(t, p, specs.Destination{ |
There was a problem hiding this comment.
I'm a bit confused by this. DestinationPluginTestSuiteRunner runs TestWriteOverwrite and TestWriteAppend, but we set the plugin write mode to WriteModeAppend.
I'd expect it so each suite will run on a specific plugin write mode
There was a problem hiding this comment.
The testsuite will re-run Init. maybe I need to change it to get just the spec of the plugin instead of the destination.
|
@erezrokah Thanks! Can you please take another look? |
|
|
||
| t.Run("TestWriteOverwrite", func(t *testing.T) { | ||
| t.Helper() | ||
| if suite.tests.Overwrite { |
There was a problem hiding this comment.
Shouldn't this be:
if suite.tests.Overwrite {
t.Run("TestWriteOverwrite"...
}
There was a problem hiding this comment.
I think not because otherwise I cant call t.skip which will give indicator on what tests were skipped natively.
There was a problem hiding this comment.
Ah, cool but then it should be if !suite.tests.Overwrite to skip when the condition is false?
erezrokah
left a comment
There was a problem hiding this comment.
The remaining comments are non blocking
🤖 I have created a release *beep* *boop* --- ## [1.1.0](v1.0.4...v1.1.0) (2022-11-08) ### Features * Add Testing suite for destination plugins ([#369](#369)) ([1a542b9](1a542b9)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
This should go after this is merged - cloudquery/plugin-sdk#369
This should go after this is merged - cloudquery/plugin-sdk#369
Closes #348
Introduce testing suite for destination plugins as well as number of methods to including
transformersandreverseTransformersto help testing suite be able to test "end-to-end".This also adds more testing with a
memoryDBplugin to test destination plugin and destination plugin testing suite