Skip to content

[Beginner]: Add unit tests for EvmAddressΒ #552

@rwalworth

Description

@rwalworth

πŸ₯ Beginner Friendly

This issue is a great fit for contributors who are ready to explore the Hiero Swift codebase a little more and take on slightly more independent work.

Beginner Issues often involve reading existing Swift code, understanding how different parts of the SDK fit together, and making small, thoughtful updates that follow established patterns.

The goal is to support skill growth while keeping the experience approachable, well-scoped, and enjoyable.

πŸ‘Ύ Description of the Issue

The EvmAddress struct in Sources/Hiero/Ethereum/EvmAddress.swift represents a 20-byte Ethereum Virtual Machine address. While EvmAddress is used and tested indirectly through other types (AccountId, ContractId, etc.), there's no dedicated unit test file for this type.

A dedicated test file would:

  • Make test coverage explicit and discoverable
  • Test edge cases and error conditions directly
  • Serve as documentation for the type's behavior

πŸ’‘ Proposed Solution

Create a new test file Tests/HieroUnitTests/EvmAddressUnitTests.swift that tests:

  1. Parsing from strings

    • With 0x prefix
    • Without 0x prefix
    • Case insensitivity (uppercase/lowercase hex)
  2. Error handling

    • Invalid hex characters
    • Wrong length (not 20 bytes)
    • Empty string
  3. Conversion methods

    • toString() returns 0x prefixed lowercase hex
    • toBytes() returns raw 20-byte Data
    • fromBytes() with valid and invalid data
  4. Protocol conformances

    • Equatable / Hashable
    • LosslessStringConvertible
    • ExpressibleByStringLiteral

πŸ‘©β€πŸ’» Implementation Steps

To implement these tests:

  • Create a new file Tests/HieroUnitTests/EvmAddressUnitTests.swift
  • Add the standard test file header and imports:
// SPDX-License-Identifier: Apache-2.0

import XCTest

@testable import Hiero

internal final class EvmAddressUnitTests: XCTestCase {
    // Tests go here
}
  • Add tests for valid parsing:
internal func test_FromStringWithPrefix() throws {
    let address = try EvmAddress.fromString("0x1234567890abcdef1234567890abcdef12345678")
    XCTAssertEqual(address.toString(), "0x1234567890abcdef1234567890abcdef12345678")
}

internal func test_FromStringWithoutPrefix() throws {
    let address = try EvmAddress.fromString("1234567890abcdef1234567890abcdef12345678")
    XCTAssertEqual(address.toString(), "0x1234567890abcdef1234567890abcdef12345678")
}

internal func test_FromStringUppercase() throws {
    let address = try EvmAddress.fromString("0x1234567890ABCDEF1234567890ABCDEF12345678")
    XCTAssertEqual(address.toString(), "0x1234567890abcdef1234567890abcdef12345678")
}
  • Add tests for error cases:
internal func test_FromStringInvalidLength() {
    XCTAssertThrowsError(try EvmAddress.fromString("0x1234")) { error in
        // Verify error type/message
    }
}

internal func test_FromStringInvalidHex() {
    XCTAssertThrowsError(try EvmAddress.fromString("0xGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG"))
}

internal func test_FromBytesInvalidLength() {
    XCTAssertThrowsError(try EvmAddress.fromBytes(Data([0x01, 0x02, 0x03])))
}
  • Add tests for byte conversion:
internal func test_ToBytes() throws {
    let address = try EvmAddress.fromString("0x0000000000000000000000000000000000000001")
    let bytes = address.toBytes()
    XCTAssertEqual(bytes.count, 20)
    XCTAssertEqual(bytes.last, 0x01)
}

internal func test_FromBytes() throws {
    var data = Data(repeating: 0, count: 20)
    data[19] = 0x42
    let address = try EvmAddress.fromBytes(data)
    XCTAssertEqual(address.toString(), "0x0000000000000000000000000000000000000042")
}
  • Add tests for protocol conformances:
internal func test_Equatable() throws {
    let a = try EvmAddress.fromString("0x1234567890abcdef1234567890abcdef12345678")
    let b = try EvmAddress.fromString("0x1234567890abcdef1234567890abcdef12345678")
    XCTAssertEqual(a, b)
}

internal func test_StringLiteral() {
    let address: EvmAddress = "0x1234567890abcdef1234567890abcdef12345678"
    XCTAssertEqual(address.toString(), "0x1234567890abcdef1234567890abcdef12345678")
}
  • Run tests with swift test to verify they pass
  • Ensure new tests follow existing test file patterns in the project

βœ… Acceptance Criteria

To help get this change merged smoothly:

  • Scope: New test file covers EvmAddress functionality
  • Behavior: No changes to production code
  • Tests: All new tests pass, existing tests unaffected
  • Review: All code review feedback addressed

πŸ“‹ Step-by-Step Contribution Guide

To help keep contributions consistent and easy to review, we recommend following these steps:

  • Comment /assign to request the issue
  • Wait for assignment
  • Fork the repository and create a branch
  • Set up the project using the instructions in README.md
  • Make the requested changes
  • Sign each commit using -s -S
  • Push your branch and open a pull request

Read Workflow Guide for step-by-step workflow guidance.
Read README.md for setup instructions.

❗ Pull requests cannot be merged without S and s signed commits.
See the Signing Guide.

πŸ€” Additional Information

If you have questions while working on this issue, feel free to ask!

You can reach the community and maintainers here:
Hiero Discord

Reference:

  • EVM addresses are 20-byte (160-bit) values, typically displayed as 40 hex characters with a 0x prefix
  • Look at existing test files like AccountIdUnitTests.swift for patterns
  • The source file is only ~70 lines, making it easy to achieve full coverage

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind: testingAdding or improving unit tests, integration tests, or test infrastructurepriority: lowNon-urgent tasks, nice-to-have improvements, or minor issuesskill: beginnerSuitable for contributors who have completed a good first issue and want to build skillsstatus: ready for devThe issue is fully defined and ready for a contributor

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions