-
Notifications
You must be signed in to change notification settings - Fork 178
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
fix: Fixes project flaky tests #1669
Changes from 24 commits
37bd3a6
38e9bab
98d87b6
f021848
72539d0
571fa00
260afbb
1f8e81d
8c546b4
f1f0a82
43aae57
3291160
95e0854
1c96572
698adeb
d6d391f
a30ccce
c76b692
f2a16ae
1ee3627
2b2c8da
9266a49
89b0ea3
fc43b97
be185bc
817acb0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -3,7 +3,6 @@ package project_test | |||||
import ( | ||||||
"fmt" | ||||||
"os" | ||||||
"strings" | ||||||
"testing" | ||||||
|
||||||
"go.mongodb.org/atlas-sdk/v20231115001/admin" | ||||||
|
@@ -15,26 +14,23 @@ import ( | |||||
) | ||||||
|
||||||
func TestAccProjectDSProject_byID(t *testing.T) { | ||||||
projectName := acctest.RandomWithPrefix("test-acc") | ||||||
orgID := os.Getenv("MONGODB_ATLAS_ORG_ID") | ||||||
teamsIds := strings.Split(os.Getenv("MONGODB_ATLAS_TEAMS_IDS"), ",") | ||||||
if len(teamsIds) < 2 { | ||||||
t.Skip("`MONGODB_ATLAS_TEAMS_IDS` must have 2 team ids for this acceptance testing") | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. improve pre-checks and fail if they're not met instead of just skipping the test |
||||||
} | ||||||
|
||||||
var ( | ||||||
projectName = acctest.RandomWithPrefix("test-acc") | ||||||
orgID = os.Getenv("MONGODB_ATLAS_ORG_ID") | ||||||
) | ||||||
resource.ParallelTest(t, resource.TestCase{ | ||||||
PreCheck: func() { acc.PreCheckBasic(t); acc.PreCheckTeamsIds(t) }, | ||||||
PreCheck: func() { acc.PreCheckBasic(t); acc.PreCheckProjectTeamsIds(t, 2) }, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
nit: for clarity I would suggest a more specific method name There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can do that but I normally like to say "with..." when there are multiple related methods, there is only one method in this case There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. renamed to: func PreCheckProjectTeamsIdsWithMinCount(tb testing.TB, minTeamsCount int) |
||||||
ProtoV6ProviderFactories: acc.TestAccProviderV6Factories, | ||||||
Steps: []resource.TestStep{ | ||||||
{ | ||||||
Config: testAccMongoDBAtlasProjectDSByIDUsingRS(acc.ConfigProject(projectName, orgID, | ||||||
[]*matlas.ProjectTeam{ | ||||||
{ | ||||||
TeamID: teamsIds[0], | ||||||
TeamID: acc.GetProjectTeamsIds(0), | ||||||
RoleNames: []string{"GROUP_READ_ONLY", "GROUP_DATA_ACCESS_ADMIN"}, | ||||||
}, | ||||||
{ | ||||||
TeamID: teamsIds[1], | ||||||
TeamID: acc.GetProjectTeamsIds(1), | ||||||
RoleNames: []string{"GROUP_DATA_ACCESS_ADMIN", "GROUP_OWNER"}, | ||||||
}, | ||||||
}, | ||||||
|
@@ -50,27 +46,24 @@ func TestAccProjectDSProject_byID(t *testing.T) { | |||||
} | ||||||
|
||||||
func TestAccProjectDSProject_byName(t *testing.T) { | ||||||
projectName := acctest.RandomWithPrefix("test-acc") | ||||||
orgID := os.Getenv("MONGODB_ATLAS_ORG_ID") | ||||||
teamsIds := strings.Split(os.Getenv("MONGODB_ATLAS_TEAMS_IDS"), ",") | ||||||
if len(teamsIds) < 2 { | ||||||
t.Skip("`MONGODB_ATLAS_TEAMS_IDS` must have 2 team ids for this acceptance testing") | ||||||
} | ||||||
|
||||||
var ( | ||||||
projectName = acctest.RandomWithPrefix("test-acc") | ||||||
orgID = os.Getenv("MONGODB_ATLAS_ORG_ID") | ||||||
) | ||||||
resource.ParallelTest(t, resource.TestCase{ | ||||||
PreCheck: func() { acc.PreCheckBasic(t); acc.PreCheckTeamsIds(t) }, | ||||||
PreCheck: func() { acc.PreCheckBasic(t); acc.PreCheckProjectTeamsIds(t, 2) }, | ||||||
ProtoV6ProviderFactories: acc.TestAccProviderV6Factories, | ||||||
Steps: []resource.TestStep{ | ||||||
{ | ||||||
Config: testAccMongoDBAtlasProjectDSByNameUsingRS(acc.ConfigProject(projectName, orgID, | ||||||
[]*matlas.ProjectTeam{ | ||||||
{ | ||||||
TeamID: teamsIds[0], | ||||||
TeamID: acc.GetProjectTeamsIds(0), | ||||||
RoleNames: []string{"GROUP_READ_ONLY", "GROUP_DATA_ACCESS_ADMIN"}, | ||||||
}, | ||||||
{ | ||||||
|
||||||
TeamID: teamsIds[1], | ||||||
TeamID: acc.GetProjectTeamsIds(1), | ||||||
RoleNames: []string{"GROUP_DATA_ACCESS_ADMIN", "GROUP_OWNER"}, | ||||||
}, | ||||||
}, | ||||||
|
@@ -86,27 +79,24 @@ func TestAccProjectDSProject_byName(t *testing.T) { | |||||
} | ||||||
|
||||||
func TestAccProjectDSProject_defaultFlags(t *testing.T) { | ||||||
projectName := acctest.RandomWithPrefix("test-acc") | ||||||
orgID := os.Getenv("MONGODB_ATLAS_ORG_ID") | ||||||
teamsIds := strings.Split(os.Getenv("MONGODB_ATLAS_TEAMS_IDS"), ",") | ||||||
if len(teamsIds) < 2 { | ||||||
t.Skip("`MONGODB_ATLAS_TEAMS_IDS` must have 2 team ids for this acceptance testing") | ||||||
} | ||||||
|
||||||
var ( | ||||||
projectName = acctest.RandomWithPrefix("test-acc") | ||||||
orgID = os.Getenv("MONGODB_ATLAS_ORG_ID") | ||||||
) | ||||||
resource.ParallelTest(t, resource.TestCase{ | ||||||
PreCheck: func() { acc.PreCheckBasic(t); acc.PreCheckTeamsIds(t) }, | ||||||
PreCheck: func() { acc.PreCheckBasic(t); acc.PreCheckProjectTeamsIds(t, 2) }, | ||||||
ProtoV6ProviderFactories: acc.TestAccProviderV6Factories, | ||||||
Steps: []resource.TestStep{ | ||||||
{ | ||||||
Config: testAccMongoDBAtlasProjectDSByNameUsingRS(acc.ConfigProject(projectName, orgID, | ||||||
[]*matlas.ProjectTeam{ | ||||||
{ | ||||||
TeamID: teamsIds[0], | ||||||
TeamID: acc.GetProjectTeamsIds(0), | ||||||
RoleNames: []string{"GROUP_READ_ONLY", "GROUP_DATA_ACCESS_ADMIN"}, | ||||||
}, | ||||||
{ | ||||||
|
||||||
TeamID: teamsIds[1], | ||||||
TeamID: acc.GetProjectTeamsIds(1), | ||||||
RoleNames: []string{"GROUP_DATA_ACCESS_ADMIN", "GROUP_OWNER"}, | ||||||
}, | ||||||
}, | ||||||
|
@@ -128,9 +118,10 @@ func TestAccProjectDSProject_defaultFlags(t *testing.T) { | |||||
} | ||||||
|
||||||
func TestAccProjectDSProject_limits(t *testing.T) { | ||||||
projectName := acctest.RandomWithPrefix("test-acc") | ||||||
orgID := os.Getenv("MONGODB_ATLAS_ORG_ID") | ||||||
|
||||||
var ( | ||||||
projectName = acctest.RandomWithPrefix("test-acc") | ||||||
orgID = os.Getenv("MONGODB_ATLAS_ORG_ID") | ||||||
) | ||||||
resource.ParallelTest(t, resource.TestCase{ | ||||||
PreCheck: func() { acc.PreCheckBasic(t) }, | ||||||
ProtoV6ProviderFactories: acc.TestAccProviderV6Factories, | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -171,17 +171,14 @@ func (d *ProjectsDS) Read(ctx context.Context, req datasource.ReadRequest, resp | |
} | ||
|
||
func populateProjectsDataSourceModel(ctx context.Context, conn *matlas.Client, connV2 *admin.APIClient, stateModel *tfProjectsDSModel, projectsRes *matlas.Projects) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the fix is in this func |
||
results := make([]*tfProjectDSModel, len(projectsRes.Results)) | ||
|
||
for i, project := range projectsRes.Results { | ||
results := make([]*tfProjectDSModel, 0, len(projectsRes.Results)) | ||
for _, project := range projectsRes.Results { | ||
atlasTeams, atlasLimits, atlasProjectSettings, err := getProjectPropsFromAPI(ctx, conn, connV2, project.ID) | ||
if err != nil { | ||
return fmt.Errorf("error while getting project properties for project %s: %v", project.ID, err.Error()) | ||
if err == nil { // if the project is still valid, e.g. could have just been deleted | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we fail if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no, that was the problem before. Imagine we get the list of projects for the org, but then some of them are deleted. It's not really a failure, so we just ignore it if it's deleted after it was in the list. This was the reason for project flaky test. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok noted, but then I guess we're ok to ignore 5xx errors? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've got 500 sometimes when doing something in a project that is being closed, so we could get also a 500 and it doesn't mean a real error but that the project is closing. So I think it's hard in this case to differentiate a "real" error from an error caused by the project being closed. Also chances are that if the project is in the list and it's not closed we'll get the details without any problem There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Understand this an edge case that is likely only appearing in our acceptance tests execution: fetching and creating/deleting project in parallel. Curious if a potential fix to this problem could be defining the data source test to run sequentially ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that would probably fix the tests, also to use the concurrency facility in GH actions so project acc and migration tests don't run in parallel. But at the end I thought this is a realistic use case that can happen sometimes and we don't want the DS to fail if that happens, that's why I focused on improving the prod. code. |
||
projectModel := newTFProjectDataSourceModel(ctx, project, atlasTeams, atlasProjectSettings, atlasLimits) | ||
results = append(results, &projectModel) | ||
} | ||
projectModel := newTFProjectDataSourceModel(ctx, project, atlasTeams, atlasProjectSettings, atlasLimits) | ||
results[i] = &projectModel | ||
} | ||
|
||
stateModel.Results = results | ||
stateModel.TotalCount = types.Int64Value(int64(projectsRes.TotalCount)) | ||
stateModel.ID = types.StringValue(id.UniqueId()) | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -2,6 +2,7 @@ package acc | |||||
|
||||||
import ( | ||||||
"os" | ||||||
"strings" | ||||||
"testing" | ||||||
) | ||||||
|
||||||
|
@@ -45,10 +46,26 @@ func PreCheckAtlasUsername(tb testing.TB) { | |||||
} | ||||||
} | ||||||
|
||||||
func PreCheckTeamsIds(tb testing.TB) { | ||||||
if os.Getenv("MONGODB_ATLAS_TEAMS_IDS") == "" { | ||||||
tb.Skip("`MONGODB_ATLAS_TEAMS_IDS` must be set for Projects acceptance testing") | ||||||
func PreCheckProjectTeamsIds(tb testing.TB, min int) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. improve teamsIds checks, and fail tests if pre-check is not met There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: can you please pass the name of the environment variable as input of the function? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same, I think it's better to have the env.var in both methods as they're used only for teamsIds, these methods are not intended to be generic for other purporses. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can change it, although I tried to follow "go idiomatic" in the sense the I think "min" in this context is clear, but I agree I can make it more specific here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. renamed to minTeamsCount (although it looks a bit redudant to me as Teams is already in function name) |
||||||
envVar := os.Getenv("MONGODB_ATLAS_TEAMS_IDS") | ||||||
if envVar == "" { | ||||||
tb.Fatal("`MONGODB_ATLAS_TEAMS_IDS` must be set for Projects acceptance testing") | ||||||
return | ||||||
} | ||||||
teamsIds := strings.Split(envVar, ",") | ||||||
if count := len(teamsIds); count < min { | ||||||
tb.Fatalf("`MONGODB_ATLAS_TEAMS_IDS` must have at least %d team ids for this acceptance testing, has %d", min, count) | ||||||
} | ||||||
} | ||||||
|
||||||
func GetProjectTeamsIds(pos int) string { | ||||||
envVar := os.Getenv("MONGODB_ATLAS_TEAMS_IDS") | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: can you please pass the name of the environment variable as input of the function? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's better in this way as PreCheckProjectTeamsIds and GetProjectTeamsIds work together for teamsIds and they both use the same env.var There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think this is an assumption that might not be always true, unless you call the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if you don't call precheck you won't check that you have the min teams you need but it will still work (returns "" when you don't have that pos). (They have the same name part ProjectTeamsIds and are located together in the file to make it easier to see that they are intended to work together) |
||||||
teamsIds := strings.Split(envVar, ",") | ||||||
count := len(teamsIds) | ||||||
if envVar == "" || pos >= count { | ||||||
return "" | ||||||
} | ||||||
return teamsIds[pos] | ||||||
} | ||||||
|
||||||
func PreCheckGov(tb testing.TB) { | ||||||
|
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 used