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

Address code duplication in Access API tests and error handling #140

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

lealobanov
Copy link
Collaborator

@lealobanov lealobanov commented Oct 30, 2024

Closes: #138

Description

Addresses code duplication in error handling and tests related to the FlowAccessApi and AsyncFlowAccessApi classes (see issue #138)

  • Also addressed refactoring comments suggested by Code Rabbit

For contributor use:

  • Targeted PR against master branch
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code follows the standards mentioned here.
  • Updated relevant documentation
  • Re-reviewed Files changed in the Github PR explorer
  • Added appropriate labels

Summary by CodeRabbit

  • New Features

    • Introduced new utility functions for improved error handling in API calls.
    • Added mock response creation methods to enhance test data generation.
  • Bug Fixes

    • Streamlined error handling in various API methods to reduce redundancy.
  • Refactor

    • Refactored existing tests to utilize new helper functions for better maintainability and readability.
    • Enhanced the structure and clarity of the test code by centralizing mock object creation.
  • Chores

    • Updated visibility of mock response factory for broader access in tests.

Copy link

coderabbitai bot commented Oct 30, 2024

Walkthrough

The changes introduced in this pull request focus on enhancing error handling and reducing code duplication across various API interaction tests and implementations. A new private utility function, safelyHandle, has been added to streamline error management in test cases. Additionally, the AsyncFlowAccessApiImpl class has been refactored to centralize API call handling through a new method, handleApiCall. The test classes have been updated to utilize new mock creation methods, improving consistency and readability in the test code.

Changes

File Change Summary
sdk/src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt Introduced safelyHandle function for error handling; refactored existing tests to use this function.
sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt Added handleApiCall method for centralized API call handling; refactored multiple API methods to utilize this method; marked several methods as deprecated.
sdk/src/test/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImplTest.kt Added helper functions for mock creation; updated MockResponseFactory visibility; refactored tests to improve mock response handling.
sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt Added companion object methods for mock creation; standardized error handling across tests; refactored tests to use new mock creation methods.

Assessment against linked issues

Objective Addressed Explanation
Address duplication in error handling (138)
Address duplication in unit tests (138)

Possibly related PRs

  • Access API refactoring + exception handling #55: Introduced a new method handleApiCall for centralized error handling in API calls, which aligns with the main PR's focus on improving error handling through the safelyHandle utility function.
  • Access api methods - aggregate changes into main branch #63: This PR adds new methods for retrieving transaction results and execution results by block ID, which relates to the main PR's changes in handling API calls and error management.
  • #106/ TransactionResult type differs from protobuf schema #116: This PR updates the FlowTransactionResult class to include additional fields that enhance the transaction's context, which is relevant to the main PR's focus on improving the structure and handling of transaction-related data.
  • FlowBlockSeal protobuf updates #122: This PR updates the FlowBlockSeal class to align with the protobuf schema, which is relevant to the main PR's changes in transaction handling and error management, as both involve improving the data structures used in API interactions.

Suggested reviewers

  • jribbink
  • franklywatson

Poem

In the code where bunnies play,
Errors once led us astray.
Now with safelyHandle in sight,
Our tests are clean, our code is bright!
Hopping through functions, all in a row,
With each little change, our confidence grows! 🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 34bedcc and 8731d91.

📒 Files selected for processing (2)
  • sdk/src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt (7 hunks)
  • sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • sdk/src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt
🔇 Additional comments (3)
sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt (3)

26-44: Centralized API Call Handling Enhances Maintainability

The introduction of the handleApiCall method effectively reduces code duplication and standardizes error handling across API calls. This refactoring enhances maintainability and improves code readability.


345-354: Refactored Script Execution Methods Reduce Duplication

The new executeScript helper function centralizes the logic for executing scripts, which minimizes code duplication in the script execution methods. This change promotes code reuse and simplifies future maintenance.


65-66: Avoid Throwing Exceptions for Absent Resources

As previously noted, throwing an IllegalStateException when an account is not found may be unnecessary and could be inefficient. Consider returning null or a meaningful error response within AccessApiCallResponse to indicate the absence of the account.

Also applies to: 79-80, 94-95


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

github-actions bot commented Oct 30, 2024

Unit Test Results

  62 files  ±0    62 suites  ±0   25s ⏱️ -1s
380 tests ±0  380 ✔️ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 8731d91. ± Comparison against base commit 662759b.

♻️ This comment has been updated with latest results.

Copy link

github-actions bot commented Oct 30, 2024

SDK Examples Unit Test Results

41 files  41 suites   7m 49s ⏱️
88 tests 86 ✔️ 0 💤 2 ❌

For more details on these failures, see this check.

Results for commit 4926b5e.

♻️ This comment has been updated with latest results.

Copy link

github-actions bot commented Oct 30, 2024

Common Integration Test Results

0 files  0 suites   0s ⏱️
0 tests 0 ✔️ 0 💤 0 ❌

Results for commit 4926b5e.

♻️ This comment has been updated with latest results.

Copy link

github-actions bot commented Oct 30, 2024

Integration Test Results

  6 files  ±0    6 suites  ±0   3m 15s ⏱️ ±0s
38 tests ±0  37 ✔️  - 1  0 💤 ±0  1 ❌ +1 

For more details on these failures, see this check.

Results for commit 8731d91. ± Comparison against base commit 662759b.

♻️ This comment has been updated with latest results.

@lealobanov lealobanov changed the title WIP: continue with code duplication changes Address code duplication in Access API tests and error handling Oct 31, 2024
@lealobanov lealobanov marked this pull request as ready for review October 31, 2024 06:50
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: 5

🧹 Outside diff range and nitpick comments (8)
sdk/src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt (2)

Line range hint 77-306: Maintain consistency in helper method usage across tests.

While many test methods use the new helper methods, some still contain inline error handling. For example, getNodeVersionInfo and getAccountByAddress tests could use helper methods.

Consider extracting these into helper methods for consistency:

private fun getNodeVersionInfo(): FlowNodeVersionInfo =
    safelyHandle(
        { handleResult(accessAPI.getNodeVersionInfo(), "Failed to get node version info") },
        "Failed to retrieve node version info"
    )

private fun getAccountByAddress(address: FlowAddress): FlowAccount =
    safelyHandle(
        { handleResult(accessAPI.getAccountByAddress(address), "Failed to get account by address") },
        "Failed to retrieve account by address"
    )

Line range hint 1-306: Overall architectural improvements align with PR objectives.

The introduction of safelyHandle and helper methods successfully addresses code duplication in the Access API tests. The changes make the code more maintainable and consistent with the PR objectives.

However, consider the following architectural improvements:

  1. Create an error handling module that can be shared across different test classes
  2. Consider using a test fixture pattern to reduce setup code duplication
  3. Add documentation for the error handling pattern to help other contributors
sdk/src/test/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImplTest.kt (1)

87-112: LGTM! Consider adding KDoc comments.

The helper functions are well-structured and provide comprehensive mock data. They effectively support test cases by creating reusable mock responses.

Consider adding KDoc comments to document the purpose and return values of these utility functions:

/**
 * Creates a mock node version info response for testing.
 * @return Access.GetNodeVersionInfoResponse with predefined test values
 */
fun createMockNodeVersionInfo(): Access.GetNodeVersionInfoResponse

/**
 * Creates a mock transactions response containing the provided transactions.
 * @param transactions List of FlowTransaction to include in the response
 * @return Access.TransactionsResponse containing the provided transactions
 */
fun createTransactionsResponse(transactions: List<FlowTransaction>): Access.TransactionsResponse
sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt (3)

Line range hint 737-749: Consider extracting common error handling test logic.

These error handling test blocks contain duplicated verification logic. Consider extracting this pattern into a helper method to reduce duplication.

private suspend fun verifyErrorChannel(errorChannel: ReceiveChannel<Throwable>, expectedMessage: String) {
    var receivedException: Throwable? = null
    val job = launch {
        receivedException = errorChannel.receiveCatching().getOrNull()
    }
    advanceUntilIdle()
    job.join()

    if (receivedException != null) {
        assertEquals(expectedMessage, receivedException!!.message)
    } else {
        fail("Expected error but got success")
    }
    
    errorChannel.cancel()
}

Then use it in the test cases:

verifyErrorChannel(errorChannel, testException.message!!)

Also applies to: 760-772, 806-818, 855-867


405-405: Consider strengthening account verification.

The account verification logic in these test cases could be strengthened by also verifying the code field of the FlowAccount.

 assertResultSuccess(result) {
     assertEquals(flowAccount.address, it.address)
     assertEquals(flowAccount.keys, it.keys)
     assertEquals(flowAccount.contracts, it.contracts)
     assertEquals(flowAccount.balance.stripTrailingZeros(), it.balance.stripTrailingZeros())
+    assertEquals(flowAccount.code, it.code)
 }

Also applies to: 421-421, 437-437


Line range hint 876-882: Consider enhancing assertResultSuccess helper method.

The helper method could be enhanced to provide more detailed error information by including the actual error message in the exception.

 private fun <T> assertResultSuccess(result: FlowAccessApi.AccessApiCallResponse<T>, assertions: (T) -> Unit) {
     when (result) {
         is FlowAccessApi.AccessApiCallResponse.Success -> assertions(result.data)
-        is FlowAccessApi.AccessApiCallResponse.Error -> throw IllegalStateException("Request failed: ${result.message}", result.throwable)
+        is FlowAccessApi.AccessApiCallResponse.Error -> throw IllegalStateException(
+            "Request failed: ${result.message}. Error details: ${result.throwable?.message}",
+            result.throwable
+        )
     }
 }
sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt (2)

437-440: Simplify compatibleRange Initialization

The initialization of compatibleRange can be simplified using Kotlin's safe-call operator and let function, enhancing code readability.

Apply this diff to streamline the code:

 val compatibleRange = if (response.info.hasCompatibleRange()) {
     FlowCompatibleRange(response.info.compatibleRange.startHeight, response.info.compatibleRange.endHeight)
-} else { null }
+} else null

