Skip to content
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

[ECO-4990] Switch to Swift Testing #61

Merged
merged 1 commit into from
Sep 23, 2024

Conversation

lawrence-forooghian
Copy link
Collaborator

@lawrence-forooghian lawrence-forooghian commented Sep 19, 2024

Resolves #55. See commit message for more details.

Currently in the middle of some back-and-forth on whether it's OK to write await #expect(…) (see Swift Forums issue linked to in commit message), but I think people can take a look at this PR anyway. — done, been told it’s best not to do that so have switched it to #expect(await …), accepting the poorer failure messages.

Summary by CodeRabbit

Summary by CodeRabbit

  • Refactor

    • Transitioned all test classes from XCTest framework to a new testing framework, simplifying the structure by using structs and @Test annotations.
    • Updated assertion syntax across all tests, enhancing readability and consistency.
    • Renamed various test methods to align with new framework conventions while maintaining original functionality.
  • Chores

    • Improved usability of error assertion helper function, enhancing its applicability in various contexts.

Copy link

coderabbitai bot commented Sep 19, 2024

Walkthrough

The changes involve a comprehensive transition from the XCTest framework to a new testing framework across multiple test files. This includes restructuring test classes into structs, changing method definitions to use @Test annotations, and updating assertion syntax from XCTest methods to the new framework's conventions. The modifications aim to modernize the testing approach while retaining the core functionality of the tests.

Changes

Files Change Summary
Tests/AblyChatTests/DefaultChatClientTests.swift, DefaultInternalLoggerTests.swift, DefaultRoomStatusTests.swift, DefaultRoomTests.swift, DefaultRoomsTests.swift, InternalLoggerTests.swift, MessageSubscriptionTests.swift, SubscriptionTests.swift Transitioned from XCTest to a new testing framework, converting classes to structs, renaming test methods, and updating assertion syntax from XCTAssert to #expect and #require.
Tests/AblyChatTests/Helpers/Helpers.swift Replaced assertIsChatError function with isChatError, changing its functionality to return a Boolean instead of throwing errors.

Assessment against linked issues

