Skip to content

Commit 7a63f66

Browse files
authored
CORE Sensor Related Additional Unit Tests (#39)
# *Additional Tests on Bluetooth-related functionality* ## ♻️ Current situation & Problem Our code coverage is lower than expected; there was no test on decoding logic. ## ⚙️ Release Notes - Added tests on decoding logic. ## ✅ Testing All tests pass. ## 📝 Code of Conduct & Contributing Guidelines By submitting creating this pull request, you agree to follow our [Code of Conduct](https://github.com/CS342/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/CS342/.github/blob/main/CONTRIBUTING.md): - [X] I agree to follow the [Code of Conduct](https://github.com/CS342/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/CS342/.github/blob/main/CONTRIBUTING.md).
1 parent 281bef3 commit 7a63f66

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

NeutroFeverGuard.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
B0DF8DF72D7BFEFB00581A00 /* FeverMonitorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0DF8DF62D7BFEF600581A00 /* FeverMonitorTests.swift */; };
7878
B0DF8DFC2D7C117800581A00 /* HealthDataFetchable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0DF8DFB2D7C114900581A00 /* HealthDataFetchable.swift */; };
7979
B0DF8DFD2D7C123200581A00 /* HealthDataFetchable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0DF8DFB2D7C114900581A00 /* HealthDataFetchable.swift */; };
80+
B0E1C5C32D80D3CB009CF90A /* SkinTemperatureDecodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0E1C5C22D80D3CB009CF90A /* SkinTemperatureDecodingTests.swift */; };
8081
B0FF4DD22D797FEA0076A043 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0FF4DD12D797FEA0076A043 /* NotificationManager.swift */; };
8182
C42B98FF2D769E54005D820B /* SpeziKeychainStorage in Frameworks */ = {isa = PBXBuildFile; productRef = C42B98FE2D769E54005D820B /* SpeziKeychainStorage */; };
8283
C42C1B312D782A7600EA417F /* MedicationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42C1B302D782A7100EA417F /* MedicationView.swift */; };
@@ -160,6 +161,7 @@
160161
B0D4C9372D790F5E000643C7 /* LabResultsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabResultsManager.swift; sourceTree = "<group>"; };
161162
B0DF8DF62D7BFEF600581A00 /* FeverMonitorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeverMonitorTests.swift; sourceTree = "<group>"; };
162163
B0DF8DFB2D7C114900581A00 /* HealthDataFetchable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthDataFetchable.swift; sourceTree = "<group>"; };
164+
B0E1C5C22D80D3CB009CF90A /* SkinTemperatureDecodingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkinTemperatureDecodingTests.swift; sourceTree = "<group>"; };
163165
B0FF4DD12D797FEA0076A043 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = "<group>"; };
164166
C42C1B302D782A7100EA417F /* MedicationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MedicationView.swift; sourceTree = "<group>"; };
165167
C42C1C6A2D7A985B00EA417F /* MedicationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MedicationManager.swift; sourceTree = "<group>"; };
@@ -377,6 +379,7 @@
377379
isa = PBXGroup;
378380
children = (
379381
B0DF8DF62D7BFEF600581A00 /* FeverMonitorTests.swift */,
382+
B0E1C5C22D80D3CB009CF90A /* SkinTemperatureDecodingTests.swift */,
380383
653A256128338800005D4D48 /* NeutroFeverGuardTests.swift */,
381384
C4A367C72D73C1E1009923C9 /* DataErrorTests.swift */,
382385
C4C8A3B22D71204200F313AE /* HelperFuncTests.swift */,
@@ -674,6 +677,7 @@
674677
isa = PBXSourcesBuildPhase;
675678
buildActionMask = 2147483647;
676679
files = (
680+
B0E1C5C32D80D3CB009CF90A /* SkinTemperatureDecodingTests.swift in Sources */,
677681
C4A367C82D73C1EC009923C9 /* DataErrorTests.swift in Sources */,
678682
B08E39F92D7C416000077929 /* FeverMonitoring.swift in Sources */,
679683
EB02C6612D5D52E90035AA89 /* NeutroFeverGuardTests.swift in Sources */,
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//
2+
// This source file is part of the NeutroFeverGuard based on the Stanford Spezi Template Application project
3+
//
4+
// SPDX-FileCopyrightText: 2025 Stanford University
5+
//
6+
// SPDX-License-Identifier: MIT
7+
//
8+
import Foundation
9+
@testable import NeutroFeverGuard
10+
import Testing
11+
12+
@MainActor
13+
struct SkinTemperatureDecodingTests {
14+
@Test("Decode valid Celsius temperature")
15+
func testDecodeValidCelsiusTemperature() {
16+
// Flags: 0x00 (Celsius, no timestamp)
17+
let data: [UInt8] = [0x00, 0x42, 0x0E, 0x00, 0xFE]
18+
let measurement = SkinTemperatureMeasurement(from: Data(data))
19+
20+
#expect(measurement != nil)
21+
#expect(measurement?.temperature == 36.50)
22+
#expect(measurement?.unit == .celsius)
23+
#expect(measurement?.timestamp == nil)
24+
}
25+
26+
@Test("Decode valid Fahrenheit temperature")
27+
func testDecodeValidFahrenheitTemperature() {
28+
// Flags: 0x01 (Fahrenheit, no timestamp)
29+
let data: [UInt8] = [0x01, 0xDA, 0x03, 0x00, 0xFF]
30+
let measurement = SkinTemperatureMeasurement(from: Data(data))
31+
32+
#expect(measurement != nil)
33+
#expect(measurement?.temperature == 98.60)
34+
#expect(measurement?.unit == .fahrenheit)
35+
#expect(measurement?.timestamp == nil)
36+
}
37+
38+
@Test("Handle sensor off-body NaN value")
39+
func testDecodeSensorOffBody() {
40+
// Flags: 0x00 (Celsius, no timestamp), Value: NaN (0x007FFFFF)
41+
let data: [UInt8] = [0x00, 0xFF, 0xFF, 0x7F, 0x00]
42+
let measurement = SkinTemperatureMeasurement(from: Data(data))
43+
44+
#expect(measurement == nil)
45+
}
46+
47+
@Test("Decode temperature with timestamp")
48+
func testDecodeTemperatureWithTimestamp() {
49+
// Flags: 0x02 (Celsius + Timestamp)
50+
// Temp: 37.20°C, Timestamp: 2025-03-10 14:30:45
51+
let data: [UInt8] = [
52+
0x02, // Flags
53+
0x88, 0x0E, 0x00, 0xFE, // Temperature: 37.20°C
54+
0xE9, 0x07, // Year: 2025
55+
0x03, // Month: 3 (March)
56+
0x0A, // Day: 10
57+
0x0E, // Hour: 14
58+
0x1E, // Minute: 30
59+
0x2D // Second: 45
60+
]
61+
let measurement = SkinTemperatureMeasurement(from: Data(data))
62+
63+
#expect(measurement != nil)
64+
#expect(measurement?.temperature == 37.20)
65+
#expect(measurement?.unit == .celsius)
66+
#expect(measurement?.timestamp != nil)
67+
68+
if let timestamp = measurement?.timestamp {
69+
let calendar = Calendar.current
70+
let components = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: timestamp)
71+
72+
#expect(components.year == 2025)
73+
#expect(components.month == 3)
74+
#expect(components.day == 10)
75+
#expect(components.hour == 14)
76+
#expect(components.minute == 30)
77+
#expect(components.second == 45)
78+
} else {
79+
#expect(true, "Timestamp should not be nil")
80+
}
81+
}
82+
83+
@Test("Handle incomplete data")
84+
func testDecodeIncompleteData() {
85+
let incompleteData: [UInt8] = [0x00, 0x42] // Too short
86+
let measurement = SkinTemperatureMeasurement(from: Data(incompleteData))
87+
88+
#expect(measurement == nil)
89+
}
90+
91+
@Test("Handle corrupted timestamp data")
92+
func testDecodeInvalidTimestamp() {
93+
let data: [UInt8] = [
94+
0x02, // Flags (Celsius + Timestamp present)
95+
0x88, 0x2E, 0x00, 0x00, // Temperature: 37.20°C
96+
0xE9, 0x07, // Year: 2025
97+
0x03 // Month: 3 (missing Day, Hour, Min, Sec)
98+
]
99+
let measurement = SkinTemperatureMeasurement(from: Data(data))
100+
101+
#expect(measurement != nil)
102+
#expect(measurement?.timestamp == nil)
103+
}
104+
}

0 commit comments

Comments
 (0)