11@testable import Grodt
2- import Testing
2+ import XCTest
33import Foundation
44
55fileprivate final class MockPriceService : PriceService {
@@ -18,12 +18,11 @@ fileprivate final class MockPriceService: PriceService {
1818 }
1919}
2020
21- class HoldingsPerformanceCalculatorTests {
21+ final class HoldingsPerformanceCalculatorTests : XCTestCase {
2222 private var mockPriceService = MockPriceService ( )
2323 private lazy var calculator = HoldingsPerformanceCalculator ( priceService: mockPriceService)
2424
25- @Test
26- func series_SingleTicker_CarryForwardAndCumulativeMoneyIn( ) async throws {
25+ func testSeries_SingleTicker_CarryForwardAndCumulativeMoneyIn( ) async throws {
2726 // Given
2827 let ticker = " AAPL "
2928 let buy = givenTransaction ( purchasedOn: YearMonthDayDate ( 2024 , 1 , 10 ) , ticker: ticker, fees: 1 , shares: 10 , pricePerShare: 5 )
@@ -50,12 +49,11 @@ class HoldingsPerformanceCalculatorTests {
5049 DatedPortfolioPerformance ( moneyIn: 51 , value: 70 , date: YearMonthDayDate ( 2024 , 1 , 14 ) ) ,
5150 DatedPortfolioPerformance ( moneyIn: 51 , value: 90 , date: YearMonthDayDate ( 2024 , 1 , 15 ) )
5251 ]
53- #expect ( series == expected2)
54- #expect ( mockPriceService. historicalPriceCallCount [ ticker] ! == 1 )
52+ XCTAssertEqual ( series, expected2)
53+ XCTAssertEqual ( mockPriceService. historicalPriceCallCount [ ticker] ?? 0 , 1 )
5554 }
5655
57- @Test
58- func series_MultiTicker_AggregationAndCarryForward( ) async throws {
56+ func testSeries_MultiTicker_AggregationAndCarryForward( ) async throws {
5957 // Given: MSFT buys on 10 (3 sh @10) and 12 (2 sh @12), AAPL buy on 14 (1 sh @100 + 2 fees)
6058 let msft1 = givenTransaction ( purchasedOn: YearMonthDayDate ( 2024 , 1 , 10 ) , ticker: " MSFT " , shares: 3 , pricePerShare: 10 )
6159 let msft2 = givenTransaction ( purchasedOn: YearMonthDayDate ( 2024 , 1 , 12 ) , ticker: " MSFT " , shares: 2 , pricePerShare: 12 )
@@ -85,24 +83,22 @@ class HoldingsPerformanceCalculatorTests {
8583 DatedPortfolioPerformance ( moneyIn: 156 , value: 107 , date: YearMonthDayDate ( 2024 , 1 , 14 ) ) ,
8684 DatedPortfolioPerformance ( moneyIn: 156 , value: 132 , date: YearMonthDayDate ( 2024 , 1 , 15 ) )
8785 ]
88- #expect ( series == expected)
86+ XCTAssertEqual ( series, expected)
8987 // One historical fetch per ticker during prefetch
90- #expect ( mockPriceService. historicalPriceCallCount [ " MSFT " ] ! == 1 )
91- #expect ( mockPriceService. historicalPriceCallCount [ " AAPL " ] ! == 1 )
88+ XCTAssertEqual ( mockPriceService. historicalPriceCallCount [ " MSFT " ] ?? 0 , 1 )
89+ XCTAssertEqual ( mockPriceService. historicalPriceCallCount [ " AAPL " ] ?? 0 , 1 )
9290 }
9391
94- @Test
95- func series_EmptyTransactions_ReturnsEmpty( ) async throws {
92+ func testSeries_EmptyTransactions_ReturnsEmpty( ) async throws {
9693 let start = YearMonthDayDate ( 2024 , 1 , 10 )
9794 let end = YearMonthDayDate ( 2024 , 1 , 15 )
9895 let series = try await calculator. performanceSeries ( for: [ ] , from: start, to: end)
9996 // Then
10097 let expected : [ DatedPortfolioPerformance ] = [ ]
101- #expect ( series == expected)
98+ XCTAssertEqual ( series, expected)
10299 }
103100
104- @Test
105- func series_TransactionsInFuture_BeforeStartIgnored( ) async throws {
101+ func testSeries_TransactionsInFuture_BeforeStartIgnored( ) async throws {
106102 // Given a purchase after the range end – should have no effect
107103 let future = givenTransaction ( purchasedOn: YearMonthDayDate ( 2024 , 1 , 20 ) , ticker: " NVDA " , shares: 1 , pricePerShare: 100 )
108104 let start = YearMonthDayDate ( 2024 , 1 , 10 )
@@ -122,13 +118,12 @@ class HoldingsPerformanceCalculatorTests {
122118 DatedPortfolioPerformance ( moneyIn: 0 , value: 0 , date: YearMonthDayDate ( 2024 , 1 , 14 ) ) ,
123119 DatedPortfolioPerformance ( moneyIn: 0 , value: 0 , date: YearMonthDayDate ( 2024 , 1 , 15 ) )
124120 ]
125- #expect ( series == expected)
121+ XCTAssertEqual ( series, expected)
126122 // Prefetch may still fetch NVDA once
127- #expect ( mockPriceService. historicalPriceCallCount [ " NVDA " ] ! == 1 )
123+ XCTAssertEqual ( mockPriceService. historicalPriceCallCount [ " NVDA " ] ?? 0 , 1 )
128124 }
129125
130- @Test
131- func performance_40Years_10Tickers( ) async throws {
126+ func testPerformance_40Years_10Tickers( ) async throws {
132127 // Local helper to add years to a YearMonthDayDate
133128 func addYears( _ years: Int , to day: YearMonthDayDate ) -> YearMonthDayDate {
134129 var calendar = Calendar . current
@@ -186,13 +181,13 @@ class HoldingsPerformanceCalculatorTests {
186181 let duration = t0. duration ( to: clock. now)
187182
188183 // Sanity
189- #expect ( series. count == allDays. count)
190- #expect ( ! series. isEmpty)
184+ XCTAssertEqual ( series. count, allDays. count)
185+ XCTAssertFalse ( series. isEmpty)
191186
192187 // Convert Duration to seconds (lenient threshold; tune for CI hardware)
193188 let comps = duration. components
194189 let seconds = Double ( comps. seconds) + Double( comps. attoseconds) / 1_000_000_000_000_000_000.0
195- #expect ( seconds < 10.0 )
190+ XCTAssertLessThan ( seconds, 10.0 )
196191 }
197192
198193
0 commit comments