Objective Addressed Explanation
Switch to Swift Testing (ECO-4990, #55)

Possibly related PRs

  • [ECO-4965] Implement logging #39: This PR involves changes in multiple test files to adapt to a new testing framework, which is relevant to the logging infrastructure introduced in this PR.

Suggested reviewers

  • maratal
  • umair-ably

Poem

🐇 In the land of code where tests do play,
A new framework hops in, brightening the way.
With structs and tests, oh what a delight,
Assertions now dance in the soft moonlight.
So let’s cheer for changes, both bold and spry,
As we leap into testing, oh my, oh my! 🌟


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    -- I pushed a fix in commit <commit_id>, please review it.
    -- Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    -- @coderabbitai generate unit testing code for this file.
    -- @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    -- @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    -- @coderabbitai read src/utils.ts and generate unit testing code.
    -- @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    -- @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

Outside diff range and nitpick comments (3)
Tests/AblyChatTests/DefaultInternalLoggerTests.swift (1)

50-50: Nitpick: Consistency in checking for nil

Consider using #require for asserting nil values for consistency with other tests.

Apply this diff to improve consistency:

-    #expect(logHandler.logArguments == nil)
+    #require(logHandler.logArguments == nil)
Tests/AblyChatTests/DefaultRoomTests.swift (2)

30-30: Check clarity of failure messages in looped assertions

Using #expect inside a loop is effective, but if an assertion fails, it might be unclear which iteration caused the failure. Consider enhancing the assertion to include the channel name for better diagnostics.


92-92: Enhance failure messages in looped assertions

Similar to previous loops, if an assertion fails inside the loop, identifying the specific channel can be challenging. Include additional context in the assertion to aid in debugging.

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 7ef0a0e and 601248a.

Files selected for processing (9)
  • Tests/AblyChatTests/DefaultChatClientTests.swift (2 hunks)
  • Tests/AblyChatTests/DefaultInternalLoggerTests.swift (3 hunks)
  • Tests/AblyChatTests/DefaultRoomStatusTests.swift (2 hunks)
  • Tests/AblyChatTests/DefaultRoomTests.swift (5 hunks)
  • Tests/AblyChatTests/DefaultRoomsTests.swift (4 hunks)
  • Tests/AblyChatTests/Helpers/Helpers.swift (1 hunks)
  • Tests/AblyChatTests/InternalLoggerTests.swift (1 hunks)
  • Tests/AblyChatTests/MessageSubscriptionTests.swift (2 hunks)
  • Tests/AblyChatTests/SubscriptionTests.swift (1 hunks)
Additional context used
SwiftLint
Tests/AblyChatTests/DefaultRoomsTests.swift

[Error] 3-3: Imports should be sorted

(sorted_imports)

Additional comments not posted (35)
Tests/AblyChatTests/Helpers/Helpers.swift (1)

8-15: Excellent refactoring of the error assertion function!

The changes made to the isChatError function significantly improve its usability and simplify the logic:

  • Changing the return type to Bool allows the function to be used in contexts where a simple Boolean check is sufficient, rather than throwing exceptions.
  • Using a guard statement to check the error type and returning false if it doesn't match eliminates the need for unwrapping and assertions, reducing the chances of exceptions being thrown.
  • Checking the error properties only if the error is of the expected type simplifies the logic and improves readability.

These changes align with the PR objectives of modernizing the testing approach and enhancing performance. Great job!

Tests/AblyChatTests/InternalLoggerTests.swift (5)

2-2: LGTM!

The import statement change aligns with the PR objective of migrating from XCTest to Swift Testing.


4-4: LGTM!

The change from class to struct aligns with the recommended way to define test suites in Swift Testing.


5-6: LGTM!

The changes to the test method, including the @Test attribute and the removal of the test prefix, align with the conventions in Swift Testing and the stated PR objectives.


12-12: LGTM!

The change from XCTAssertNoThrow to #require aligns with the assertion syntax in Swift Testing.


14-16: LGTM!

The change from XCTAssertEqual to #expect aligns with the assertion syntax in Swift Testing.

Tests/AblyChatTests/SubscriptionTests.swift (2)

6-10: LGTM!

The test has been successfully refactored to use the new Swift Testing framework while maintaining the original test logic. The #expect assertion correctly verifies the emitted elements from the subscription.


13-22: LGTM!

The test has been successfully refactored to use the new Swift Testing framework while maintaining the original test logic. The #expect assertion correctly verifies the emitted elements from the subscription.

Tests/AblyChatTests/DefaultChatClientTests.swift (4)

2-2: Looks good!

The import of the Testing framework aligns with the PR objective of transitioning to Swift Testing.


Line range hint 4-28: Great work on transitioning the tests to Swift Testing!

The changes effectively migrate the test structure and assertions to align with Swift Testing conventions while preserving the core test logic. This is a significant step towards modernizing the testing approach.


25-25: Looks good!

The use of #require to unwrap rooms aligns with Swift Testing syntax while maintaining the assertion logic.


26-27: Great use of #expect for assertions!

The assertions effectively verify the realtime and clientOptions properties of defaultRooms using Swift Testing's #expect syntax.

Tests/AblyChatTests/DefaultRoomStatusTests.swift (3)

5-8: LGTM!

The test logic is correct, and the changes align with the migration to the new testing framework.


11-14: LGTM!

The test logic is correct, and the changes align with the migration to the new testing framework.


Line range hint 17-39: LGTM!

The test logic is correct, and the changes align with the migration to the new testing framework. The use of #require enhances clarity in the test's intent.

Tests/AblyChatTests/MessageSubscriptionTests.swift (3)

26-30: LGTM!

The test logic is correct and aligns with the objectives of migrating to the new testing framework. The use of @Test annotation and #expect assertion syntax is appropriate.


33-42: LGTM!

The test logic is correct and aligns with the objectives of migrating to the new testing framework. The use of @Test annotation and #expect assertion syntax is appropriate.


45-53: LGTM!

The test logic is correct and aligns with the objectives of migrating to the new testing framework. The use of @Test annotation, #require for unwrapping optionals, and #expect assertion syntax is appropriate.

Tests/AblyChatTests/DefaultRoomsTests.swift (3)

Line range hint 7-22: LGTM!

The test has been successfully updated to use the new testing framework syntax while preserving the original test logic. The assertions verify the expected behavior of the get method.


Line range hint 26-40: LGTM!

The test has been successfully updated to use the new testing framework syntax while preserving the original test logic. The assertion verifies that calling the get method with the same room ID returns the same room object.


Line range hint 44-66: LGTM!

The test has been successfully updated to use the new testing framework syntax while preserving the original test logic. The assertion verifies that calling the get method with the same room ID but different options throws an inconsistentRoomOptions error.

Tests/AblyChatTests/DefaultInternalLoggerTests.swift (6)

2-2: Approved: Importing the Testing framework

The addition of import Testing aligns with the migration to the new Swift Testing framework.


4-4: Approved: Transition to struct-based test suites

Switching from a class to a struct for the test suite is appropriate with the new testing framework and reflects the updated testing conventions.


5-10: Approved: Test for default logger initialization

The defaults() test correctly verifies that DefaultInternalLogger initializes with the expected default log handler and log level.


Line range hint 13-30: Approved: Test for logging behavior at default log level

The log() test effectively checks that the logger logs messages appropriately when the log level meets the required severity, including interpolation of code location into the message.


27-27: Confirm necessity of try with #require

Using try with #require suggests that logHandler.logArguments might throw an error or be asynchronous. Ensure that this is intended and that logHandler.logArguments requires error handling.


Line range hint 33-50: Approved: Test for logging suppression at lower log levels

The log_whenLogLevelArgumentIsLessSevereThanLogLevelProperty_itDoesNotLog() test correctly verifies that the logger suppresses logging when the message's log level is less severe than the logger's configured log level.

Tests/AblyChatTests/DefaultRoomTests.swift (8)

3-3: Properly import the Testing framework

The addition of import Testing correctly introduces the new testing framework needed for Swift Testing.


5-5: Verify the impact of changing from class to struct

Changing DefaultRoomTests from a class to a struct alters its reference semantics to value semantics. Ensure this change doesn't affect any inherited behaviors or shared states within your test suite.


6-6: Correct use of @test annotation

The @Test annotation is properly applied to the test method, enabling it to be recognized by the Swift Testing framework.


37-37: @test annotation correctly added

The test method is appropriately annotated with @Test, ensuring it is executed by the testing framework.


65-65: Ensure correct error comparison in assertion

The assertion compares roomAttachError and channelAttachError using identity (===). Verify that both errors are expected to be the same instance. If only the error information needs to match, consider comparing their properties instead.


68-68: Proper application of @test annotation

The @Test annotation is correctly used, allowing the test method to be recognized by the framework.


99-99: @test annotation correctly used

The test method is correctly annotated with @Test, which is necessary for the Swift Testing framework.


127-127: Verify error identity assertion

Confirm that using the identity operator (===) is appropriate for comparing roomDetachError and channelDetachError. If they are not guaranteed to be the same instance, consider comparing their error codes or messages instead.

Tests/AblyChatTests/DefaultRoomTests.swift Show resolved Hide resolved
Tests/AblyChatTests/DefaultRoomTests.swift Show resolved Hide resolved
@lawrence-forooghian lawrence-forooghian force-pushed the 55-switch-to-swift-testing branch 2 times, most recently from 86614e6 to ca271d6 Compare September 19, 2024 20:19
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: 0

Outside diff range and nitpick comments (1)
Tests/AblyChatTests/Helpers/Helpers.swift (1)

8-8: Consider renaming the maybeError parameter to error for better readability.

Since the function no longer force unwraps the optional error, the maybe prefix in the parameter name is not necessary. Renaming it to error would improve readability without losing clarity.

Apply this diff to rename the parameter:

-func isChatError(_ maybeError: (any Error)?, withCode code: AblyChat.ErrorCode) -> Bool {
+func isChatError(_ error: (any Error)?, withCode code: AblyChat.ErrorCode) -> Bool {
     guard let ablyError = maybeError as? ARTErrorInfo else {
         return false
     }
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 86614e6 and ca271d6.

Files selected for processing (9)
  • Tests/AblyChatTests/DefaultChatClientTests.swift (2 hunks)
  • Tests/AblyChatTests/DefaultInternalLoggerTests.swift (3 hunks)
  • Tests/AblyChatTests/DefaultRoomStatusTests.swift (2 hunks)
  • Tests/AblyChatTests/DefaultRoomTests.swift (5 hunks)
  • Tests/AblyChatTests/DefaultRoomsTests.swift (4 hunks)
  • Tests/AblyChatTests/Helpers/Helpers.swift (1 hunks)
  • Tests/AblyChatTests/InternalLoggerTests.swift (1 hunks)
  • Tests/AblyChatTests/MessageSubscriptionTests.swift (2 hunks)
  • Tests/AblyChatTests/SubscriptionTests.swift (1 hunks)
Files skipped from review as they are similar to previous changes (3)
  • Tests/AblyChatTests/DefaultRoomStatusTests.swift
  • Tests/AblyChatTests/InternalLoggerTests.swift
  • Tests/AblyChatTests/SubscriptionTests.swift
Additional context used
Learnings (3)
Tests/AblyChatTests/DefaultChatClientTests.swift (1)
Learnt from: lawrence-forooghian
PR: ably-labs/ably-chat-swift#61
File: Tests/AblyChatTests/DefaultRoomTests.swift:33-34
Timestamp: 2024-09-19T18:44:56.819Z
Learning: In Swift Testing, using `#expect` with `await` may result in less informative failure messages when debugging asynchronous tests.
Tests/AblyChatTests/DefaultRoomTests.swift (1)
Learnt from: lawrence-forooghian
PR: ably-labs/ably-chat-swift#61
File: Tests/AblyChatTests/DefaultRoomTests.swift:33-34
Timestamp: 2024-09-19T18:44:56.819Z
Learning: In Swift Testing, using `#expect` with `await` may result in less informative failure messages when debugging asynchronous tests.
Tests/AblyChatTests/DefaultRoomsTests.swift (1)
Learnt from: lawrence-forooghian
PR: ably-labs/ably-chat-swift#61
File: Tests/AblyChatTests/DefaultRoomTests.swift:33-34
Timestamp: 2024-09-19T18:44:56.819Z
Learning: In Swift Testing, using `#expect` with `await` may result in less informative failure messages when debugging asynchronous tests.
Additional comments not posted (28)
Tests/AblyChatTests/Helpers/Helpers.swift (2)

3-3: LGTM!

The import statement is correct and necessary for using the new testing framework.


6-15: Verify the function signature change in the codebase.

The new function implementation is correct and enhances usability by returning a Boolean value instead of throwing exceptions. However, ensure that all calls to assertIsChatError have been updated to use the new isChatError function and handle the Boolean return value appropriately.

Run the following script to verify the function usage:

Verification successful

To ensure a comprehensive verification, we need to check for other test files that might be using the isChatError function. Let's run an additional script to search for all test files and their contents.


It seems there was an issue with the 'rg' command in the previous script. Let's try a different approach using 'grep' to search for 'isChatError' usage in all test files.


Function signature change verified, consider expanding test coverage.

The verification process confirms that the isChatError function has been correctly implemented and is being used appropriately in the test files. The old assertIsChatError function has been completely removed, and the new isChatError function is being used with the correct syntax to handle its Boolean return value.

However, it's worth noting that the function is only used in one test file (DefaultRoomsTests.swift). Consider the following suggestions:

  • Review other test files to determine if additional test cases using isChatError would be beneficial for more comprehensive error handling coverage.
  • Ensure that all relevant error scenarios across different components of the AblyChatTests are adequately tested using this new function.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all calls to `assertIsChatError` have been updated to use `isChatError`.

# Test 1: Search for the old function usage. Expect: No occurrences.
rg --type swift $'assertIsChatError'

# Test 2: Search for the new function usage. Expect: Only occurrences with appropriate handling of the Boolean return value.
rg --type swift -A 5 $'isChatError'

Length of output: 784


Script:

#!/bin/bash
# Description: Find all test files and check for isChatError usage

# Find all test files
echo "All test files:"
fd -e swift -p 'Tests/'

# Search for isChatError usage in all test files
echo -e "\nisChatError usage in test files:"
rg --type swift -p 'Tests/' 'isChatError'

Length of output: 996


Script:

#!/bin/bash
# Description: Find isChatError usage in all test files using grep

echo "isChatError usage in test files:"
grep -r "isChatError" Tests/

Length of output: 357

Tests/AblyChatTests/DefaultChatClientTests.swift (2)

5-12: LGTM!

The test migration looks good. The logic remains the same, and the assertion has been correctly updated to use #expect from Swift Testing.


Line range hint 15-27: LGTM!

The test migration looks good. The logic remains the same, and the assertions have been correctly updated to use #expect and #require from Swift Testing.

Tests/AblyChatTests/DefaultInternalLoggerTests.swift (3)

5-10: LGTM!

The test logic remains the same, and the new #expect syntax is used correctly for assertions.


Line range hint 13-30: LGTM!

The test logic remains the same, and the new #require and #expect syntax is used correctly for assertions.


Line range hint 33-50: LGTM!

The test logic remains the same, and the new #expect syntax is used correctly for the assertion.

Tests/AblyChatTests/MessageSubscriptionTests.swift (3)

26-30: LGTM!

The test logic is correct and aligns with the migration objectives. The use of @Test annotation and #expect assertion syntax is consistent with the new testing framework.


33-42: LGTM!

The test logic is correct and aligns with the migration objectives. The use of @Test annotation and #expect assertion syntax is consistent with the new testing framework.


45-53: LGTM!

The test logic is correct and aligns with the migration objectives. The use of @Test annotation, #require for unwrapping optionals, and #expect assertion syntax is consistent with the new testing framework.

Tests/AblyChatTests/DefaultRoomsTests.swift (5)

4-4: LGTM!

Changing DefaultRoomsTests from a class to a struct aligns with the conventions of the new testing framework. Structs are value types and are more lightweight compared to reference types like classes.


Line range hint 6-21: LGTM!

The changes to the get_returnsRoomWithGivenID method align with the conventions of the new testing framework:

  • Renaming the method and adding the @Test annotation follows the new syntax.
  • Updating the assertions to use #require and #expect maintains the test logic while conforming to the new framework.

The core functionality of the test remains intact, ensuring that the get method returns a room with the given ID and options.


Line range hint 25-39: LGTM!

The changes to the get_returnsExistingRoomWithGivenID method align with the conventions of the new testing framework:

  • Renaming the method and adding the @Test annotation follows the new syntax.
  • Updating the assertion to use #expect maintains the test logic while conforming to the new framework.

The core functionality of the test remains intact, ensuring that the get method returns the same room object when called with the same room ID.


Line range hint 43-65: LGTM!

The changes to the get_throwsErrorWhenOptionsDoNotMatch method align with the conventions of the new testing framework:

  • Renaming the method and adding the @Test annotation follows the new syntax.
  • Updating the assertion to use #expect maintains the test logic while conforming to the new framework.

The core functionality of the test remains intact, ensuring that the get method throws an inconsistentRoomOptions error when called with different options for the same room ID.


65-65: LGTM!

Using the isChatError function in the assertion improves the readability and maintainability of the test. It encapsulates the logic of checking the error type and code, making the assertion more concise.

Tests/AblyChatTests/DefaultRoomTests.swift (13)

3-3: Switch to Swift Testing framework

Importing the Testing framework aligns with the migration to Swift Testing, as outlined in the PR objectives.


5-5: Updated test case to a struct

Converting DefaultRoomTests from a class to a struct is appropriate in Swift Testing and reflects the new testing conventions.


6-6: Adopting @Test annotation

Using the @Test attribute correctly marks the function as a test case in Swift Testing.


7-7: Properly defined asynchronous test function

The test function attach_attachesAllChannels_andSucceedsIfAllSucceed is correctly defined with async throws, suitable for asynchronous testing.


30-30: Asserting channel attach invocation

The assertion #expect(channel.attachCallCounter.isNonZero) appropriately verifies that the attach method was called on each channel.


33-34: Correct use of asynchronous assertions

The use of await #expect and try await #expect ensures proper verification of asynchronous operations and state changes.


37-37: Using @Test annotation for test function

The @Test attribute is appropriately applied to attach_attachesAllChannels_andFailsIfOneFails.


65-65: Verify error comparison using ===

Ensure that using === for error comparison is intentional. The === operator checks for reference equality (same instance). If you need to compare the error contents, consider comparing specific properties like code or message, or use == if ARTErrorInfo conforms to Equatable.


68-68: Using @Test annotation

The @Test attribute correctly marks the test function detach_detachesAllChannels_andSucceedsIfAllSucceed.


92-92: Asserting channel detach invocation

The assertion #expect(channel.detachCallCounter.isNonZero) correctly verifies that the detach method was called on each channel.


95-96: Correct use of asynchronous assertions

The use of await #expect and try await #expect ensures proper verification of asynchronous operations and state changes.


99-99: Using @Test annotation

The @Test attribute correctly marks the test function detach_detachesAllChannels_andFailsIfOneFails.


127-127: Duplicate: Verify error comparison using ===

This error comparison is similar to the one commented on earlier. Ensure the use of === is intentional.

@lawrence-forooghian
Copy link
Collaborator Author

@maratal just a heads up that I’ve changed something since you reviewed this (see the final part of the commit message, about async stuff)

@maratal
Copy link
Collaborator

maratal commented Sep 20, 2024

@maratal just a heads up that I’ve changed something since you reviewed this (see the final part of the commit message, about async stuff)

I think that "expect -> async" vs "async -> expect" is a minor difference and can be changed later with one find/replace command.

We’re doing this because it’s, I guess, the future, and offers
performance improvements, but more immediately because it reduces
verbosity when testing `async` functions and properties.

I’ve done the migration in a pretty straightforward fashion, just
stripping the `test` prefix from the method names (which my eyes are
still getting used to), and not trying to use any new features like test
descriptions, nested suites, or tags. We can figure out how we want to
use these as we get used to using Swift Testing.

Decided to keep testing for errors via a do { … } catch { … } instead of
using #expect(…, throws:) because I like being able to write tests in a
Given / When / Then fashion — i.e. do things, then make assertions.

Whilst working on this, I noticed that some of Swift Testing’s useful
test failure messages stop being so useful when testing asynchronous
code, which takes a bit of the shine off it. For example, if you write

> #expect(status.current == .attached)

then you’ll get a failure message of

> Expectation failed: (current → .detached) == .attached

that is, it shows you information about `current` which helps you to
understand why the expectation failed.

But if, on the other hand, you write

> #expect(await status.current == .attached)

then you’ll get a failure message of

> Expectation failed: await status.current == .detached

which is less useful. I asked about this in [1] and was told that it’s a
known issue and that Swift macro limitations mean it’s unlikely to be
fixed soon. ([2] is a similar question that I found after.) If we decide
that this is a dealbreaker and that we want the rich failure messages,
then we’ll need to switch back to the current way of doing things; that
is, first do the `await` and then the #expect.

Resolves #55.

[1] https://forums.swift.org/t/expectation-failure-messages-are-less-useful-with-await/74754
[2] https://forums.swift.org/t/try-expect-throwing-or-expect-try-throwing/73076/17
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: 0

Outside diff range and nitpick comments (2)
Tests/AblyChatTests/InternalLoggerTests.swift (1)

12-12: LGTM: Assertions updated to Swift Testing syntax

The assertions have been correctly updated to use the #expect and #require syntax of the Swift Testing framework. The test cases remain the same, ensuring that the functionality is still properly verified.

Consider adding a small comment explaining the purpose of the #require call, as it might not be immediately clear to all readers why it's used instead of #expect. For example:

// Use #require to unwrap the optional and fail the test if it's nil
let receivedArguments = try #require(logger.logArguments)

Also applies to: 14-16

Tests/AblyChatTests/DefaultInternalLoggerTests.swift (1)

33-34: Consider breaking down long method names for improved readability

While the current implementation is correct and follows the new framework's conventions, consider breaking down long method names into multiple lines for improved readability. For example:

@Test
func log_whenLogLevelArgumentIsLessSevereThanLogLevelProperty_itDoesNotLog() {

Could be written as:

@Test
func log_whenLogLevelArgumentIsLessSevereThanLogLevelProperty_itDoesNotLog(
) {

This is a minor suggestion and is up to your team's coding style preferences.

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between c3cf9b8 and f5cab27.

Files selected for processing (9)
  • Tests/AblyChatTests/DefaultChatClientTests.swift (2 hunks)
  • Tests/AblyChatTests/DefaultInternalLoggerTests.swift (3 hunks)
  • Tests/AblyChatTests/DefaultRoomStatusTests.swift (2 hunks)
  • Tests/AblyChatTests/DefaultRoomTests.swift (5 hunks)
  • Tests/AblyChatTests/DefaultRoomsTests.swift (4 hunks)
  • Tests/AblyChatTests/Helpers/Helpers.swift (1 hunks)
  • Tests/AblyChatTests/InternalLoggerTests.swift (1 hunks)
  • Tests/AblyChatTests/MessageSubscriptionTests.swift (2 hunks)
  • Tests/AblyChatTests/SubscriptionTests.swift (1 hunks)
Files skipped from review as they are similar to previous changes (5)
  • Tests/AblyChatTests/DefaultChatClientTests.swift
  • Tests/AblyChatTests/DefaultRoomStatusTests.swift
  • Tests/AblyChatTests/DefaultRoomsTests.swift
  • Tests/AblyChatTests/Helpers/Helpers.swift
  • Tests/AblyChatTests/SubscriptionTests.swift
Additional context used
Learnings (1)
Tests/AblyChatTests/DefaultRoomTests.swift (1)
Learnt from: lawrence-forooghian
PR: ably-labs/ably-chat-swift#61
File: Tests/AblyChatTests/DefaultRoomTests.swift:33-34
Timestamp: 2024-09-19T18:44:56.819Z
Learning: In Swift Testing, using `#expect` with `await` may result in less informative failure messages when debugging asynchronous tests.
Additional comments not posted (24)
Tests/AblyChatTests/InternalLoggerTests.swift (4)

2-2: LGTM: Import statement updated for Swift Testing

The import statement has been correctly updated to use the new testing framework, which aligns with the PR objective of switching to Swift Testing.


5-6: LGTM: Test method correctly annotated and renamed

The test method has been properly annotated with @test, and the 'test' prefix has been removed from the method name. This change aligns with the new testing framework and the PR objectives.


1-18: Overall changes align well with PR objectives

The changes in this file successfully transition the test from XCTest to Swift Testing. The structure has been updated (class to struct, method annotation), and assertions have been modified to use the new syntax. These changes align perfectly with the PR objectives of switching to Swift Testing and improving the testing of asynchronous functions.

The core functionality of the test remains intact, ensuring that the MockInternalLogger correctly populates the log message's level, message, and code location.


4-4: LGTM: Test class changed to struct

The test class has been correctly changed to a struct, which is consistent with the new Swift Testing framework's approach. This change removes the inheritance from XCTestCase, as it's no longer needed.

Let's verify that this change has been consistently applied across all test files:

Tests/AblyChatTests/DefaultInternalLoggerTests.swift (6)

2-2: LGTM: Import statement updated for new testing framework

The import of 'Testing' is consistent with the PR objective to switch to Swift Testing.


4-4: LGTM: Test class converted to struct

The change from a class extending XCTestCase to a struct is in line with the new testing framework's conventions.


5-10: LGTM: 'defaults' test method updated to new framework

The changes to this test method are consistent with the PR objectives:

  1. 'test_' prefix removed from the method name.
  2. @test annotation added.
  3. Assertions updated to use #expect syntax.

These modifications align well with the transition to the new testing framework.


Line range hint 13-30: LGTM: 'log' test method updated to new framework

The changes to this test method are well-implemented and align with the PR objectives:

  1. 'test_' prefix removed from the method name.
  2. @test annotation added.
  3. Assertions updated to use #expect and #require syntax.
  4. 'Given/When/Then' structure maintained, as mentioned in the PR objectives.

These modifications successfully transition the test to the new framework while preserving the test's logic and structure.


Line range hint 33-50: LGTM: Long-named test method updated to new framework

The changes to this test method are well-implemented and consistent with the PR objectives:

  1. 'test_' prefix removed from the method name.
  2. @test annotation added.
  3. Assertion updated to use #expect syntax.
  4. 'Given/When/Then' structure maintained, as mentioned in the PR objectives.

These modifications successfully transition the test to the new framework while preserving the test's logic and structure.


Line range hint 1-51: LGTM: Consistent and comprehensive transition to new testing framework

The changes in this file demonstrate a thorough and consistent transition to the new testing framework:

  1. All test methods have been updated uniformly.
  2. The file structure has been changed from a class to a struct as required.
  3. Assertions have been consistently updated to the new syntax (#expect and #require).
  4. The original test logic and 'Given/When/Then' structure have been preserved.

These changes successfully meet the PR objectives while maintaining the integrity of the tests.

Tests/AblyChatTests/MessageSubscriptionTests.swift (5)

3-3: LGTM: Import statement for new testing framework added.

The addition of import Testing aligns with the PR objective of switching to Swift Testing. This change is necessary for utilizing the new testing framework in this file.


26-27: LGTM: Test method updated to new framework syntax.

The changes to withMockAsyncSequence align with the PR objectives:

  1. Using @Test annotation instead of func prefix.
  2. Removing the test prefix from the method name.
  3. Updating the assertion to use #expect.

These modifications successfully transition the test to the new Swift Testing framework.

Note: As mentioned in the PR summary, the new #expect syntax may result in less informative failure messages for asynchronous tests. This is a known trade-off that aligns with current community best practices.

Also applies to: 30-30


33-34: LGTM: Emit test method successfully updated.

The changes to the emit test method are consistent with the previous updates:

  1. @Test annotation added.
  2. test prefix removed from the method name.
  3. Assertion updated to use #expect.

The core logic of the test remains intact, maintaining its focus on emitting and collecting messages.

Also applies to: 42-42


45-46: LGTM: MockGetPreviousMessages test method successfully updated with new syntax.

The changes to mockGetPreviousMessages are consistent with the PR objectives:

  1. @Test annotation added and test prefix removed.
  2. XCTUnwrap replaced with #require.
  3. Assertion updated to use #expect.

The use of #require is a new pattern introduced in this method, which appears to be the equivalent of XCTUnwrap in the new testing framework.

The comment explaining the type casting approach to avoid a compiler error is helpful for understanding the implementation choice. Consider documenting this workaround in a more visible place (e.g., README or CONTRIBUTING file) if it's a pattern that needs to be repeated across multiple test files.

Also applies to: 52-53


21-21: LGTM: Test class changed to struct.

Changing MessageSubscriptionTests from a class to a struct aligns with the new Swift Testing framework's approach. This modification is consistent with the PR objectives.

Please verify that this change doesn't introduce any unintended side effects in test initialization or management. Run the following script to check for any other test files that might need similar updates:

Tests/AblyChatTests/DefaultRoomTests.swift (9)

3-5: LGTM: Successful migration to Swift Testing framework

The changes to import the Testing framework and convert the test class to a struct align with the migration to Swift Testing. This is a good step towards modernizing the test suite.


6-7: LGTM: Test method declaration updated to Swift Testing syntax

The use of @Test annotation and removal of the 'test_' prefix from the method name adhere to Swift Testing conventions. This improves readability and aligns with modern Swift testing practices.


30-34: Assertion syntax updated, but consider async error message clarity

The update to use #expect instead of XCTAssert* methods is correct for Swift Testing. However, as you've noted in the PR description, using await inside #expect may lead to less informative error messages for async tests. This is a known limitation of the current Swift Testing implementation.

Consider monitoring the Swift forums for updates on this issue or explore alternative patterns if more detailed error messages become crucial for debugging.


37-38: LGTM: Test method declaration updated correctly

The second test method has been properly updated to use the @Test annotation and the 'test_' prefix has been removed from the method name. This change is consistent with Swift Testing conventions and improves readability.


65-65: LGTM: Assertions updated correctly

The assertion has been properly updated to use #expect and #require, which is the correct syntax for Swift Testing. The use of #require for unwrapping the optional value before the assertion is a good practice.


68-69: LGTM: Test method declaration updated correctly

The third test method has been properly updated to use the @Test annotation and the 'test_' prefix has been removed from the method name. This change is consistent with Swift Testing conventions and improves readability.


92-96: Assertion syntax updated, but consider async error message clarity

The assertions have been correctly updated to use #expect instead of XCTAssert* methods, which is appropriate for Swift Testing. However, as noted earlier, using await inside #expect may result in less informative error messages for async tests.

While this is a known limitation of the current Swift Testing implementation, it's worth keeping an eye on potential improvements or workarounds in future updates.


99-100: LGTM: Test method and assertions updated correctly

The fourth test method has been properly updated:

  1. The @Test annotation is used correctly.
  2. The 'test_' prefix has been removed from the method name, improving readability.
  3. The assertion has been updated to use #expect and #require, which is the correct syntax for Swift Testing.

These changes are consistent with Swift Testing conventions and represent a successful migration of the test suite.

Also applies to: 127-127


Line range hint 1-128: Overall: Successful migration to Swift Testing framework

The changes in this file demonstrate a comprehensive and consistent migration from XCTest to the Swift Testing framework. Key points:

  1. All test methods have been properly annotated with @Test and renamed according to Swift Testing conventions.
  2. Assertions have been updated to use #expect and #require syntax.
  3. The test class has been converted to a struct, aligning with Swift Testing practices.

The migration addresses the PR objectives, including the transition to Swift Testing and handling of async testing syntax. The known limitation regarding less informative error messages for async tests has been acknowledged and is being monitored for future improvements.

Great job on implementing these changes consistently throughout the file!

@lawrence-forooghian lawrence-forooghian merged commit 90b9ac1 into main Sep 23, 2024
11 checks passed
@lawrence-forooghian lawrence-forooghian deleted the 55-switch-to-swift-testing branch September 23, 2024 14:04
This was referenced Nov 7, 2024
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.

Switch to Swift Testing
3 participants