IobCalculateTests.swift 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. import Foundation
  2. import Testing
  3. @testable import Trio
  4. @Suite("Calculate IOB Tests") struct CalculateIobTests {
  5. // Helper function to create a basic treatment
  6. func createTreatment(insulin: Decimal, timestamp: Date) -> ComputedPumpHistoryEvent {
  7. ComputedPumpHistoryEvent.forTest(
  8. type: .bolus,
  9. timestamp: timestamp,
  10. insulin: insulin
  11. )
  12. }
  13. // Helper function to create a basic profile
  14. func createProfile(
  15. curve: InsulinCurve = .rapidActing,
  16. useCustomPeakTime: Bool = false,
  17. insulinPeakTime: Decimal = 0
  18. ) -> Profile {
  19. var profile = Profile()
  20. profile.curve = curve
  21. profile.useCustomPeakTime = useCustomPeakTime
  22. profile.insulinPeakTime = insulinPeakTime
  23. profile.dia = 3
  24. return profile
  25. }
  26. @Test("should return nil when treatment has no insulin") func returnNilForNoInsulin() async throws {
  27. let treatment = ComputedPumpHistoryEvent.forTest(
  28. type: .bolus,
  29. timestamp: Date()
  30. )
  31. let result = try IobCalculation.iobCalc(
  32. treatment: treatment,
  33. time: Date(),
  34. dia: 3,
  35. profile: createProfile()
  36. )
  37. #expect(result == nil)
  38. }
  39. @Test("should calculate IOB with default rapid-acting settings") func calculateDefaultRapidActing() async throws {
  40. let now = Date()
  41. let thirtyMinsAgo = now - 30.minutesToSeconds
  42. let treatment = createTreatment(insulin: 2, timestamp: thirtyMinsAgo)
  43. let result = try IobCalculation.iobCalc(
  44. treatment: treatment,
  45. time: now,
  46. dia: 3,
  47. profile: createProfile()
  48. )
  49. #expect(result != nil)
  50. #expect(result!.activityContrib.isApproximatelyEqual(to: 0.0115, epsilon: 0.0001))
  51. #expect(result!.iobContrib.isApproximatelyEqual(to: 1.8085, epsilon: 0.0001))
  52. }
  53. @Test("should calculate IOB with custom peak time for rapid-acting insulin") func calculateCustomPeakRapidActing() async throws {
  54. let now = Date()
  55. let thirtyMinsAgo = now - 30.minutesToSeconds
  56. let treatment = createTreatment(insulin: 2, timestamp: thirtyMinsAgo)
  57. let profile = createProfile(
  58. curve: .rapidActing,
  59. useCustomPeakTime: true,
  60. insulinPeakTime: 100
  61. )
  62. let result = try IobCalculation.iobCalc(
  63. treatment: treatment,
  64. time: now,
  65. dia: 3,
  66. profile: profile
  67. )
  68. #expect(result != nil)
  69. #expect(result!.activityContrib.isApproximatelyEqual(to: 0.0079, epsilon: 0.0001))
  70. #expect(result!.iobContrib.isApproximatelyEqual(to: 1.8763, epsilon: 0.0001))
  71. }
  72. @Test("should handle peak time limits for rapid-acting insulin") func handlePeakTimeLimitsRapidActing() async throws {
  73. let now = Date()
  74. let thirtyMinsAgo = now - 30.minutesToSeconds
  75. let treatment = createTreatment(insulin: 2, timestamp: thirtyMinsAgo)
  76. // Test upper limit (120)
  77. let profileHigh = createProfile(
  78. curve: .rapidActing,
  79. useCustomPeakTime: true,
  80. insulinPeakTime: 150
  81. )
  82. let resultHigh = try IobCalculation.iobCalc(
  83. treatment: treatment,
  84. time: now,
  85. dia: 3,
  86. profile: profileHigh
  87. )
  88. #expect(resultHigh != nil)
  89. // Test lower limit (50)
  90. let profileLow = createProfile(
  91. curve: .rapidActing,
  92. useCustomPeakTime: true,
  93. insulinPeakTime: 30
  94. )
  95. let resultLow = try IobCalculation.iobCalc(
  96. treatment: treatment,
  97. time: now,
  98. dia: 3,
  99. profile: profileLow
  100. )
  101. #expect(resultLow != nil)
  102. }
  103. @Test("should calculate IOB with ultra-rapid insulin") func calculateUltraRapid() async throws {
  104. let now = Date()
  105. let thirtyMinsAgo = now - 30.minutesToSeconds
  106. let treatment = createTreatment(insulin: 2, timestamp: thirtyMinsAgo)
  107. let profile = createProfile(curve: .ultraRapid)
  108. let result = try IobCalculation.iobCalc(
  109. treatment: treatment,
  110. time: now,
  111. dia: 3,
  112. profile: profile
  113. )
  114. #expect(result != nil)
  115. #expect(result!.activityContrib.isApproximatelyEqual(to: 0.01569, epsilon: 0.0001))
  116. #expect(result!.iobContrib.isApproximatelyEqual(to: 1.7202, epsilon: 0.0001))
  117. }
  118. @Test("should handle peak time limits for ultra-rapid insulin") func handlePeakTimeLimitsUltraRapid() async throws {
  119. let now = Date()
  120. let thirtyMinsAgo = now - 30.minutesToSeconds
  121. let treatment = createTreatment(insulin: 2, timestamp: thirtyMinsAgo)
  122. // Test upper limit (100)
  123. let profileHigh = createProfile(
  124. curve: .ultraRapid,
  125. useCustomPeakTime: true,
  126. insulinPeakTime: 120
  127. )
  128. let resultHigh = try IobCalculation.iobCalc(
  129. treatment: treatment,
  130. time: now,
  131. dia: 3,
  132. profile: profileHigh
  133. )
  134. #expect(resultHigh != nil)
  135. // Test lower limit (35)
  136. let profileLow = createProfile(
  137. curve: .ultraRapid,
  138. useCustomPeakTime: true,
  139. insulinPeakTime: 30
  140. )
  141. let resultLow = try IobCalculation.iobCalc(
  142. treatment: treatment,
  143. time: now,
  144. dia: 3,
  145. profile: profileLow
  146. )
  147. #expect(resultLow != nil)
  148. }
  149. @Test("should handle insulin activity after DIA") func handleActivityAfterDIA() async throws {
  150. let now = Date()
  151. let fourHoursAgo = now - (4 * 60 * 60)
  152. let treatment = createTreatment(insulin: 2, timestamp: fourHoursAgo)
  153. let result = try IobCalculation.iobCalc(
  154. treatment: treatment,
  155. time: now,
  156. dia: 3,
  157. profile: createProfile()
  158. )
  159. #expect(result != nil)
  160. #expect(result?.activityContrib == 0)
  161. #expect(result?.iobContrib == 0)
  162. }
  163. }