Or use safe-call with let:

+val compatibleRange = response.info.compatibleRange?.let {
+    FlowCompatibleRange(it.startHeight, it.endHeight)
+}

26-41: Use Specific Exception Types in Catch Blocks

Catching the general Exception class in the handleApiCall method may obscure the root cause of errors. Using more specific exception types can aid in debugging and provide clearer error handling.

Consider catching specific exceptions like IOException, GrpcException, or any other relevant exceptions expected from the API calls.

-} catch (e: Exception) {
+} catch (e: IOException) {

Adjust the exception types based on the exceptions that apiCall() might throw.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 662759b and 36c22b2.

📒 Files selected for processing (4)
  • sdk/src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt (7 hunks)
  • sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt (1 hunks)
  • sdk/src/test/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImplTest.kt (6 hunks)
  • sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt (31 hunks)
🧰 Additional context used
📓 Learnings (1)
sdk/src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt (2)
Learnt from: lealobanov
PR: onflow/flow-jvm-sdk#55
File: src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt:95-106
Timestamp: 2024-07-03T12:30:04.496Z
Learning: In the `TransactionIntegrationTest` class, exception handling is implemented using `IntegrationTestUtils.handleResult`.
Learnt from: lealobanov
PR: onflow/flow-jvm-sdk#55
File: src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt:95-106
Timestamp: 2024-10-08T17:04:37.869Z
Learning: In the `TransactionIntegrationTest` class, exception handling is implemented using `IntegrationTestUtils.handleResult`.
🔇 Additional comments (7)
sdk/src/test/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImplTest.kt (3)

15-15: LGTM! Good use of shared test utilities.

The import of createMockAccount from FlowAccessApiImplTest.Companion helps reduce code duplication between test classes, which aligns well with the PR objectives.


121-130: LGTM! Good refactoring of test utilities.

Making MockResponseFactory public and adding new account response factory methods improves code reuse across test classes, which aligns with the PR's goal of reducing duplication.


Line range hint 468-503: LGTM! Effective reduction of test code duplication.

The account-related test methods have been successfully refactored to use the shared createMockAccount utility, which:

  • Reduces code duplication
  • Maintains comprehensive assertions
  • Improves consistency across test cases
sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt (3)

14-22: LGTM! Good refactoring of imports.

The imports have been organized to leverage shared test utilities from AsyncFlowAccessApiImplTest, which helps reduce code duplication across test classes.


55-58: Well-structured utility methods in companion object.

Good addition of utility methods createMockTransaction and createMockAccount to centralize mock object creation. This promotes code reuse and maintains consistency in test data creation.


87-87: Consistent error handling pattern across test cases.

Good use of shared testException across error test cases. This standardizes error handling and makes the tests more maintainable.

Also applies to: 106-106, 142-142, 172-172, 204-204, 290-290, 322-322, 391-391

sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt (1)

285-296: Validate Transactions Before Sending

In sendTransaction, ensuring that the transaction is valid before sending can prevent unnecessary API calls and potential errors.

Run the following script to verify the transaction's validity:

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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 36c22b2 and 9f3f7d5.

📒 Files selected for processing (1)
  • sdk/src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt (7 hunks)
🧰 Additional context used
📓 Learnings (1)
sdk/src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt (2)
Learnt from: lealobanov
PR: onflow/flow-jvm-sdk#55
File: src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt:95-106
Timestamp: 2024-07-03T12:30:04.496Z
Learning: In the `TransactionIntegrationTest` class, exception handling is implemented using `IntegrationTestUtils.handleResult`.
Learnt from: lealobanov
PR: onflow/flow-jvm-sdk#55
File: src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt:95-106
Timestamp: 2024-10-08T17:04:37.869Z
Learning: In the `TransactionIntegrationTest` class, exception handling is implemented using `IntegrationTestUtils.handleResult`.
🔇 Additional comments (2)
sdk/src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt (2)

22-24: Well-implemented error handling utility!

The safelyHandle function effectively simplifies error handling by combining Result handling with exception handling. This implementation addresses the previous feedback about reducing error handling complexity.


27-52: Previous suggestion about error message duplication remains valid.

The helper methods consistently use both handleResult and safelyHandle, but there's still duplication in error messages as noted in the previous review.

@lealobanov lealobanov self-assigned this Nov 5, 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.

Address code duplication in tests and error handling
1 participant