Skip to content

Commit 3f1988d

Browse files
Thomas StrombergThomas Stromberg
authored andcommitted
improve test performance
1 parent f9df84d commit 3f1988d

17 files changed

+262
-7
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ build-registrar:
1616

1717
# Run tests with race detection and coverage
1818
test:
19-
go test -v -race -cover ./...
19+
go test -race -cover ./...
2020

2121
# Format code
2222
fmt:

pkg/bot/coordinator_test_helpers.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"sync"
78
"time"
89

910
ghmailto "github.com/codeGROOVE-dev/gh-mailto/pkg/gh-mailto"
@@ -15,6 +16,7 @@ import (
1516

1617
// mockStateStore implements StateStore interface from bot package.
1718
type mockStateStore struct {
19+
mu sync.Mutex
1820
threads map[string]ThreadInfo
1921
dmTimes map[string]time.Time
2022
dmUsers map[string][]string
@@ -25,6 +27,8 @@ type mockStateStore struct {
2527
}
2628

2729
func (m *mockStateStore) Thread(owner, repo string, number int, channelID string) (ThreadInfo, bool) {
30+
m.mu.Lock()
31+
defer m.mu.Unlock()
2832
key := fmt.Sprintf("%s/%s#%d:%s", owner, repo, number, channelID)
2933
if m.threads != nil {
3034
if info, ok := m.threads[key]; ok {
@@ -35,6 +39,8 @@ func (m *mockStateStore) Thread(owner, repo string, number int, channelID string
3539
}
3640

3741
func (m *mockStateStore) SaveThread(owner, repo string, number int, channelID string, info ThreadInfo) error {
42+
m.mu.Lock()
43+
defer m.mu.Unlock()
3844
if m.saveThreadErr != nil {
3945
return m.saveThreadErr
4046
}
@@ -47,6 +53,8 @@ func (m *mockStateStore) SaveThread(owner, repo string, number int, channelID st
4753
}
4854

4955
func (m *mockStateStore) LastDM(userID, prURL string) (time.Time, bool) {
56+
m.mu.Lock()
57+
defer m.mu.Unlock()
5058
key := userID + ":" + prURL
5159
if m.dmTimes != nil {
5260
if t, ok := m.dmTimes[key]; ok {
@@ -57,6 +65,8 @@ func (m *mockStateStore) LastDM(userID, prURL string) (time.Time, bool) {
5765
}
5866

5967
func (m *mockStateStore) RecordDM(userID, prURL string, sentAt time.Time) error {
68+
m.mu.Lock()
69+
defer m.mu.Unlock()
6070
key := userID + ":" + prURL
6171
if m.dmTimes == nil {
6272
m.dmTimes = make(map[string]time.Time)
@@ -66,6 +76,8 @@ func (m *mockStateStore) RecordDM(userID, prURL string, sentAt time.Time) error
6676
}
6777

6878
func (m *mockStateStore) ListDMUsers(prURL string) []string {
79+
m.mu.Lock()
80+
defer m.mu.Unlock()
6981
if m.dmUsers != nil {
7082
if users, ok := m.dmUsers[prURL]; ok {
7183
return users
@@ -75,13 +87,17 @@ func (m *mockStateStore) ListDMUsers(prURL string) []string {
7587
}
7688

7789
func (m *mockStateStore) WasProcessed(eventKey string) bool {
90+
m.mu.Lock()
91+
defer m.mu.Unlock()
7892
if m.processedEvents != nil {
7993
return m.processedEvents[eventKey]
8094
}
8195
return false
8296
}
8397

8498
func (m *mockStateStore) MarkProcessed(eventKey string, _ time.Duration) error {
99+
m.mu.Lock()
100+
defer m.mu.Unlock()
85101
if m.markProcessedErr != nil {
86102
return m.markProcessedErr
87103
}
@@ -93,6 +109,8 @@ func (m *mockStateStore) MarkProcessed(eventKey string, _ time.Duration) error {
93109
}
94110

95111
func (m *mockStateStore) LastNotification(prURL string) time.Time {
112+
m.mu.Lock()
113+
defer m.mu.Unlock()
96114
if m.lastNotifications != nil {
97115
if t, ok := m.lastNotifications[prURL]; ok {
98116
return t
@@ -102,6 +120,8 @@ func (m *mockStateStore) LastNotification(prURL string) time.Time {
102120
}
103121

104122
func (m *mockStateStore) RecordNotification(prURL string, notifiedAt time.Time) error {
123+
m.mu.Lock()
124+
defer m.mu.Unlock()
105125
if m.lastNotifications == nil {
106126
m.lastNotifications = make(map[string]time.Time)
107127
}
@@ -130,6 +150,7 @@ func (*mockStateStore) Close() error {
130150
//
131151
//nolint:govet // fieldalignment optimization would reduce test readability
132152
type mockSlackClient struct {
153+
mu sync.Mutex
133154
postThreadFunc func(ctx context.Context, channelID, text string, attachments []slack.Attachment) (string, error)
134155
updateMessageFunc func(ctx context.Context, channelID, timestamp, text string) error
135156
updateDMMessageFunc func(ctx context.Context, userID, timestamp, text string) error
@@ -170,35 +191,41 @@ type mockUpdatedDMMessage struct {
170191
}
171192

172193
func (m *mockSlackClient) PostThread(ctx context.Context, channelID, text string, attachments []slack.Attachment) (string, error) {
194+
m.mu.Lock()
173195
m.postedMessages = append(m.postedMessages, mockPostedMessage{
174196
ChannelID: channelID,
175197
Text: text,
176198
Attachments: attachments,
177199
})
200+
m.mu.Unlock()
178201
if m.postThreadFunc != nil {
179202
return m.postThreadFunc(ctx, channelID, text, attachments)
180203
}
181204
return "1234567890.123456", nil
182205
}
183206

184207
func (m *mockSlackClient) UpdateMessage(ctx context.Context, channelID, timestamp, text string) error {
208+
m.mu.Lock()
185209
m.updatedMessages = append(m.updatedMessages, mockUpdatedMessage{
186210
ChannelID: channelID,
187211
Timestamp: timestamp,
188212
Text: text,
189213
})
214+
m.mu.Unlock()
190215
if m.updateMessageFunc != nil {
191216
return m.updateMessageFunc(ctx, channelID, timestamp, text)
192217
}
193218
return nil
194219
}
195220

196221
func (m *mockSlackClient) UpdateDMMessage(ctx context.Context, userID, prURL, text string) error {
222+
m.mu.Lock()
197223
m.updatedDMMessage = append(m.updatedDMMessage, mockUpdatedDMMessage{
198224
UserID: userID,
199225
PRURL: prURL,
200226
Text: text,
201227
})
228+
m.mu.Unlock()
202229
if m.updateDMMessageFunc != nil {
203230
return m.updateDMMessageFunc(ctx, userID, prURL, text)
204231
}
@@ -363,6 +390,7 @@ func (m *mockUserMapper) FormatUserMentions(ctx context.Context, githubUsers []s
363390

364391
// mockTracker is a simple mock for notification tracking in tests.
365392
type mockTracker struct {
393+
mu sync.Mutex
366394
channelNotified bool
367395
userTags []mockUserTag
368396
tagInfoByUser map[string]TagInfo // Map from slackUserID to TagInfo for testing
@@ -378,10 +406,14 @@ type mockUserTag struct {
378406
}
379407

380408
func (m *mockTracker) UpdateChannelNotification(workspaceID, owner, repo string, prNumber int) {
409+
m.mu.Lock()
410+
defer m.mu.Unlock()
381411
m.channelNotified = true
382412
}
383413

384414
func (m *mockTracker) UpdateUserPRChannelTag(workspaceID, slackUserID, channelID, owner, repo string, prNumber int) {
415+
m.mu.Lock()
416+
defer m.mu.Unlock()
385417
m.userTags = append(m.userTags, mockUserTag{
386418
workspaceID: workspaceID,
387419
slackUserID: slackUserID,
@@ -393,6 +425,8 @@ func (m *mockTracker) UpdateUserPRChannelTag(workspaceID, slackUserID, channelID
393425
}
394426

395427
func (m *mockTracker) LastUserPRChannelTag(workspaceID, slackUserID, owner, repo string, prNumber int) TagInfo {
428+
m.mu.Lock()
429+
defer m.mu.Unlock()
396430
if m.tagInfoByUser != nil {
397431
if tagInfo, ok := m.tagInfoByUser[slackUserID]; ok {
398432
return tagInfo
@@ -403,6 +437,7 @@ func (m *mockTracker) LastUserPRChannelTag(workspaceID, slackUserID, owner, repo
403437

404438
// mockNotifier is a simple mock for notification manager in tests.
405439
type mockNotifier struct {
440+
mu sync.Mutex
406441
Tracker *mockTracker
407442
notifyUserError error
408443
notifyCalls []notifyUserCall
@@ -417,12 +452,14 @@ type notifyUserCall struct {
417452

418453
// NotifyUser mocks the notify.Manager.NotifyUser method.
419454
func (m *mockNotifier) NotifyUser(ctx context.Context, workspaceID, userID, channelID, channelName string, pr interface{}) error {
455+
m.mu.Lock()
420456
m.notifyCalls = append(m.notifyCalls, notifyUserCall{
421457
workspaceID: workspaceID,
422458
userID: userID,
423459
channelID: channelID,
424460
channelName: channelName,
425461
})
462+
m.mu.Unlock()
426463
return m.notifyUserError
427464
}
428465

pkg/slack/additional_functions_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010

1111
// TestPostThreadReply tests posting a reply to a thread.
1212
func TestPostThreadReply(t *testing.T) {
13+
t.Parallel()
14+
1315
mockSlack := slacktest.New()
1416
defer mockSlack.Close()
1517

@@ -46,6 +48,8 @@ func TestPostThreadReply(t *testing.T) {
4648

4749
// TestHasRecentDMAboutPR_NoRecent tests when no recent DM exists.
4850
func TestHasRecentDMAboutPR_NoRecent(t *testing.T) {
51+
t.Parallel()
52+
4953
mockSlack := slacktest.New()
5054
defer mockSlack.Close()
5155

@@ -70,6 +74,8 @@ func TestHasRecentDMAboutPR_NoRecent(t *testing.T) {
7074

7175
// TestSaveDMMessageInfo tests saving DM message information.
7276
func TestSaveDMMessageInfo(t *testing.T) {
77+
t.Parallel()
78+
7379
mockSlack := slacktest.New()
7480
defer mockSlack.Close()
7581

pkg/slack/api_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
)
1010

1111
func TestSlackAPIWrapper(t *testing.T) {
12+
t.Parallel()
13+
1214
ctx := context.Background()
1315

1416
t.Run("RawClient", func(t *testing.T) {

pkg/slack/api_wrapper_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111

1212
// TestSlackAPIWrapperIntegration tests the actual slackAPIWrapper with a mock HTTP server.
1313
func TestSlackAPIWrapperIntegration(t *testing.T) {
14+
t.Parallel()
15+
1416
// Create a mock HTTP server that responds to Slack API calls
1517
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1618
// Return simple successful responses for all endpoints

pkg/slack/client_additional_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
)
1212

1313
func TestUpdateDMMessage(t *testing.T) {
14+
t.Parallel()
15+
1416
ctx := context.Background()
1517

1618
t.Run("no_state_store", func(t *testing.T) {
@@ -28,6 +30,8 @@ func TestUpdateDMMessage(t *testing.T) {
2830
}
2931

3032
func TestSearchMessages(t *testing.T) {
33+
t.Parallel()
34+
3135
ctx := context.Background()
3236

3337
t.Run("success", func(t *testing.T) {
@@ -83,6 +87,8 @@ func TestSearchMessages(t *testing.T) {
8387
}
8488

8589
func TestAPI(t *testing.T) {
90+
t.Parallel()
91+
8692
t.Run("wrapper_returns_raw_client", func(t *testing.T) {
8793
rawClient := slack.New("test-token")
8894
wrapper := newSlackAPIWrapper(rawClient)
@@ -112,6 +118,8 @@ func TestAPI(t *testing.T) {
112118
}
113119

114120
func TestResolveChannelID(t *testing.T) {
121+
t.Parallel()
122+
115123
ctx := context.Background()
116124

117125
t.Run("cached_channel", func(t *testing.T) {
@@ -194,6 +202,8 @@ func TestResolveChannelID(t *testing.T) {
194202
}
195203

196204
func TestIsUserInChannel(t *testing.T) {
205+
t.Parallel()
206+
197207
ctx := context.Background()
198208

199209
t.Run("user_in_channel", func(t *testing.T) {
@@ -259,6 +269,8 @@ func TestIsUserInChannel(t *testing.T) {
259269
}
260270

261271
func TestPublishHomeView(t *testing.T) {
272+
t.Parallel()
273+
262274
ctx := context.Background()
263275

264276
t.Run("success", func(t *testing.T) {
@@ -307,6 +319,8 @@ func TestPublishHomeView(t *testing.T) {
307319
}
308320

309321
func TestChannelHistory(t *testing.T) {
322+
t.Parallel()
323+
310324
ctx := context.Background()
311325

312326
t.Run("success", func(t *testing.T) {
@@ -412,6 +426,8 @@ func (m *programmableMockStateStore) SaveDMMessage(userID, prURL string, info st
412426
}
413427

414428
func TestUpdateDMMessage_Complete(t *testing.T) {
429+
t.Parallel()
430+
415431
ctx := context.Background()
416432
prURL := "https://github.com/test/repo/pull/123"
417433

pkg/slack/client_coverage_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import (
1212

1313
// TestPostThreadReply_ErrorCases tests error handling in PostThreadReply.
1414
func TestPostThreadReply_ErrorCases(t *testing.T) {
15+
t.Parallel()
16+
1517
ctx := context.Background()
1618

1719
t.Run("channel_not_found", func(t *testing.T) {
@@ -123,6 +125,8 @@ func TestPostThreadReply_ErrorCases(t *testing.T) {
123125

124126
// TestHasRecentDMAboutPR_WithStateStore tests HasRecentDMAboutPR with a state store.
125127
func TestHasRecentDMAboutPR_WithStateStore(t *testing.T) {
128+
t.Parallel()
129+
126130
ctx := context.Background()
127131
prURL := "https://github.com/test/repo/pull/123"
128132

@@ -244,6 +248,8 @@ func TestHasRecentDMAboutPR_WithStateStore(t *testing.T) {
244248

245249
// TestSendDirectMessage_Errors tests error handling in SendDirectMessage.
246250
func TestSendDirectMessage_Errors(t *testing.T) {
251+
t.Parallel()
252+
247253
ctx := context.Background()
248254

249255
t.Run("open_conversation_fails", func(t *testing.T) {
@@ -323,6 +329,8 @@ func TestSendDirectMessage_Errors(t *testing.T) {
323329

324330
// TestSaveDMMessageInfo_WithStore tests SaveDMMessageInfo with a state store.
325331
func TestSaveDMMessageInfo_WithStore(t *testing.T) {
332+
t.Parallel()
333+
326334
ctx := context.Background()
327335

328336
t.Run("saves_to_store", func(t *testing.T) {
@@ -376,6 +384,8 @@ func TestSaveDMMessageInfo_WithStore(t *testing.T) {
376384

377385
// TestPostThread_Errors tests error handling in PostThread.
378386
func TestPostThread_Errors(t *testing.T) {
387+
t.Parallel()
388+
379389
ctx := context.Background()
380390

381391
t.Run("channel_not_found_during_check", func(t *testing.T) {
@@ -495,6 +505,8 @@ func TestPostThread_Errors(t *testing.T) {
495505

496506
// TestUpdateMessage_EdgeCases tests edge cases in UpdateMessage.
497507
func TestUpdateMessage_EdgeCases(t *testing.T) {
508+
t.Parallel()
509+
498510
ctx := context.Background()
499511

500512
t.Run("message_not_found", func(t *testing.T) {

0 commit comments

Comments
 (0)