Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,12 @@ missing_docs:
excludes_inherited_types: false
excludes_trivial_init: false
severity: error

custom_rules:
no_try_optional_in_tests:
name: "No try? in tests"
message: "Avoid `try?` in tests. Use `try XCTUnwrap(...)` instead."
regex: 'try\?'
severity: error
included:
- "./Tests/.*\\.swift"
2 changes: 2 additions & 0 deletions Tests/SentryTests/Helper/EnvelopeComparison.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ extension XCTest {
let expectedElements = unzippedExpected.backwardCompatibleSplit(separator: newline)
let actualElements = unzippedActual.backwardCompatibleSplit(separator: newline)
let expectedData = try expectedElements.map { data -> EnvelopeData in
// swiftlint:disable:next no_try_optional_in_tests
if let json = try? JSONSerialization.jsonObject(with: data) as? NSDictionary {
return .dictionary(json)
}
let dataAsString = try XCTUnwrap(String(data: data, encoding: .utf8))
return .string(dataAsString)
}
let actualData = try actualElements.map { data -> EnvelopeData in
// swiftlint:disable:next no_try_optional_in_tests
if let json = try? JSONSerialization.jsonObject(with: data) as? NSDictionary {
return .dictionary(json)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ class SentryInfoPlistWrapperTests: XCTestCase {
sut = SentryInfoPlistWrapper(bundle: testBundle)
}

override func tearDown() {
TestBundle.cleanup(testBundle)
override func tearDownWithError() throws {
try TestBundle.cleanup(testBundle)
testBundle = nil
sut = nil
super.tearDown()
Expand Down
4 changes: 2 additions & 2 deletions Tests/SentryTests/Helper/InfoPlist/TestBundle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,14 @@ class TestBundle {

/// Cleans up a temporary test bundle
/// - Parameter bundle: The bundle to clean up
static func cleanup(_ bundle: Bundle?) {
static func cleanup(_ bundle: Bundle?) throws {
guard let bundle = bundle else {
return
}

// Only delete if it's in the temp directory (safety check)
if bundle.bundleURL.path.contains(FileManager.default.temporaryDirectory.path) {
try? FileManager.default.removeItem(at: bundle.bundleURL)
try FileManager.default.removeItem(at: bundle.bundleURL)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ class SentryHangTrackingIntegrationTests: SentrySDKIntegrationTestsBase {
extensionDetector: SentryExtensionDetector(infoPlistWrapper: fixture.infoPlistWrapper)
)
defer {
try? fixture.tearDownDI()
XCTAssertNoThrow(try fixture.tearDownDI())
}
crashWrapper.internalIsBeingTraced = false

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class SentryMetricsApiE2ETests: XCTestCase {
XCTAssertEqual(capturedMetrics.count.intValue, 1, "Should capture 1 metric")
XCTAssertFalse(capturedMetrics.data.isEmpty, "Captured metrics data should not be empty")

let metrics = getCapturedMetrics(from: client)
let metrics = try getCapturedMetrics(from: client)
XCTAssertEqual(metrics.count, 1, "Should have exactly 1 metric")
let metric = try XCTUnwrap(metrics.first)
XCTAssertEqual(metric["name"] as? String, "network.request.count", "Metric key should match")
Expand Down Expand Up @@ -78,7 +78,7 @@ class SentryMetricsApiE2ETests: XCTestCase {
let capturedMetrics = try XCTUnwrap(client.captureMetricsDataInvocations.first, "Metrics should be created for zero values")
XCTAssertEqual(capturedMetrics.count.intValue, 1, "Should capture 1 metric")

let metrics = getCapturedMetrics(from: client)
let metrics = try getCapturedMetrics(from: client)
XCTAssertEqual(metrics.count, 1, "Should have exactly 1 metric")
let metric = try XCTUnwrap(metrics.first)
XCTAssertEqual(metric["name"] as? String, "button.click", "Metric key should match")
Expand All @@ -99,7 +99,7 @@ class SentryMetricsApiE2ETests: XCTestCase {
let capturedMetrics = try XCTUnwrap(client.captureMetricsDataInvocations.first, "Metric should be created for large values")
XCTAssertEqual(capturedMetrics.count.intValue, 1, "Should capture 1 metric")

let metrics = getCapturedMetrics(from: client)
let metrics = try getCapturedMetrics(from: client)
XCTAssertEqual(metrics.count, 1, "Should have exactly 1 metric")
let metric = try XCTUnwrap(metrics.first)
XCTAssertEqual(metric["name"] as? String, "events.processed", "Metric key should match")
Expand Down Expand Up @@ -129,7 +129,7 @@ class SentryMetricsApiE2ETests: XCTestCase {
let capturedMetrics = try XCTUnwrap(client.captureMetricsDataInvocations.first, "Metric should be created with attributes")
XCTAssertEqual(capturedMetrics.count.intValue, 1, "Should capture 1 metric")

let metrics = getCapturedMetrics(from: client)
let metrics = try getCapturedMetrics(from: client)
XCTAssertEqual(metrics.count, 1, "Should have exactly 1 metric")
let metric = try XCTUnwrap(metrics.first)
XCTAssertEqual(metric["name"] as? String, "api.request.count", "Metric key should match")
Expand Down Expand Up @@ -167,7 +167,7 @@ class SentryMetricsApiE2ETests: XCTestCase {
XCTAssertEqual(capturedMetrics.count.intValue, 1, "Should capture 1 metric")
XCTAssertFalse(capturedMetrics.data.isEmpty, "Captured metrics data should not be empty")

let metrics = getCapturedMetrics(from: client)
let metrics = try getCapturedMetrics(from: client)
XCTAssertEqual(metrics.count, 1, "Should have exactly 1 metric")
let metric = try XCTUnwrap(metrics.first)
XCTAssertEqual(metric["name"] as? String, "http.request.duration", "Metric key should match")
Expand Down Expand Up @@ -219,7 +219,7 @@ class SentryMetricsApiE2ETests: XCTestCase {
let capturedMetrics = try XCTUnwrap(client.captureMetricsDataInvocations.first, "Metrics should be created for zero values")
XCTAssertEqual(capturedMetrics.count.intValue, 1, "Should capture 1 metric")

let metrics = getCapturedMetrics(from: client)
let metrics = try getCapturedMetrics(from: client)
XCTAssertEqual(metrics.count, 1, "Should have exactly 1 metric")
let metric = try XCTUnwrap(metrics.first)
XCTAssertEqual(metric["name"] as? String, "response.time", "Metric key should match")
Expand All @@ -240,7 +240,7 @@ class SentryMetricsApiE2ETests: XCTestCase {
let capturedMetrics = try XCTUnwrap(client.captureMetricsDataInvocations.first, "Metric should be created for large values")
XCTAssertEqual(capturedMetrics.count.intValue, 1, "Should capture 1 metric")

let metrics = getCapturedMetrics(from: client)
let metrics = try getCapturedMetrics(from: client)
XCTAssertEqual(metrics.count, 1, "Should have exactly 1 metric")
let metric = try XCTUnwrap(metrics.first)
XCTAssertEqual(metric["name"] as? String, "processing.duration", "Metric key should match")
Expand All @@ -261,7 +261,7 @@ class SentryMetricsApiE2ETests: XCTestCase {
let capturedMetrics = try XCTUnwrap(client.captureMetricsDataInvocations.first, "Metrics should be created for negative values")
XCTAssertEqual(capturedMetrics.count.intValue, 1, "Should capture 1 metric")

let metrics = getCapturedMetrics(from: client)
let metrics = try getCapturedMetrics(from: client)
XCTAssertEqual(metrics.count, 1, "Should have exactly 1 metric")
let metric = try XCTUnwrap(metrics.first)
XCTAssertEqual(metric["name"] as? String, "latency", "Metric key should match")
Expand Down Expand Up @@ -291,7 +291,7 @@ class SentryMetricsApiE2ETests: XCTestCase {
let capturedMetrics = try XCTUnwrap(client.captureMetricsDataInvocations.first, "Metric should be created with attributes")
XCTAssertEqual(capturedMetrics.count.intValue, 1, "Should capture 1 metric")

let metrics = getCapturedMetrics(from: client)
let metrics = try getCapturedMetrics(from: client)
XCTAssertEqual(metrics.count, 1, "Should have exactly 1 metric")
let metric = try XCTUnwrap(metrics.first)
XCTAssertEqual(metric["name"] as? String, "db.query.duration", "Metric key should match")
Expand Down Expand Up @@ -329,7 +329,7 @@ class SentryMetricsApiE2ETests: XCTestCase {
XCTAssertEqual(capturedMetrics.count.intValue, 1, "Should capture 1 metric")
XCTAssertFalse(capturedMetrics.data.isEmpty, "Captured metrics data should not be empty")

let metrics = getCapturedMetrics(from: client)
let metrics = try getCapturedMetrics(from: client)
XCTAssertEqual(metrics.count, 1, "Should have exactly 1 metric")
let metric = try XCTUnwrap(metrics.first)
XCTAssertEqual(metric["name"] as? String, "memory.usage", "Metric key should match")
Expand Down Expand Up @@ -381,7 +381,7 @@ class SentryMetricsApiE2ETests: XCTestCase {
let capturedMetrics = try XCTUnwrap(client.captureMetricsDataInvocations.first, "Metrics should be created for zero values")
XCTAssertEqual(capturedMetrics.count.intValue, 1, "Should capture 1 metric")

let metrics = getCapturedMetrics(from: client)
let metrics = try getCapturedMetrics(from: client)
XCTAssertEqual(metrics.count, 1, "Should have exactly 1 metric")
let metric = try XCTUnwrap(metrics.first)
XCTAssertEqual(metric["name"] as? String, "queue.depth", "Metric key should match")
Expand All @@ -402,7 +402,7 @@ class SentryMetricsApiE2ETests: XCTestCase {
let capturedMetrics = try XCTUnwrap(client.captureMetricsDataInvocations.first, "Metric should be created for large values")
XCTAssertEqual(capturedMetrics.count.intValue, 1, "Should capture 1 metric")

let metrics = getCapturedMetrics(from: client)
let metrics = try getCapturedMetrics(from: client)
XCTAssertEqual(metrics.count, 1, "Should have exactly 1 metric")
let metric = try XCTUnwrap(metrics.first)
XCTAssertEqual(metric["name"] as? String, "active.connections", "Metric key should match")
Expand All @@ -424,7 +424,7 @@ class SentryMetricsApiE2ETests: XCTestCase {
XCTAssertEqual(capturedMetrics.count.intValue, 1, "Should capture 1 metric")
XCTAssertFalse(capturedMetrics.data.isEmpty, "Captured metrics data should not be empty")

let metrics = getCapturedMetrics(from: client)
let metrics = try getCapturedMetrics(from: client)
XCTAssertEqual(metrics.count, 1, "Should have exactly 1 metric")
let metric = try XCTUnwrap(metrics.first)
XCTAssertEqual(metric["name"] as? String, "temperature", "Metric key should match")
Expand Down Expand Up @@ -457,7 +457,7 @@ class SentryMetricsApiE2ETests: XCTestCase {
let capturedMetrics = try XCTUnwrap(client.captureMetricsDataInvocations.first, "Metric should be created with attributes")
XCTAssertEqual(capturedMetrics.count.intValue, 1, "Should capture 1 metric")

let metrics = getCapturedMetrics(from: client)
let metrics = try getCapturedMetrics(from: client)
XCTAssertEqual(metrics.count, 1, "Should have exactly 1 metric")
let metric = try XCTUnwrap(metrics.first)
XCTAssertEqual(metric["name"] as? String, "system.cpu.usage", "Metric key should match")
Expand Down Expand Up @@ -541,18 +541,18 @@ class SentryMetricsApiE2ETests: XCTestCase {
// JSONSerialization provides a good middle ground: it parses the JSON structure without duplicating
// the encoding/decoding logic, and it's order-agnostic, making tests stable while still verifying
// the actual data structure produced by the buffer.
private func getCapturedMetrics(from client: TestClient) -> [[String: Any]] {
private func getCapturedMetrics(from client: TestClient) throws -> [[String: Any]] {
var allMetrics: [[String: Any]] = []

for invocation in client.captureMetricsDataInvocations.invocations {
if let jsonObject = try? JSONSerialization.jsonObject(with: invocation.data) as? [String: Any],
let items = jsonObject["items"] as? [[String: Any]] {
let jsonObject = try XCTUnwrap(JSONSerialization.jsonObject(with: invocation.data) as? [String: Any])
if let items = jsonObject["items"] as? [[String: Any]] {
for item in items {
allMetrics.append(item)
}
}
}

return allMetrics
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ final class DefaultSentryMetricsTelemetryBufferTests: XCTestCase {
// -- Assert --
XCTAssertEqual(testCallbackHelper.captureMetricsDataInvocations.count, 1)

let capturedMetrics = testCallbackHelper.getCapturedMetrics()
let capturedMetrics = try testCallbackHelper.getCapturedMetrics()
XCTAssertEqual(capturedMetrics.element(at: 0)?["name"] as? String, "metric.one")
XCTAssertEqual(capturedMetrics.element(at: 1)?["name"] as? String, "metric.two")

Expand Down Expand Up @@ -94,7 +94,7 @@ final class DefaultSentryMetricsTelemetryBufferTests: XCTestCase {
// -- Assert --
XCTAssertEqual(testCallbackHelper.captureMetricsDataInvocations.count, 1)

let capturedMetrics = testCallbackHelper.getCapturedMetrics()
let capturedMetrics = try testCallbackHelper.getCapturedMetrics()
XCTAssertEqual(capturedMetrics.element(at: 0)?["name"] as? String, "large.metric")

// Assert no further metrics
Expand All @@ -119,7 +119,7 @@ final class DefaultSentryMetricsTelemetryBufferTests: XCTestCase {
// -- Assert -- Should have flushed once when reaching maxMetricCount
XCTAssertEqual(testCallbackHelper.captureMetricsDataInvocations.count, 1)

let capturedMetrics = testCallbackHelper.getCapturedMetrics()
let capturedMetrics = try testCallbackHelper.getCapturedMetrics()
XCTAssertEqual(capturedMetrics.count, 10, "Should have captured exactly 10 metrics")
}

Expand All @@ -143,7 +143,7 @@ final class DefaultSentryMetricsTelemetryBufferTests: XCTestCase {

// Verify flush occurred
XCTAssertEqual(testCallbackHelper.captureMetricsDataInvocations.count, 1)
let capturedMetrics = testCallbackHelper.getCapturedMetrics()
let capturedMetrics = try testCallbackHelper.getCapturedMetrics()
XCTAssertEqual(capturedMetrics.count, 1)
}

Expand Down Expand Up @@ -215,7 +215,7 @@ final class DefaultSentryMetricsTelemetryBufferTests: XCTestCase {
// -- Assert --
XCTAssertEqual(testCallbackHelper.captureMetricsDataInvocations.count, 1, "Should flush when reaching default maxMetricCount of 100")

let capturedMetrics = testCallbackHelper.getCapturedMetrics()
let capturedMetrics = try testCallbackHelper.getCapturedMetrics()
XCTAssertEqual(capturedMetrics.count, 100, "Should have captured exactly 100 metrics")
}

Expand Down Expand Up @@ -257,7 +257,7 @@ final class DefaultSentryMetricsTelemetryBufferTests: XCTestCase {
// -- Assert --
XCTAssertEqual(testCallbackHelper.captureMetricsDataInvocations.count, 1, "Should flush when exceeding default maxBufferSizeBytes of 1MB")

let capturedMetrics = testCallbackHelper.getCapturedMetrics()
let capturedMetrics = try testCallbackHelper.getCapturedMetrics()
XCTAssertGreaterThan(capturedMetrics.count, 0, "Should have captured at least one metric")
XCTAssertLessThanOrEqual(capturedMetrics.count, 600, "Should not have captured more metrics than were added")
}
Expand All @@ -281,7 +281,7 @@ final class DefaultSentryMetricsTelemetryBufferTests: XCTestCase {
XCTAssertGreaterThanOrEqual(duration, 0, "captureMetrics should return a non-negative duration")
XCTAssertEqual(testCallbackHelper.captureMetricsDataInvocations.count, 1)

let capturedMetrics = testCallbackHelper.getCapturedMetrics()
let capturedMetrics = try testCallbackHelper.getCapturedMetrics()
XCTAssertEqual(capturedMetrics.count, 2)
}

Expand Down Expand Up @@ -321,7 +321,7 @@ final class DefaultSentryMetricsTelemetryBufferTests: XCTestCase {
// The actual duration depends on system performance, so we just verify it's non-negative
XCTAssertEqual(testCallbackHelper.captureMetricsDataInvocations.count, 1, "Should invoke callback once")

let capturedMetrics = testCallbackHelper.getCapturedMetrics()
let capturedMetrics = try testCallbackHelper.getCapturedMetrics()
XCTAssertEqual(capturedMetrics.count, 5, "Should capture all 5 metrics")
}

Expand Down Expand Up @@ -405,7 +405,7 @@ final class DefaultSentryMetricsTelemetryBufferTests: XCTestCase {
XCTAssertEqual(testCallbackHelper.captureMetricsDataInvocations.count, 2)

// Verify each flush contains only one metric
let capturedMetrics = testCallbackHelper.getCapturedMetrics()
let capturedMetrics = try testCallbackHelper.getCapturedMetrics()
XCTAssertEqual(capturedMetrics.element(at: 0)?["name"] as? String, "metric.1")
XCTAssertEqual(capturedMetrics.element(at: 1)?["name"] as? String, "metric.2")

Expand All @@ -429,7 +429,7 @@ final class DefaultSentryMetricsTelemetryBufferTests: XCTestCase {
sut.captureMetrics()

// -- Assert --
let capturedMetrics = testCallbackHelper.getCapturedMetrics()
let capturedMetrics = try testCallbackHelper.getCapturedMetrics()
let capturedMetric = try XCTUnwrap(capturedMetrics.first)
XCTAssertEqual(capturedMetric["type"] as? String, "counter")
XCTAssertEqual(capturedMetric["value"] as? Int64, 42)
Expand All @@ -453,7 +453,7 @@ final class DefaultSentryMetricsTelemetryBufferTests: XCTestCase {
sut.captureMetrics()

// -- Assert --
let capturedMetrics = testCallbackHelper.getCapturedMetrics()
let capturedMetrics = try testCallbackHelper.getCapturedMetrics()
let capturedMetric = try XCTUnwrap(capturedMetrics.first)
XCTAssertEqual(capturedMetric["type"] as? String, "distribution")
XCTAssertEqual(capturedMetric["value"] as? Double, 42.123456)
Expand All @@ -477,7 +477,7 @@ final class DefaultSentryMetricsTelemetryBufferTests: XCTestCase {
sut.captureMetrics()

// -- Assert --
let capturedMetrics = testCallbackHelper.getCapturedMetrics()
let capturedMetrics = try testCallbackHelper.getCapturedMetrics()
let capturedMetric = try XCTUnwrap(capturedMetrics.first)
XCTAssertEqual(capturedMetric["type"] as? String, "gauge")
XCTAssertEqual(capturedMetric["value"] as? Double, 42.0)
Expand Down Expand Up @@ -525,18 +525,18 @@ final class TestMetricsBufferCallbackHelper {
// JSONSerialization provides a good middle ground: it parses the JSON structure without duplicating
// the encoding/decoding logic, and it's order-agnostic, making tests stable while still verifying
// the actual data structure produced by the buffer.
func getCapturedMetrics() -> [[String: Any]] {
func getCapturedMetrics() throws -> [[String: Any]] {
var allMetrics: [[String: Any]] = []

for invocation in captureMetricsDataInvocations.invocations {
if let jsonObject = try? JSONSerialization.jsonObject(with: invocation.data) as? [String: Any],
let items = jsonObject["items"] as? [[String: Any]] {
let jsonObject = try XCTUnwrap(JSONSerialization.jsonObject(with: invocation.data) as? [String: Any])
if let items = jsonObject["items"] as? [[String: Any]] {
for item in items {
allMetrics.append(item)
}
}
}

return allMetrics
}
}
Loading
Loading