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
Refactored S3 test cases to remove repetition and use table drive tests #110
Refactored S3 test cases to remove repetition and use table drive tests #110
Conversation
* Remove passing testing var t all across the code * Reduce repetitive main tests and add subtests * Subtests simplified in 2 categories - TestList and TestNuke * Have subtests generated via returned test functions to avail table driven tests
@yorinasub17 @brikis98 - can you please check and let me know if this looks okay? Thanks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR!
GitHub is not doing a great job of rendering the diff, so this was quite hard to read and compare the old to the new. Would appreciate a second set of eyes @yorinasub17.
aws/s3_test.go
Outdated
// genTestsBucketName generates a test bucket name. | ||
func genTestBucketName() string { | ||
// Call UniqueID twice because even if the nth test tries to reuse a name of the first test | ||
// AWS S3 deletion operation might be in progress after nuking. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I understand this explanation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wanted to have a little bit more randomness but yes the comment isn't clear and not needed. Removed.
aws/s3_test.go
Outdated
objectCount int | ||
objectBatchsize int | ||
// setAWSParams sets up common operations for nuke S3 tests. | ||
func setAWSParams() (AWSParams, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: perhaps newAWSParams
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
aws/s3_test.go
Outdated
// Verify that - before creating bucket - it should not exist | ||
// | ||
// Please note that we are not reusing awsParams.awsSession and creating a random session in a region other | ||
// than the one in which the bucket is created - this is useful to test the sceanrio where the user has |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// than the one in which the bucket is created - this is useful to test the sceanrio where the user has | |
// than the one in which the bucket is created - this is useful to test the scenario where the user has |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
aws/s3_test.go
Outdated
if err == nil { | ||
assert.Fail(t, "Did not fail for invalid batch size") | ||
} | ||
t.Logf("SUCCESS: Did not list buckets due to invalid batch size - %s", bucket.name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not be using t.Logf
for logging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
aws/s3_test.go
Outdated
type testCaseStruct struct { | ||
name string | ||
args TestListS3BucketArgs | ||
} | ||
} | ||
|
||
func TestList_EmptyS3Bucket_NoTags(t *testing.T) { | ||
testListS3BucketsWrapper(t, []map[string]string{}, 10, true) | ||
} | ||
var allTestCases []testCaseStruct | ||
|
||
func TestList_EmptyS3Bucket_WithoutFilterTag(t *testing.T) { | ||
testListS3BucketsWrapper(t, []map[string]string{ | ||
testCases := []testCaseStruct{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: The Go idiom typically used for table-driven tests declares the struct and the tests all in one:
var testCases = []struct {
param1 string
param2 string
}{
{"aaa", "bbb"},
{"ccc", "ddd"},
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done for TestListS3Bucket
. For TestNukeS3Bucket
as per -
Line 428 in 7a99393
for _, bucketType := range []string{"NoVersioning", "Versioning"} { |
aws/s3_test.go
Outdated
|
||
targetRegions := []string{awsParams.region} | ||
|
||
return func(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
t.Parallel()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
* Not using t.Logf * Fixing typos * Using t.Parallel in sub and main tests * Using idomatic golang test struct where possible
0906e49
to
7a99393
Compare
@brikis98 @yorinasub17 - updated as per feedback. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The update makes sense, but I am not sure this is the best implementation for readability. I think my biggest challenge with this is the test function generator pattern.
I think it would be easier to follow and understand what is going on if there was instead a function to drive the test runNukeTest(t *testing.T, args *Args)
that then contains the combination of the generator routine and subtest function. Then, usage would be:
t.Run(tc.name, func(t *testing.T) { runNukeTest(t, tc.args) })
This removes one layer of indirection and should help make it much easier to follow what is going on. What do you think?
aws/s3_test.go
Outdated
isVersioned := false | ||
if bucketType == "Versioning" { | ||
isVersioned = true | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT:
isVersioned := bucketType == "Versioning"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
* Remove one level of indirection by combining subtest and setup for S3 list and nuke tests
Thanks - that would lead to cleaner code. Fixed it. |
@yorinasub17 - updated as per feedback. |
@yorinasub17 - just wanted to check if the above looks good - I have updated the code as per your feedback. Thanks. |
Hi @saurabh-hirani apologies for the delay on this. I've been super booked this month and haven't had the time to look at this. I am hoping to be able to review this again next week. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies for the long review cycle this time. I had to put this off multiple times, but finally had the time to look. This is very close, but had a few style nits.
I am committed to moving this across the finish line in the next two weeks. Let me know if you are not able to handle the updates, and I can try to find time to apply them myself.
Region: awsgo.String(region)}, | ||
) | ||
return session, err | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: since the namespace is shared across the entire package, this should probably be put in a different place or renamed to something specific to s3 tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done - added S3Test prefix where possible for consistency.
region string | ||
awsSession *session.Session | ||
svc *s3.S3 | ||
bucketName string | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: rename to something that is specific to S3.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been removed so not applicable.
aws/s3_test.go
Outdated
// TestS3Bucket represents a test S3 bucket | ||
type TestS3Bucket struct { | ||
name string | ||
tags []map[string]string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: consider using the structs from aws sdk for type safety.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checked and saw that there is no need for TestS3Bucket struct - easier to have functions which take args and instead of using types and getting into potential conflicts with AWS. create
and addObject
have been replaced by S3TestCreateBucket
and S3TestBucketAddObject
aws/s3_test.go
Outdated
if err != nil { | ||
assert.Fail(t, errors.WithStackTrace(err).Error()) | ||
assert.Failf(t, "Failed to setup AWS params", errors.WithStackTrace(err).Error()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use require.Fail
or require.NoError
to cut the test short. Otherwise, execution will continue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks - wasn't aware of that - have used require.NoError
- removes the if/else check also.
aws/s3_test.go
Outdated
allTestCases = append(allTestCases, testCaseStruct{ | ||
"EmptyBucket", | ||
TestNukeS3BucketArgs{isVersioned: false, checkDeleteMarker: false, objectCount: 0, objectBatchsize: 0, shouldNuke: true}, | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: statically define the list like you did in the other test instead of using append
, for consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did that - had optimised in this case as EmptyBucket test does not need to deal with versioned/non-versioned flags but moved it in.
}, true) | ||
} | ||
for _, bucketType := range []string{"NoVersioning", "Versioning"} { | ||
isVersioned := bucketType == "Versioning" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: use true
and false
directly in the range var.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cannot do so as the tests need the Versioning v/s NonVersioning prefix
--- PASS: TestNukeS3Bucket/NoVersioning_EmptyBucket (9.39s)
--- PASS: TestNukeS3Bucket/NoVersioning_BatchObjects_InvalidBatchSize_Over (9.97s)
--- PASS: TestNukeS3Bucket/Versioning_EmptyBucket (9.60s)
--- PASS: TestNukeS3Bucket/Versioning_AllObjects (24.06s)
Having true/false in range will lead to reinterpreting true false and setting Versioning/nonVersioning
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could do:
fmt.Sprintf("Versioning_%v_EmptyBucket", isVersioning)
But it's not a big deal so can keep this as is.
Thanks @yorinasub17 - will check out the changes today and reply back in the next 1-2 days. |
* Add S3Test prefix to avoid conflicts with other files in this namespace + AWS core libs * Use require.NoError * Remove TestS3Bucket type and use direct functions
@yorinasub17 updated as per feedback and added comments. Please check and let me know if this looks good. |
@yorinasub17 - can you please review the above changes and provide feedback if any more changes are required? |
Apologies for the delay. I had been snoozing this and lost track of it amongst all the other things on my plate. I just took a pass and the updates look reasonable, so kicked off a build. If that passes, we can go ahead and merge this in. Thanks! |
Ok build passed! Will merge this in. Thanks for your contribution! |
Thanks @yorinasub17 and @brikis98 for the feedback! |
The current code for
s3_test.go
has the following issues:t
is passed throughout the code and should be consolidated to be used only with tests.Refactored the code to fix the above issues. This has no impact on the current functionality as only the
s3_test.go
file has changed. This activity is also to ensure that adding cases for tagged and named deletions in the future is easier.