Skip to content

Conversation

@tomerqodo
Copy link

@tomerqodo tomerqodo commented Jan 22, 2026

Benchmark PR from qodo-benchmark#236

Summary by CodeRabbit

  • Tests
    • Updated test infrastructure to support asynchronous lifecycle methods across multiple test suites, enabling better async/await patterns in test execution.
    • Enhanced thread safety and isolation for test classes running on the main thread.
    • Improved concurrency support in mock objects and test utilities for better test reliability.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 22, 2026

Walkthrough

This PR systematically converts test lifecycle methods from synchronous to asynchronous throwing variants across multiple test classes, updates setUp and tearDown method signatures to async throws, and adds @MainActor annotations to various test classes for main-thread isolation.

Changes

Cohort / File(s) Summary
Test lifecycle async conversion
SyncContentSettingsViewControllerTests.swift, FxAWebViewModelTests.swift, RatingPromptManagerTests.swift, HistoryPanelTests.swift, MainMenu/MainMenuConfigurationUtilityTests.swift, MainMenu/MainMenuCoordinatorTests.swift, MainMenu/MainMenuMiddlewareTests.swift, Microsurvey/MicrosurveyCoordinatorTests.swift, Microsurvey/MicrosurveyMiddlewareTests.swift, OnboardingTests/IntroViewControllerTests.swift, OnboardingTests/IntroViewModelTests.swift
Convert setUp() and tearDown() from synchronous to async throws variants; update super calls to try await super.setUp()/tearDown()
Test lifecycle async + @MainActor isolation
Frontend/StoriesFeed/StoriesFeedDiffableDataSourceTests.swift, Library/Bookmarks/EditBookmarkDataSourceTests.swift, MainMenu/MainMenuViewControllerTests.swift, Microsurvey/MicrosurveyViewControllerTests.swift, NativeErrorPage/NativeErrorPageViewControllerTests.swift
Add @MainActor annotation to test class and convert lifecycle methods to async throws
Test lifecycle async + @MainActor removal
Library/Bookmarks/EditBookmarkViewModelTests.swift
Remove @MainActor attribute and convert lifecycle methods to async throws
Helper and Mock adjustments
Helpers/NotificationManagerTests.swift
Change closure to capture center parameter; replace XCTAssertTrue with Swift assert statements
Mock concurrency compliance
Mocks/MockBrowserViewControllerWebViewDelegates.swift, Mocks/MockProfile.swift, Mocks/MockUserNotificationCenter.swift
Make MockURLAuthenticationChallengeSender final; add @Sendable to completion closure in MockTabQueue.getQueuedTabs(); add @unchecked Sendable conformance to MockUserNotificationCenter

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Async and await, now our tests shall flow,
Lifecycle methods with a concurrent glow,
From sync to async, the rabbit did trace,
Main actors dancing at a swifter pace! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: Swift 6 migration fixes for unit test warnings, with specific reference to the FXIOS-14344 ticket.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In
`@firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/StoriesFeed/StoriesFeedDiffableDataSourceTests.swift`:
- Around line 28-33: The tearDown method calls try await super.tearDown() too
early; move the super.tearDown() call to the end of tearDown so test-specific
cleanup runs first: nil out diffableDataSource and collectionView and call
DependencyHelperMock().reset() before invoking try await super.tearDown() in the
override of func tearDown() async throws (method name: tearDown; symbols:
diffableDataSource, collectionView, DependencyHelperMock().reset()).

In
`@firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/NotificationManagerTests.swift`:
- Around line 25-30: Replace the synchronous assert() calls in
testRequestAuthorization with XCTest assertions and an expectation: use an
XCTestExpectation, call notificationManager.requestAuthorization and in its
completion fulfill the expectation and use XCTAssertTrue for granted and
XCTAssertTrue(center?.requestAuthorizationWasCalled ?? false) (or XCTAssertEqual
as appropriate), then waitForExpectations with a timeout; this ensures
testRequestAuthorization waits for the asynchronous completion and reports
failures via XCTest instead of crashing.
🧹 Nitpick comments (6)
firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockBrowserViewControllerWebViewDelegates.swift (1)

23-45: Consider adding final to MockNavigationAction for consistency.

