From e57f50b361d49fec7613cffdfae49d4fd7100766 Mon Sep 17 00:00:00 2001 From: Prachi Gauriar Date: Fri, 4 Jul 2025 12:22:19 -0400 Subject: [PATCH] Add .swift-format and fix lint warnings --- .github/workflows/VerifyChanges.yaml | 14 ++ .swift-format | 75 +++++++ CLAUDE.md | 88 ++++++++ Documentation/MarkdownStyleGuide.md | 190 ++++++++++++++++++ Package.swift | 4 +- README.md | 10 +- Scripts/install-git-hooks | 50 +++++ Scripts/lint | 10 + .../CollectionGeneration.swift | 1 - .../BinaryFloatingPoint+Random.swift | 1 - .../CaseIterable+Random.swift | 1 - .../Random Value Generation/Data+Random.swift | 1 - .../Optional+Random.swift | 1 - .../RandomValueGenerating.swift | 7 +- .../SeedableRandomNumberGenerator.swift | 9 +- .../String+Random.swift | 5 +- .../Random Value Generation/URL+Random.swift | 1 - .../URLComponents+Random.swift | 1 - .../URLQueryItem+Random.swift | 11 +- .../Random Value Generation/UUID+Random.swift | 1 - Sources/DevTesting/Stubbing/Stub.swift | 26 +-- .../CollectionGenerationTests.swift | 3 +- .../BinaryFloatingPoint+RandomTests.swift | 3 +- .../CaseIterable+RandomTests.swift | 3 +- .../Data+RandomTests.swift | 1 - .../Optional+RandomTests.swift | 1 - .../RandomValueGeneratingTests.swift | 1 - .../SeedableRandomNumberGeneratorTests.swift | 1 - .../String+RandomTests.swift | 2 +- .../URL+RandomTests.swift | 1 - .../URLComponents+RandomTests.swift | 1 - .../URLQueryItem+RandomTests.swift | 1 - .../UUID+RandomTests.swift | 21 +- .../DevTestingTests/Stubbing/StubTests.swift | 3 +- .../Supporting Types/CaseIterableEnums.swift | 1 - .../Supporting Types/HashableError.swift | 1 - 36 files changed, 481 insertions(+), 70 deletions(-) create mode 100644 .swift-format create mode 100644 CLAUDE.md create mode 100644 Documentation/MarkdownStyleGuide.md create mode 100755 Scripts/install-git-hooks create mode 100755 Scripts/lint diff --git a/.github/workflows/VerifyChanges.yaml b/.github/workflows/VerifyChanges.yaml index cc18e93..8c8ca49 100644 --- a/.github/workflows/VerifyChanges.yaml +++ b/.github/workflows/VerifyChanges.yaml @@ -8,8 +8,22 @@ on: branches: [ $default-branch ] jobs: + lint: + name: Lint + runs-on: macos-15 + if: ${{ github.event_name == 'pull_request' }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Select Xcode 16.4 + run: | + sudo xcode-select -s /Applications/Xcode_16.4.0.app + - name: Lint + run: | + Scripts/lint build-and-test: name: Build and Test (${{ matrix.platform }}) + needs: lint runs-on: macos-15 strategy: fail-fast: false diff --git a/.swift-format b/.swift-format new file mode 100644 index 0000000..6cd31d6 --- /dev/null +++ b/.swift-format @@ -0,0 +1,75 @@ +{ + "fileScopedDeclarationPrivacy": { + "accessLevel": "private" + }, + "indentConditionalCompilationBlocks": false, + "indentSwitchCaseLabels": false, + "indentation": { + "spaces": 4 + }, + "lineBreakAroundMultilineExpressionChainComponents": false, + "lineBreakBeforeControlFlowKeywords": false, + "lineBreakBeforeEachArgument": false, + "lineBreakBeforeEachGenericRequirement": false, + "lineBreakBetweenDeclarationAttributes": false, + "lineLength": 120, + "maximumBlankLines": 2, + "multiElementCollectionTrailingCommas": true, + "noAssignmentInExpressions": { + "allowedFunctions": [] + }, + "prioritizeKeepingFunctionOutputTogether": true, + "reflowMultilineStringLiterals": { + "never": {} + }, + "respectsExistingLineBreaks": true, + "rules": { + "AllPublicDeclarationsHaveDocumentation": false, + "AlwaysUseLiteralForEmptyCollectionInit": true, + "AlwaysUseLowerCamelCase": true, + "AmbiguousTrailingClosureOverload": true, + "AvoidRetroactiveConformances": false, + "BeginDocumentationCommentWithOneLineSummary": true, + "DoNotUseSemicolons": true, + "DontRepeatTypeInStaticProperties": true, + "FileScopedDeclarationPrivacy": true, + "FullyIndirectEnum": true, + "GroupNumericLiterals": true, + "IdentifiersMustBeASCII": true, + "NeverForceUnwrap": false, + "NeverUseForceTry": false, + "NeverUseImplicitlyUnwrappedOptionals": false, + "NoAccessLevelOnExtensionDeclaration": true, + "NoAssignmentInExpressions": true, + "NoBlockComments": true, + "NoCasesWithOnlyFallthrough": true, + "NoEmptyLinesOpeningClosingBraces": false, + "NoEmptyTrailingClosureParentheses": true, + "NoLabelsInCasePatterns": true, + "NoLeadingUnderscores": false, + "NoParensAroundConditions": true, + "NoPlaygroundLiterals": true, + "NoVoidReturnOnFunctionSignature": true, + "OmitExplicitReturns": false, + "OneCasePerLine": true, + "OneVariableDeclarationPerLine": true, + "OnlyOneTrailingClosureArgument": true, + "OrderedImports": true, + "ReplaceForEachWithForLoop": true, + "ReturnVoidInsteadOfEmptyTuple": true, + "TypeNamesShouldBeCapitalized": true, + "UseEarlyExits": true, + "UseExplicitNilCheckInConditions": true, + "UseLetInEveryBoundCaseVariable": true, + "UseShorthandTypeNames": true, + "UseSingleLinePropertyGetter": true, + "UseSynthesizedInitializer": true, + "UseTripleSlashForDocumentationComments": true, + "UseWhereClausesInForLoops": true, + "ValidateDocumentationComments": false + }, + "spacesAroundRangeFormationOperators": true, + "spacesBeforeEndOfLineComments": 4, + "tabWidth": 4, + "version": 1 +} diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..5450c28 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,88 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this +repository. + + +## Development Commands + +### Building and Testing + + - **Build for testing**: `swift build --package-path . --disable-automatic-resolution` + - **Run tests**: `swift test --package-path . --disable-automatic-resolution` + - **Run tests with code coverage**: Tests are run through the GitHub Actions workflow using + `build_and_test.sh` from DevBuilds + - **Test specific platform**: Use `xcodebuild` with appropriate destination (see + `.github/workflows/VerifyChanges.yaml` for examples) + +### Code Formatting and Linting + + - **Lint check**: `Scripts/lint` (runs `swift format lint --recursive --strict` from anywhere) + - **Format code**: `swift format --in-place --recursive Sources/ Tests/` + - **Manual lint**: `swift format lint --recursive --strict Sources/ Tests/` + - **Swift format configuration**: Uses `.swift-format` file with 4-space indentation and 120 + character line length + +### Git Hooks + + - **Install git hooks**: `Scripts/install-git-hooks` (installs pre-commit hook that runs lint + check) + - **Pre-commit hook**: Automatically runs `Scripts/lint` before each commit + +### Documentation + + - **Build documentation**: `swift package generate-documentation` + - **Documentation source**: `Sources/DevTesting/Documentation.docc/` + + +## Code Architecture + +### Core Components + +**RandomValueGenerating Protocol**: The central protocol that test suites conform to for generating +repeatable random test data. Uses `SeedableRandomNumberGenerator` and logs seeds for test +reproducibility. + +**Three Main Feature Areas**: + + 1. **Random Value Generation** (`Sources/DevTesting/Random Value Generation/`): Extensions for + generating random values of various types (String, Data, URL, UUID, etc.) with seeded + randomness + 2. **Collection Generation** (`Sources/DevTesting/Collection Generation/`): Array extensions for + generating collections of random data + 3. **Stubbing** (`Sources/DevTesting/Stubbing/`): `Stub` and `ThrowingStub` classes for mocking + and spying in tests + +### Key Design Patterns + + - **Seeded Randomness**: All random generation uses `SeedableRandomNumberGenerator` to ensure + test reproducibility + - **Logging Integration**: Random seeds are logged using `os.Logger` (subsystem: "DevTesting", + category: "randomization") + - **Swift Testing Integration**: Designed specifically for Swift Testing framework, not XCTest + - **Type Safety**: Extensive use of Swift 6 features including typed throws and existential + types + +### Dependencies + + - **Swift Numerics**: Used for `RealModule` in tests + - **Platform Requirements**: iOS 18+, macOS 15+, tvOS 18+, visionOS 2+, watchOS 11+ + - **Swift Version**: Requires Swift 6.1 toolchain + +### Testing Strategy + + - **Test Plans**: Uses `DevTesting.xctestplan` for organized test execution + - **Coverage Target**: Aims for 99%+ test coverage + - **Platform Testing**: Tests run on iOS, macOS, tvOS, and watchOS simulators + - **CI/CD**: GitHub Actions workflow with matrix strategy across platforms + +### Documentation Standards + + - **Full Documentation**: All public APIs are documented with Swift DocC + - **API Guidelines**: Follows Swift API Design Guidelines + - **Documentation Comments**: Uses triple-slash comments (`///`) + - **Markdown Style**: Follow `Documentation/MarkdownStyleGuide.md` for consistent formatting: + - 100 character line length + - 4-space indented code blocks (no fenced blocks) + - 2-space indented bullet lists with alignment + - Consistent terminology (function vs method, type vs class) \ No newline at end of file diff --git a/Documentation/MarkdownStyleGuide.md b/Documentation/MarkdownStyleGuide.md new file mode 100644 index 0000000..d94f75c --- /dev/null +++ b/Documentation/MarkdownStyleGuide.md @@ -0,0 +1,190 @@ +# Markdown Style Guide + +This document defines the Markdown formatting standards for documentation in the Shopper iOS +codebase. + + +## General Formatting + +### Line Length + +Keep all lines under **100 characters**. Break long sentences and paragraphs at natural points +to stay within this limit. + + ✅ Good: + Faucibus consectetur lacinia nostra eros conubia nibh inceptos hendrerit, ante blandit + vulputate imperdiet amet porttitor torquent mattis. + + ❌ Bad: + Faucibus consectetur lacinia nostra eros conubia nibh inceptos hendrerit, ante blandit vulputate imperdiet amet porttitor torquent mattis. + + +### Spacing + +Use consistent spacing for visual hierarchy: + +- **Between major sections**: 2 blank lines +- **After code blocks**: 1 blank line +- **Before subsections**: 1 blank line +- **After section headers**: 1 blank line + +Example: + + ## Major Section + + Content here. + + + ## Another Major Section + + ### Subsection + + Content after subsection header. + + code block here + + Content after code block. + + +## Headers + +### Structure + +Use consistent header hierarchy: + + - `#` for document title + - `##` for major sections + - `###` for subsections + - `####` for sub-subsections (use sparingly) + +### Numbering + +Number subsections when they represent sequential steps or ordered items: + + ## Usage Patterns + + ### 1. Basic Setup + ### 2. Advanced Configuration + ### 3. Verification + + +## Code Blocks + +### Indented Code Blocks + +Use **4-space indentation** for all code blocks instead of fenced blocks: + + ✅ Good: + import DevTesting + + final class MockService: ServiceProtocol { + nonisolated(unsafe) var performActionStub: Stub! + } + + ❌ Bad: + ```swift + import DevTesting + + final class MockService: ServiceProtocol { + nonisolated(unsafe) var performActionStub: Stub! + } + ``` + + +## Lists + +### Unordered Lists + +Use `-` as the bullet character for unordered lists. Place the hyphen 2 spaces from current +indentation level, followed by a space, then your text. When a bullet point spans multiple lines, +align continuation lines with the start of the text (not the hyphen). This ensures all text within a +bullet aligns vertically and makes proper indentation on continuation lines a matter of pressing tab +one or more times. + + - Turpis cubilia sit urna dis ultricies consequat massa hendrerit enim natoque. + - Consectetur sapien posuere sit arcu finibus mattis dictumst dis, lectus ipsum in dictum + lobortis bibendum enim, suscipit aliquet nulla porta erat id class purus. + - Scelerisque massa rutrum dapibus placerat aenean tellus arcu cursus. + - Iaculis, cubilia tristique efficitur bibendum urna imperdiet facilisis turpis hac, + platea est habitant auctor quisque nec pulvinar fermentum sociosqu. + - Parturient justo, venenatis nunc lobortis senectus tortor orci elementum consequat. + - In nibh nisl venenatis bibendum neque mattis habitant tempor proin, tincidunt lobortis + vulputate commodo. + +Blank lines can be placed between bullets if it aids in readability. + +### Ordered Lists + +Use standard numbered lists for sequential items. Follow similar indentation rules as for unordered +lists. Note that the `.` characters in the bullets leads to some strange indentation, but this is +unavoidable. + + 1. Turpis cubilia sit urna dis ultricies consequat massa hendrerit enim natoque. + + 2. Consectetur sapien posuere sit arcu finibus mattis dictumst dis, lectus ipsum in dictum + lobortis bibendum enim, suscipit aliquet nulla porta erat id class purus. + + 1. Scelerisque massa rutrum dapibus placerat aenean tellus arcu cursus. + 2. Iaculis, cubilia tristique efficitur bibendum urna imperdiet facilisis turpis hac, + platea est habitant auctor quisque nec pulvinar fermentum sociosqu. + 3. Parturient justo, venenatis nunc lobortis senectus tortor orci elementum consequat. + + 4. In nibh nisl venenatis bibendum neque mattis habitant tempor proin, tincidunt lobortis + vulputate commodo. + + +## Text Formatting + +### Bold Text + +Use bold for emphasis on key terms: + + - **File names**: `Mock[ProtocolName].swift` + - **Type names**: `Mock[ProtocolName]` + +### Code Spans + +Use backticks for: + + - Type names: `Stub` + - Function names: `performAction(_:)` + - File names: `MockAppServices.swift` + - Keywords: `nonisolated(unsafe)` + +### Terminology Consistency + +Use consistent terminology throughout documents: + +- Prefer "function" over "method" when referring to Swift functions +- Use "type" instead of "class" when referring generically to classes/structs/enums +- Use "property" for stored and computed properties + + +## File Structure Examples + +Use indented text blocks for file structure diagrams: + + Tests/ + ├── Folder 1/ + │ └── Folder 2/ + │ ├── File1.swift + │ └── File2.swift + └── Folder 3/ + └── Folder 4/ + ├── File3.swift + └── File4.swift + + +## Links and References + +### Internal References + +Use relative paths for internal documentation: + + See [Test Mock Documentation](TestMocks.md) for details. + +### Code References + +Reference specific locations using this pattern: + + The main implementation is in `Stub.swift:42-68`. diff --git a/Package.swift b/Package.swift index 4b387e7..4083627 100644 --- a/Package.swift +++ b/Package.swift @@ -20,10 +20,10 @@ let package = Package( .library( name: "DevTesting", targets: ["DevTesting"] - ), + ) ], dependencies: [ - .package(url: "https://github.com/apple/swift-numerics", from: "1.0.0"), + .package(url: "https://github.com/apple/swift-numerics", from: "1.0.0") ], targets: [ .target( diff --git a/README.md b/README.md index 80bac35..c0e2933 100644 --- a/README.md +++ b/README.md @@ -34,10 +34,18 @@ interfaces are fully documented and tested. We aim for overall test coverage ove [SwiftAPIDesignGuidelines]: https://swift.org/documentation/api-design-guidelines/ +### Development Setup + +To set up the development environment: + + 1. Run `Scripts/install-git-hooks` to install pre-commit hooks that automatically check code + formatting. + 2. Use `Scripts/lint` to manually check code formatting at any time. + ## Bugs and Feature Requests -Find a bug? Want a new feature? Create a GitHub issue and we’ll take a look. +Find a bug? Want a new feature? Create a GitHub issue and we’ll take a look. ## License diff --git a/Scripts/install-git-hooks b/Scripts/install-git-hooks new file mode 100755 index 0000000..670ea93 --- /dev/null +++ b/Scripts/install-git-hooks @@ -0,0 +1,50 @@ +#!/bin/bash + +# Get the directory where this script is located +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Go to the repository root (one level up from Scripts) +REPO_ROOT="$(dirname "$SCRIPT_DIR")" + +# Check if we're in a git repository +if [ ! -d "$REPO_ROOT/.git" ]; then + echo "Error: Not in a git repository" + exit 1 +fi + +mkdir -p "$REPO_ROOT/.git/hooks" + +# Function to install the pre-commit hook +install_pre_commit_hook() { + local pre_commit_hook="$REPO_ROOT/.git/hooks/pre-commit" + + echo "Installing pre-commit hook..." + + cat > "$pre_commit_hook" << 'EOF' +#!/bin/bash + +# Get the directory where this hook is located +HOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Go to the repository root (two levels up from .git/hooks) +REPO_ROOT="$(dirname "$(dirname "$HOOK_DIR")")" + +# Run the lint script +echo "Running lint check..." +if ! "$REPO_ROOT/Scripts/lint"; then + echo "Lint check failed. Please fix formatting issues before committing." + exit 1 +fi + +echo "Lint check passed." +EOF + + chmod +x "$pre_commit_hook" + echo "Pre-commit hook installed successfully!" +} + +# Install the pre-commit hook +install_pre_commit_hook + +echo "All git hooks installed successfully!" +echo "The pre-commit hook will run 'Scripts/lint' before each commit." diff --git a/Scripts/lint b/Scripts/lint new file mode 100755 index 0000000..2050e33 --- /dev/null +++ b/Scripts/lint @@ -0,0 +1,10 @@ +#!/bin/bash + +# Get the directory where this script is located +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Go to the repository root (one level up from Scripts) +REPO_ROOT="$(dirname "$SCRIPT_DIR")" + +# Run swift format lint with full paths to preserve user's PWD +swift format lint --strict --recursive "$REPO_ROOT/Sources/" "$REPO_ROOT/Tests/" diff --git a/Sources/DevTesting/Collection Generation/CollectionGeneration.swift b/Sources/DevTesting/Collection Generation/CollectionGeneration.swift index 76075de..dc67fc0 100644 --- a/Sources/DevTesting/Collection Generation/CollectionGeneration.swift +++ b/Sources/DevTesting/Collection Generation/CollectionGeneration.swift @@ -7,7 +7,6 @@ import Foundation - extension Array { /// Creates a new array whose elements are generated by the specified closure. /// diff --git a/Sources/DevTesting/Random Value Generation/BinaryFloatingPoint+Random.swift b/Sources/DevTesting/Random Value Generation/BinaryFloatingPoint+Random.swift index aa3b4b5..1658627 100644 --- a/Sources/DevTesting/Random Value Generation/BinaryFloatingPoint+Random.swift +++ b/Sources/DevTesting/Random Value Generation/BinaryFloatingPoint+Random.swift @@ -7,7 +7,6 @@ import Foundation - extension BinaryFloatingPoint where RawSignificand: FixedWidthInteger { /// Returns a random value in the half-open range that almost always can be printed precisely in decimal. /// diff --git a/Sources/DevTesting/Random Value Generation/CaseIterable+Random.swift b/Sources/DevTesting/Random Value Generation/CaseIterable+Random.swift index 744c40d..286ce07 100644 --- a/Sources/DevTesting/Random Value Generation/CaseIterable+Random.swift +++ b/Sources/DevTesting/Random Value Generation/CaseIterable+Random.swift @@ -7,7 +7,6 @@ import Foundation - extension CaseIterable { /// Returns a random value of this type. /// diff --git a/Sources/DevTesting/Random Value Generation/Data+Random.swift b/Sources/DevTesting/Random Value Generation/Data+Random.swift index 7dc8452..89b8c64 100644 --- a/Sources/DevTesting/Random Value Generation/Data+Random.swift +++ b/Sources/DevTesting/Random Value Generation/Data+Random.swift @@ -7,7 +7,6 @@ import Foundation - extension Data { /// Returns a data instance filled with random bytes. /// diff --git a/Sources/DevTesting/Random Value Generation/Optional+Random.swift b/Sources/DevTesting/Random Value Generation/Optional+Random.swift index b5084a6..404a4c9 100644 --- a/Sources/DevTesting/Random Value Generation/Optional+Random.swift +++ b/Sources/DevTesting/Random Value Generation/Optional+Random.swift @@ -7,7 +7,6 @@ import Foundation - extension Optional { /// Randomly returns a value or `nil`. /// diff --git a/Sources/DevTesting/Random Value Generation/RandomValueGenerating.swift b/Sources/DevTesting/Random Value Generation/RandomValueGenerating.swift index 95bae8b..1d7cd72 100644 --- a/Sources/DevTesting/Random Value Generation/RandomValueGenerating.swift +++ b/Sources/DevTesting/Random Value Generation/RandomValueGenerating.swift @@ -6,12 +6,11 @@ // import Foundation -import os import Testing - +import os /// A logger used to log random seeds. -fileprivate let randomizationLogger = Logger(subsystem: "DevTesting", category: "randomization") +private let randomizationLogger = Logger(subsystem: "DevTesting", category: "randomization") /// A type that can generate random values. @@ -36,7 +35,7 @@ fileprivate let randomizationLogger = Logger(subsystem: "DevTesting", category: /// /// Importantly, ``makeRandomNumberGenerator(seed:)`` and ``randomSeed``’s setter log the seed (using subsystem /// `DevTesting` and category `randomization`), which appear in Xcode’s output and can be queried via the command-line -/// +/// public protocol RandomValueGenerating { /// The random number generator that the type uses to generate values. var randomNumberGenerator: SeedableRandomNumberGenerator { get set } diff --git a/Sources/DevTesting/Random Value Generation/SeedableRandomNumberGenerator.swift b/Sources/DevTesting/Random Value Generation/SeedableRandomNumberGenerator.swift index e5558ec..781215d 100644 --- a/Sources/DevTesting/Random Value Generation/SeedableRandomNumberGenerator.swift +++ b/Sources/DevTesting/Random Value Generation/SeedableRandomNumberGenerator.swift @@ -8,7 +8,6 @@ import Foundation import os - /// An efficient, thread-safe pseudo-random number generator that can be seeded to produce repeatable results. /// /// This type is a Swift translation version of Sebastiano Vigna’s [public domain C implementation of @@ -20,7 +19,7 @@ public struct SeedableRandomNumberGenerator: RandomNumberGenerator, Sendable { /// This state is mutated whenever ``next()`` is called or ``seed`` is set. private var state: (UInt64, UInt64) - + /// Creates a new seeded random number generator with the specified seed value. /// /// The seed is used to initialize a splitmix64 pseudo-random number generator, which is then used to initialize @@ -78,11 +77,11 @@ private struct SplitMix64RandomNumberGenerator: RandomNumberGenerator, Sendable mutating func next() -> UInt64 { - state = state &+ 0x9e3779b97f4a7c15 + state = state &+ 0x9e37_79b9_7f4a_7c15 var z = state - z = (z ^ (z >> 30)) &* 0xbf58476d1ce4e5b9 - z = (z ^ (z >> 27)) &* 0x94d049bb133111eb + z = (z ^ (z >> 30)) &* 0xbf58_476d_1ce4_e5b9 + z = (z ^ (z >> 27)) &* 0x94d0_49bb_1331_11eb return z ^ (z >> 31) } } diff --git a/Sources/DevTesting/Random Value Generation/String+Random.swift b/Sources/DevTesting/Random Value Generation/String+Random.swift index 70fb11f..a69fdb5 100644 --- a/Sources/DevTesting/Random Value Generation/String+Random.swift +++ b/Sources/DevTesting/Random Value Generation/String+Random.swift @@ -7,7 +7,6 @@ import Foundation - extension String { /// Returns a random string composed of characters from the specified collection. /// @@ -75,14 +74,14 @@ extension String { ) } - + /// Returns an array of characters whose Unicode scalar values correspond to those in the specified ranges. /// /// Every scalar in the range must be a valid Unicode scalar or execution will halt. /// /// - Parameter unicodeScalarRanges: The ranges of Unicode scalar values to convert to characters. private static func characters( - fromUnicodeScalarRanges unicodeScalarRanges: ClosedRange ... + fromUnicodeScalarRanges unicodeScalarRanges: ClosedRange... ) -> [Character] { return unicodeScalarRanges.flatMap { (unicodeScalarRange) in unicodeScalarRange.map { Character(UnicodeScalar($0)!) } diff --git a/Sources/DevTesting/Random Value Generation/URL+Random.swift b/Sources/DevTesting/Random Value Generation/URL+Random.swift index b377a0d..02a8b5d 100644 --- a/Sources/DevTesting/Random Value Generation/URL+Random.swift +++ b/Sources/DevTesting/Random Value Generation/URL+Random.swift @@ -7,7 +7,6 @@ import Foundation - extension URL { /// Returns a random URL. /// diff --git a/Sources/DevTesting/Random Value Generation/URLComponents+Random.swift b/Sources/DevTesting/Random Value Generation/URLComponents+Random.swift index 7415cb3..cb90ad3 100644 --- a/Sources/DevTesting/Random Value Generation/URLComponents+Random.swift +++ b/Sources/DevTesting/Random Value Generation/URLComponents+Random.swift @@ -7,7 +7,6 @@ import Foundation - extension URLComponents { /// Returns random URL components. /// diff --git a/Sources/DevTesting/Random Value Generation/URLQueryItem+Random.swift b/Sources/DevTesting/Random Value Generation/URLQueryItem+Random.swift index 5ba7331..6b69e9f 100644 --- a/Sources/DevTesting/Random Value Generation/URLQueryItem+Random.swift +++ b/Sources/DevTesting/Random Value Generation/URLQueryItem+Random.swift @@ -7,7 +7,6 @@ import Foundation - extension URLQueryItem { /// Returns a random URL query item. /// @@ -21,10 +20,12 @@ extension URLQueryItem { count: Int.random(in: 3 ... 10, using: &generator), using: &generator ), - value: Int.random(in: 0 ..< 10, using: &generator) == 0 ? nil : .randomAlphanumeric( - count: Int.random(in: 3 ... 10, using: &generator), - using: &generator - ) + value: Int.random(in: 0 ..< 10, using: &generator) == 0 + ? nil + : .randomAlphanumeric( + count: Int.random(in: 3 ... 10, using: &generator), + using: &generator + ) ) } } diff --git a/Sources/DevTesting/Random Value Generation/UUID+Random.swift b/Sources/DevTesting/Random Value Generation/UUID+Random.swift index f82f972..eeb0d3b 100644 --- a/Sources/DevTesting/Random Value Generation/UUID+Random.swift +++ b/Sources/DevTesting/Random Value Generation/UUID+Random.swift @@ -7,7 +7,6 @@ import Foundation - extension UUID { /// Returns a random UUID. /// diff --git a/Sources/DevTesting/Stubbing/Stub.swift b/Sources/DevTesting/Stubbing/Stub.swift index d527430..f20eb34 100644 --- a/Sources/DevTesting/Stubbing/Stub.swift +++ b/Sources/DevTesting/Stubbing/Stub.swift @@ -8,7 +8,6 @@ import Foundation import os - /// A stub for a function. public final class ThrowingStub where ErrorType: Error { /// A recorded call to the stub. @@ -37,7 +36,7 @@ public final class ThrowingStub where ErrorTyp /// The stub’s mutable properties. private let mutableProperties: OSAllocatedUnfairLock - + /// Creates a new throwing stub with the specified default result. /// /// - Parameters: @@ -55,7 +54,7 @@ public final class ThrowingStub where ErrorTyp ) } - + /// The stub’s default result. /// /// This result is used whenever the stub is called and ``resultQueue`` is empty. @@ -84,7 +83,7 @@ public final class ThrowingStub where ErrorTyp } } - + /// The stub’s recorded calls. /// /// If you just need the call’s arguments, you can use ``callArguments`` instead. @@ -92,13 +91,13 @@ public final class ThrowingStub where ErrorTyp return mutableProperties.withLockUnchecked { $0.calls } } - + /// Clears the stub’s recorded calls. public func clearCalls() { mutableProperties.withLockUnchecked { $0.calls = [] } } - + /// Calls the stub with the specified arguments, recording the call. /// /// If the stub’s ``resultQueue`` is empty, returns or throws ``defaultResult``. Otherwise, removes the first @@ -107,11 +106,12 @@ public final class ThrowingStub where ErrorTyp /// - Parameter arguments: The arguments with which to call the stub. public func callAsFunction(_ arguments: Arguments) throws(ErrorType) -> ReturnType { let result = mutableProperties.withLockUnchecked { (properties) in - let result = if properties.resultQueue.isEmpty { - properties.defaultResult - } else { - properties.resultQueue.removeFirst() - } + let result = + if properties.resultQueue.isEmpty { + properties.defaultResult + } else { + properties.resultQueue.removeFirst() + } properties.calls.append( .init(arguments: arguments, result: result) @@ -131,7 +131,7 @@ extension ThrowingStub { return calls.map(\.arguments) } - + /// The return values of the stub’s recorded calls. public var callResults: [Result] { return calls.map(\.result) @@ -139,7 +139,7 @@ extension ThrowingStub { } -extension ThrowingStub: Sendable where Arguments: Sendable, ReturnType: Sendable { } +extension ThrowingStub: Sendable where Arguments: Sendable, ReturnType: Sendable {} // MARK: - Arguments is Void diff --git a/Tests/DevTestingTests/Collection Generation/CollectionGenerationTests.swift b/Tests/DevTestingTests/Collection Generation/CollectionGenerationTests.swift index b59b28f..bb96335 100644 --- a/Tests/DevTestingTests/Collection Generation/CollectionGenerationTests.swift +++ b/Tests/DevTestingTests/Collection Generation/CollectionGenerationTests.swift @@ -9,7 +9,6 @@ import DevTesting import Foundation import Testing - struct CollectionGenerationTests { @Test func indexedArrayInit() { @@ -73,7 +72,7 @@ struct CollectionGenerationTests { defer { i += 1 } return (i, "\(i)") } - let expectedDictionary = Dictionary(uniqueKeysWithValues: (0 ..< count).map { ($0, "\($0)" ) }) + let expectedDictionary = Dictionary(uniqueKeysWithValues: (0 ..< count).map { ($0, "\($0)") }) #expect(dictionary == expectedDictionary) } diff --git a/Tests/DevTestingTests/Random Value Generation/BinaryFloatingPoint+RandomTests.swift b/Tests/DevTestingTests/Random Value Generation/BinaryFloatingPoint+RandomTests.swift index 22df741..70f2cb6 100644 --- a/Tests/DevTestingTests/Random Value Generation/BinaryFloatingPoint+RandomTests.swift +++ b/Tests/DevTestingTests/Random Value Generation/BinaryFloatingPoint+RandomTests.swift @@ -9,7 +9,6 @@ import DevTesting import Foundation import Testing - struct BinaryFloatingPoint_RandomTests { @Test func halfOpenRange() throws { @@ -64,6 +63,6 @@ struct BinaryFloatingPoint_RandomTests { } -fileprivate struct CodableBinaryFloat: Codable where Value: BinaryFloatingPoint & Codable { +private struct CodableBinaryFloat: Codable where Value: BinaryFloatingPoint & Codable { let value: Value } diff --git a/Tests/DevTestingTests/Random Value Generation/CaseIterable+RandomTests.swift b/Tests/DevTestingTests/Random Value Generation/CaseIterable+RandomTests.swift index c33948d..9c828f6 100644 --- a/Tests/DevTestingTests/Random Value Generation/CaseIterable+RandomTests.swift +++ b/Tests/DevTestingTests/Random Value Generation/CaseIterable+RandomTests.swift @@ -9,7 +9,6 @@ import DevTesting import Foundation import Testing - struct CaseIterable_RandomTests { @Test func randomReturnsNilForUninhabitedEnum() { @@ -31,7 +30,7 @@ struct CaseIterable_RandomTests { #expect(countsByCase.count == 3) for (_, count) in countsByCase { let caseProportion = Double(count) / Double(results.count) - #expect(caseProportion.isApproximatelyEqual(to: 1/3, absoluteTolerance: 0.03)) + #expect(caseProportion.isApproximatelyEqual(to: 1 / 3, absoluteTolerance: 0.03)) } } } diff --git a/Tests/DevTestingTests/Random Value Generation/Data+RandomTests.swift b/Tests/DevTestingTests/Random Value Generation/Data+RandomTests.swift index 237387d..945ab99 100644 --- a/Tests/DevTestingTests/Random Value Generation/Data+RandomTests.swift +++ b/Tests/DevTestingTests/Random Value Generation/Data+RandomTests.swift @@ -9,7 +9,6 @@ import DevTesting import Foundation import Testing - struct Data_RandomTests { @Test func randomReturnsEmptyDataWhenCountIsNonPositive() { diff --git a/Tests/DevTestingTests/Random Value Generation/Optional+RandomTests.swift b/Tests/DevTestingTests/Random Value Generation/Optional+RandomTests.swift index 1c47443..873d725 100644 --- a/Tests/DevTestingTests/Random Value Generation/Optional+RandomTests.swift +++ b/Tests/DevTestingTests/Random Value Generation/Optional+RandomTests.swift @@ -10,7 +10,6 @@ import Foundation import RealModule import Testing - struct Optional_RandomTests { @Test func randomValuesAreEvenlyDistributed() { diff --git a/Tests/DevTestingTests/Random Value Generation/RandomValueGeneratingTests.swift b/Tests/DevTestingTests/Random Value Generation/RandomValueGeneratingTests.swift index 26a2e20..f95d1e3 100644 --- a/Tests/DevTestingTests/Random Value Generation/RandomValueGeneratingTests.swift +++ b/Tests/DevTestingTests/Random Value Generation/RandomValueGeneratingTests.swift @@ -9,7 +9,6 @@ import DevTesting import Foundation import Testing - struct RandomValueGeneratingTests { private let iterationRange = 0 ..< 10 private var generator = RandomValueGenerator() diff --git a/Tests/DevTestingTests/Random Value Generation/SeedableRandomNumberGeneratorTests.swift b/Tests/DevTestingTests/Random Value Generation/SeedableRandomNumberGeneratorTests.swift index bf0625b..59acf73 100644 --- a/Tests/DevTestingTests/Random Value Generation/SeedableRandomNumberGeneratorTests.swift +++ b/Tests/DevTestingTests/Random Value Generation/SeedableRandomNumberGeneratorTests.swift @@ -9,7 +9,6 @@ import DevTesting import Foundation import Testing - struct SeedableRandomNumberGeneratorTests { let iterationRange = 0 ..< 1000 diff --git a/Tests/DevTestingTests/Random Value Generation/String+RandomTests.swift b/Tests/DevTestingTests/Random Value Generation/String+RandomTests.swift index 12e31ad..98dac2b 100644 --- a/Tests/DevTestingTests/Random Value Generation/String+RandomTests.swift +++ b/Tests/DevTestingTests/Random Value Generation/String+RandomTests.swift @@ -5,10 +5,10 @@ // Created by Prachi Gauriar on 3/5/25. // -@testable import DevTesting import Foundation import Testing +@testable import DevTesting struct String_RandomTests { @Test diff --git a/Tests/DevTestingTests/Random Value Generation/URL+RandomTests.swift b/Tests/DevTestingTests/Random Value Generation/URL+RandomTests.swift index de3dda3..4cd355c 100644 --- a/Tests/DevTestingTests/Random Value Generation/URL+RandomTests.swift +++ b/Tests/DevTestingTests/Random Value Generation/URL+RandomTests.swift @@ -9,7 +9,6 @@ import DevTesting import Foundation import Testing - struct URL_RandomTests { @Test( arguments: [ diff --git a/Tests/DevTestingTests/Random Value Generation/URLComponents+RandomTests.swift b/Tests/DevTestingTests/Random Value Generation/URLComponents+RandomTests.swift index 31e9f65..261fbab 100644 --- a/Tests/DevTestingTests/Random Value Generation/URLComponents+RandomTests.swift +++ b/Tests/DevTestingTests/Random Value Generation/URLComponents+RandomTests.swift @@ -9,7 +9,6 @@ import DevTesting import Foundation import Testing - struct URLComponents_RandomTests { @Test func randomReturnsCorrectComponentsWhenIncludeArgumentsAreNil() throws { diff --git a/Tests/DevTestingTests/Random Value Generation/URLQueryItem+RandomTests.swift b/Tests/DevTestingTests/Random Value Generation/URLQueryItem+RandomTests.swift index e99f9b7..5c77536 100644 --- a/Tests/DevTestingTests/Random Value Generation/URLQueryItem+RandomTests.swift +++ b/Tests/DevTestingTests/Random Value Generation/URLQueryItem+RandomTests.swift @@ -9,7 +9,6 @@ import DevTesting import Foundation import Testing - struct URLQueryItem_RandomTests { @Test func randomReturnsCorrectQueryItems() { diff --git a/Tests/DevTestingTests/Random Value Generation/UUID+RandomTests.swift b/Tests/DevTestingTests/Random Value Generation/UUID+RandomTests.swift index 3cac8fd..18d90b6 100644 --- a/Tests/DevTestingTests/Random Value Generation/UUID+RandomTests.swift +++ b/Tests/DevTestingTests/Random Value Generation/UUID+RandomTests.swift @@ -9,7 +9,6 @@ import DevTesting import Foundation import Testing - final class UUID_RandomTests { @Test func generatesUUIDFromTwoUInt64s() { @@ -21,16 +20,16 @@ final class UUID_RandomTests { // Except for bytes 6 and 8, all bytes are just taken from the randomly generated values. Byte 6 starts with // 0x4 and is otherwise random. The first two bits of Byte 8 are 2, but is otherwise random. - #expect(uuid.uuid.0 == UInt8((uint1 >> (0 * 8)) & 0xff)) - #expect(uuid.uuid.1 == UInt8((uint1 >> (1 * 8)) & 0xff)) - #expect(uuid.uuid.2 == UInt8((uint1 >> (2 * 8)) & 0xff)) - #expect(uuid.uuid.3 == UInt8((uint1 >> (3 * 8)) & 0xff)) - #expect(uuid.uuid.4 == UInt8((uint1 >> (4 * 8)) & 0xff)) - #expect(uuid.uuid.5 == UInt8((uint1 >> (5 * 8)) & 0xff)) - #expect(uuid.uuid.6 == UInt8((uint1 >> (6 * 8)) & 0x0f | 0x40)) - #expect(uuid.uuid.7 == UInt8((uint1 >> (7 * 8)) & 0xff)) - #expect(uuid.uuid.8 == UInt8((uint2 >> (0 * 8)) & 0x3f | 0x80)) - #expect(uuid.uuid.9 == UInt8((uint2 >> (1 * 8)) & 0xff)) + #expect(uuid.uuid.0 == UInt8((uint1 >> (0 * 8)) & 0xff)) + #expect(uuid.uuid.1 == UInt8((uint1 >> (1 * 8)) & 0xff)) + #expect(uuid.uuid.2 == UInt8((uint1 >> (2 * 8)) & 0xff)) + #expect(uuid.uuid.3 == UInt8((uint1 >> (3 * 8)) & 0xff)) + #expect(uuid.uuid.4 == UInt8((uint1 >> (4 * 8)) & 0xff)) + #expect(uuid.uuid.5 == UInt8((uint1 >> (5 * 8)) & 0xff)) + #expect(uuid.uuid.6 == UInt8((uint1 >> (6 * 8)) & 0x0f | 0x40)) + #expect(uuid.uuid.7 == UInt8((uint1 >> (7 * 8)) & 0xff)) + #expect(uuid.uuid.8 == UInt8((uint2 >> (0 * 8)) & 0x3f | 0x80)) + #expect(uuid.uuid.9 == UInt8((uint2 >> (1 * 8)) & 0xff)) #expect(uuid.uuid.10 == UInt8((uint2 >> (2 * 8)) & 0xff)) #expect(uuid.uuid.11 == UInt8((uint2 >> (3 * 8)) & 0xff)) #expect(uuid.uuid.12 == UInt8((uint2 >> (4 * 8)) & 0xff)) diff --git a/Tests/DevTestingTests/Stubbing/StubTests.swift b/Tests/DevTestingTests/Stubbing/StubTests.swift index ff2af23..5fb5599 100644 --- a/Tests/DevTestingTests/Stubbing/StubTests.swift +++ b/Tests/DevTestingTests/Stubbing/StubTests.swift @@ -9,7 +9,6 @@ import DevTesting import Foundation import Testing - struct StubTests { @Test func initSetsProperties() { @@ -60,7 +59,7 @@ struct StubTests { let arguments = (0 ... 5).map(String.init(_:)) let expectedResults = resultQueue + [defaultResult] for (argument, expectedResult) in zip(arguments, expectedResults) { - let result = Result { () throws (HashableError) in + let result = Result { () throws(HashableError) in try stub(argument) } diff --git a/Tests/DevTestingTests/Supporting Types/CaseIterableEnums.swift b/Tests/DevTestingTests/Supporting Types/CaseIterableEnums.swift index f2e11e4..c410838 100644 --- a/Tests/DevTestingTests/Supporting Types/CaseIterableEnums.swift +++ b/Tests/DevTestingTests/Supporting Types/CaseIterableEnums.swift @@ -7,7 +7,6 @@ import Foundation - enum UninhabitedEnum: CaseIterable { // Intentionally empty } diff --git a/Tests/DevTestingTests/Supporting Types/HashableError.swift b/Tests/DevTestingTests/Supporting Types/HashableError.swift index 4c6647e..fa66c3c 100644 --- a/Tests/DevTestingTests/Supporting Types/HashableError.swift +++ b/Tests/DevTestingTests/Supporting Types/HashableError.swift @@ -7,7 +7,6 @@ import Foundation - struct HashableError: Error, Hashable { let id: Int }