This mock class is the only one in the file not marked as final. For consistency with MockFrameInfo, MockURLAuthenticationChallengeSender, and MockFileManager, consider making this class final as well.

♻️ Suggested change
-class MockNavigationAction: WKNavigationAction {
+final class MockNavigationAction: WKNavigationAction {
firefox-ios/firefox-ios-tests/Tests/ClientTests/NativeErrorPage/NativeErrorPageViewControllerTests.swift (1)

19-22: Consider reordering tearDown: reset dependencies before calling super.

The current order calls super.tearDown() before DependencyHelperMock().reset(). Standard tearDown practice is to clean up local/test state first, then call the superclass method. This is the inverse of setUp order.

Suggested fix
     override func tearDown() {
-        super.tearDown()
         DependencyHelperMock().reset()
+        super.tearDown()
     }
firefox-ios/firefox-ios-tests/Tests/ClientTests/MainMenu/MainMenuCoordinatorTests.swift (1)

20-23: Consider setting mockRouter to nil in tearDown for test isolation.

The mockRouter property is initialized in setUp but not cleaned up in tearDown. While this may work in practice since a new instance is created in each setUp, explicitly nilling it out ensures proper test isolation and matches the pattern used in other test files in this PR.

Suggested fix
     override func tearDown() async throws {
         DependencyHelperMock().reset()
+        mockRouter = nil
         try await super.tearDown()
     }
firefox-ios/firefox-ios-tests/Tests/ClientTests/OnboardingTests/IntroViewControllerTests.swift (2)

20-23: Missing DependencyHelperMock().reset() in tearDown.

The setUp calls DependencyHelperMock().bootstrapDependencies(), but tearDown doesn't call reset(). Other test files in this PR (e.g., MainMenuCoordinatorTests, SyncContentSettingsViewControllerTests) consistently reset dependencies in tearDown. This could affect test isolation.

Suggested fix
     override func tearDown() async throws {
+        DependencyHelperMock().reset()
         mockNotificationCenter = nil
         try await super.tearDown()
     }

77-78: Redundant @MainActor annotation.

This method-level @MainActor annotation is redundant since the class is already annotated with @MainActor at line 10. The method will inherit the actor isolation from the class.

Suggested fix
-    `@MainActor`
     func testViewMovesToNextScreenAfterNotification() {
firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/StoriesFeed/StoriesFeedDiffableDataSourceTests.swift (1)

44-45: Redundant @MainActor annotation.

This method-level @MainActor annotation is redundant since the class is already annotated with @MainActor at line 11. The method inherits actor isolation from the class.

Suggested fix
-    `@MainActor`
     func test_updateSnapshot_withValidState_returnsStories() throws {
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6d2792c and ac31d8c.

📒 Files selected for processing (21)
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/StoriesFeed/StoriesFeedDiffableDataSourceTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/SyncContentSettingsViewControllerTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/FxAWebViewModelTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/NotificationManagerTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/RatingPromptManagerTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/Library/Bookmarks/EditBookmarkDataSourceTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/Library/Bookmarks/EditBookmarkViewModelTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/Library/HistoryPanelTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/MainMenu/MainMenuConfigurationUtilityTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/MainMenu/MainMenuCoordinatorTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/MainMenu/MainMenuMiddlewareTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/MainMenu/MainMenuViewControllerTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/Microsurvey/MicrosurveyCoordinatorTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/Microsurvey/MicrosurveyMiddlewareTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/Microsurvey/MicrosurveyViewControllerTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockBrowserViewControllerWebViewDelegates.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockProfile.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockUserNotificationCenter.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/NativeErrorPage/NativeErrorPageViewControllerTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/OnboardingTests/IntroViewControllerTests.swift
  • firefox-ios/firefox-ios-tests/Tests/ClientTests/OnboardingTests/IntroViewModelTests.swift
🔇 Additional comments (18)
firefox-ios/firefox-ios-tests/Tests/ClientTests/MainMenu/MainMenuMiddlewareTests.swift (2)

15-20: LGTM!

The conversion to async throws with try await super.setUp() called first follows the correct XCTest lifecycle pattern for Swift 6 migration. Parent setup executes before child initialization.


22-27: LGTM!

The tearDown order is correct: child cleanup (reset dependencies, nil out mocks, reset store) happens before calling try await super.tearDown(). This aligns with the commit message "Fix teardown methods orders" and follows the proper pattern of reversing the setup sequence.

firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockBrowserViewControllerWebViewDelegates.swift (1)

48-54: LGTM! Adding final is appropriate for this mock class.

The change aligns well with Swift 6 migration goals and is consistent with other mocks in this file (MockFrameInfo, MockFileManager).

firefox-ios/firefox-ios-tests/Tests/ClientTests/OnboardingTests/IntroViewModelTests.swift (1)

16-25: LGTM!

The migration to async throws lifecycle methods is correct. The tearDown properly nullifies nimbusUtility before calling super.tearDown(), which follows the recommended cleanup order.

firefox-ios/firefox-ios-tests/Tests/ClientTests/MainMenu/MainMenuViewControllerTests.swift (1)

10-22: LGTM on the @MainActor annotation.

Adding @MainActor is appropriate since MainMenuViewController is a UIKit view controller requiring main thread access.

Note: Unlike other test files in this PR (e.g., MainMenuConfigurationUtilityTests), the setUp/tearDown methods here remain synchronous. This works fine but creates slight inconsistency across the test suite. Consider aligning with the async pattern if desired.

firefox-ios/firefox-ios-tests/Tests/ClientTests/MainMenu/MainMenuConfigurationUtilityTests.swift (1)

17-27: LGTM!

The migration to async throws lifecycle methods is correct. The tearDown properly cleans up dependencies and nullifies the utility before calling super.tearDown().

firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockUserNotificationCenter.swift (1)

9-9: Pragmatic choice for test code, but note the implications.

Adding @unchecked Sendable suppresses concurrency warnings but the class has unsynchronized mutable state (pendingRequests, *WasCalled flags). This is acceptable for test mocks that run sequentially, but be aware this asserts thread-safety that isn't actually enforced.

If tests ever run concurrently or the mock is captured across actor boundaries with concurrent access, data races could occur.

firefox-ios/firefox-ios-tests/Tests/ClientTests/Library/Bookmarks/EditBookmarkDataSourceTests.swift (1)

8-18: Swift 6 XCTest lifecycle migration looks good.

@MainActor plus async/throws setup/teardown with awaited super calls is consistent with the rest of the migration.

Also applies to: 25-28

firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockProfile.swift (1)

93-97: Good concurrency annotation update.

Adding @MainActor and @Sendable to the completion keeps the API aligned with actor isolation expectations.

firefox-ios/firefox-ios-tests/Tests/ClientTests/Microsurvey/MicrosurveyViewControllerTests.swift (1)

10-11: Main-actor isolation for UI tests is appropriate.

firefox-ios/firefox-ios-tests/Tests/ClientTests/Library/HistoryPanelTests.swift (1)

14-16: Async XCTest lifecycle update looks correct.

Also applies to: 21-25

firefox-ios/firefox-ios-tests/Tests/ClientTests/Microsurvey/MicrosurveyCoordinatorTests.swift (1)

15-16: Async setup/teardown conversion is solid.

Also applies to: 22-25

firefox-ios/firefox-ios-tests/Tests/ClientTests/Microsurvey/MicrosurveyMiddlewareTests.swift (1)

15-16: Async lifecycle migration is consistent and clean.

Also applies to: 22-27

firefox-ios/firefox-ios-tests/Tests/ClientTests/Library/Bookmarks/EditBookmarkViewModelTests.swift (1)

33-45: LGTM! Async lifecycle methods are correctly implemented.

The setUp correctly calls super.setUp() first before initializing test fixtures, and tearDown properly cleans up test-specific resources before calling super.tearDown() last. This follows the correct order for XCTest lifecycle methods.

firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/SyncContentSettingsViewControllerTests.swift (1)

15-29: LGTM! Async lifecycle methods are correctly implemented.

The lifecycle methods follow the correct pattern: setUp calls super first then initializes test fixtures, and tearDown cleans up dependencies and test objects before calling super last.

firefox-ios/firefox-ios-tests/Tests/ClientTests/FxAWebViewModelTests.swift (1)

14-27: LGTM! Async lifecycle methods are correctly implemented.

The setUp and tearDown methods follow the correct ordering pattern for XCTest async lifecycle methods, with proper resource initialization and cleanup.

firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/RatingPromptManagerTests.swift (2)

22-24: Async setUp migration looks correct.
Awaiting super.setUp() before initializing fixtures is appropriate.


36-45: Async tearDown migration looks correct.
Using try await super.tearDown() in the async override is consistent with XCTest’s async lifecycle.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +28 to 33
override func tearDown() async throws {
try await super.tearDown()
diffableDataSource = nil
collectionView = nil
DependencyHelperMock().reset()
super.tearDown()
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incorrect tearDown order: super.tearDown() should be called last.

The super.tearDown() call on line 29 should be the last statement in the method, not the first. Test-specific cleanup (nilling out diffableDataSource, collectionView, and resetting dependencies) should happen before calling the superclass tearDown. This is the opposite order of setUp where super is called first.

The other test files in this PR correctly place super.tearDown() at the end.

Proposed fix
     override func tearDown() async throws {
-        try await super.tearDown()
         diffableDataSource = nil
         collectionView = nil
         DependencyHelperMock().reset()
+        try await super.tearDown()
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
override func tearDown() async throws {
try await super.tearDown()
diffableDataSource = nil
collectionView = nil
DependencyHelperMock().reset()
super.tearDown()
}
override func tearDown() async throws {
diffableDataSource = nil
collectionView = nil
DependencyHelperMock().reset()
try await super.tearDown()
}
🤖 Prompt for AI Agents
In
`@firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/StoriesFeed/StoriesFeedDiffableDataSourceTests.swift`
around lines 28 - 33, The tearDown method calls try await super.tearDown() too
early; move the super.tearDown() call to the end of tearDown so test-specific
cleanup runs first: nil out diffableDataSource and collectionView and call
DependencyHelperMock().reset() before invoking try await super.tearDown() in the
override of func tearDown() async throws (method name: tearDown; symbols:
diffableDataSource, collectionView, DependencyHelperMock().reset()).

Comment on lines 25 to 30
func testRequestAuthorization() {
notificationManager.requestAuthorization { (granted, error) in
XCTAssertTrue(granted)
XCTAssertTrue(self.center.requestAuthorizationWasCalled)
notificationManager.requestAuthorization { [center] (granted, error) in
assert(granted, "Authorization should be granted")
assert(center?.requestAuthorizationWasCalled ?? false, "requestAuthorization should be called")
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Using assert() instead of XCTAssert* will not report test failures correctly.

The change from XCTAssertTrue to assert() is problematic:

  1. assert() doesn't integrate with XCTest—failures won't be reported as test failures in test results
  2. assert() crashes the process rather than gracefully failing the test
  3. The completion handler executes asynchronously but the test doesn't wait for it, so assertions may not run before the test completes
Suggested fix using expectations
     func testRequestAuthorization() {
+        let expectation = expectation(description: "Authorization callback")
         notificationManager.requestAuthorization { [center] (granted, error) in
-            assert(granted, "Authorization should be granted")
-            assert(center?.requestAuthorizationWasCalled ?? false, "requestAuthorization should be called")
+            XCTAssertTrue(granted, "Authorization should be granted")
+            XCTAssertTrue(center?.requestAuthorizationWasCalled ?? false, "requestAuthorization should be called")
+            expectation.fulfill()
         }
+        wait(for: [expectation], timeout: 1.0)
     }
🤖 Prompt for AI Agents
In
`@firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/NotificationManagerTests.swift`
around lines 25 - 30, Replace the synchronous assert() calls in
testRequestAuthorization with XCTest assertions and an expectation: use an
XCTestExpectation, call notificationManager.requestAuthorization and in its
completion fulfill the expectation and use XCTAssertTrue for granted and
XCTAssertTrue(center?.requestAuthorizationWasCalled ?? false) (or XCTAssertEqual
as appropriate), then waitForExpectations with a timeout; this ensures
testRequestAuthorization waits for the asynchronous completion and reports
failures via XCTest instead of crashing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants