Skip to content

Commit 3af178e

Browse files
authored
[Testing]Implement Performance UITesting (#981)
1 parent ef14678 commit 3af178e

File tree

5 files changed

+182
-0
lines changed

5 files changed

+182
-0
lines changed

StreamVideo.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@
146146
40245F652BE27B2000FCF075 /* StatelessAudioOutputIconView_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40245F642BE27B2000FCF075 /* StatelessAudioOutputIconView_Tests.swift */; };
147147
40245F672BE27B8400FCF075 /* StatelessSpeakerIconView_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40245F662BE27B8400FCF075 /* StatelessSpeakerIconView_Tests.swift */; };
148148
40245F692BE27CCB00FCF075 /* StatelessParticipantsListButton_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40245F682BE27CCB00FCF075 /* StatelessParticipantsListButton_Tests.swift */; };
149+
4026BEEA2EA79FD400360AD0 /* CallFlow_PerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4026BEE92EA79FD400360AD0 /* CallFlow_PerformanceTests.swift */; };
149150
402778832BD13C62002F4399 /* NoiseCancellationFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 402778822BD13C62002F4399 /* NoiseCancellationFilter.swift */; };
150151
4028FE982DC4F638001F9DC3 /* ConsumableBucket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4028FE972DC4F638001F9DC3 /* ConsumableBucket.swift */; };
151152
4028FE9A2DC4FC8E001F9DC3 /* ConsumableBucketItemTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4028FE992DC4FC8E001F9DC3 /* ConsumableBucketItemTransformer.swift */; };
@@ -674,6 +675,7 @@
674675
40B575D42DCCECE800F489B8 /* MockAVPictureInPictureController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B575D22DCCECDA00F489B8 /* MockAVPictureInPictureController.swift */; };
675676
40B575D82DCCF00200F489B8 /* StreamPictureInPictureControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B575D52DCCEFB500F489B8 /* StreamPictureInPictureControllerProtocol.swift */; };
676677
40B713692A275F1400D1FE67 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8456E6C5287EB55F004E180E /* AppState.swift */; };
678+
40BAD0B32EA7CE3200CCD3D7 /* StreamWebRTC in Frameworks */ = {isa = PBXBuildFile; productRef = 40BAD0B22EA7CE3200CCD3D7 /* StreamWebRTC */; };
677679
40BBC4792C6227DC002AEF92 /* DemoNoiseCancellationButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40BBC4782C6227DC002AEF92 /* DemoNoiseCancellationButtonView.swift */; };
678680
40BBC47C2C6227F1002AEF92 /* View+PresentDemoMoreMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40BBC47B2C6227F1002AEF92 /* View+PresentDemoMoreMenu.swift */; };
679681
40BBC47E2C62287F002AEF92 /* DemoReconnectionButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40BBC47D2C62287F002AEF92 /* DemoReconnectionButtonView.swift */; };
@@ -1906,6 +1908,7 @@
19061908
40245F642BE27B2000FCF075 /* StatelessAudioOutputIconView_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatelessAudioOutputIconView_Tests.swift; sourceTree = "<group>"; };
19071909
40245F662BE27B8400FCF075 /* StatelessSpeakerIconView_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatelessSpeakerIconView_Tests.swift; sourceTree = "<group>"; };
19081910
40245F682BE27CCB00FCF075 /* StatelessParticipantsListButton_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatelessParticipantsListButton_Tests.swift; sourceTree = "<group>"; };
1911+
4026BEE92EA79FD400360AD0 /* CallFlow_PerformanceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallFlow_PerformanceTests.swift; sourceTree = "<group>"; };
19091912
402778822BD13C62002F4399 /* NoiseCancellationFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoiseCancellationFilter.swift; sourceTree = "<group>"; };
19101913
4028FE972DC4F638001F9DC3 /* ConsumableBucket.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsumableBucket.swift; sourceTree = "<group>"; };
19111914
4028FE992DC4FC8E001F9DC3 /* ConsumableBucketItemTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsumableBucketItemTransformer.swift; sourceTree = "<group>"; };
@@ -3206,6 +3209,7 @@
32063209
buildActionMask = 2147483647;
32073210
files = (
32083211
40C4DF522C1C60A80035DBC2 /* StreamVideo.framework in Frameworks */,
3212+
40BAD0B32EA7CE3200CCD3D7 /* StreamWebRTC in Frameworks */,
32093213
822FF7212AEAD100000202A7 /* StreamSwiftTestHelpers in Frameworks */,
32103214
);
32113215
runOnlyForDeploymentPostprocessing = 0;
@@ -6338,6 +6342,7 @@
63386342
824DBA9F29F6D77B005ACD09 /* ReconnectionTests.swift */,
63396343
82FB89362A702A9200AC16A1 /* Authentication_Tests.swift */,
63406344
40B499CB2AC1A90F00A53B60 /* DeeplinkTests.swift */,
6345+
4026BEE92EA79FD400360AD0 /* CallFlow_PerformanceTests.swift */,
63416346
);
63426347
path = Tests;
63436348
sourceTree = "<group>";
@@ -7696,6 +7701,7 @@
76967701
name = SwiftUIDemoAppUITests;
76977702
packageProductDependencies = (
76987703
822FF7202AEAD100000202A7 /* StreamSwiftTestHelpers */,
7704+
40BAD0B22EA7CE3200CCD3D7 /* StreamWebRTC */,
76997705
);
77007706
productName = SwiftUIDemoAppUITests;
77017707
productReference = 82392D512993C9E100941435 /* SwiftUIDemoAppUITests.xctest */;
@@ -8169,6 +8175,7 @@
81698175
files = (
81708176
82392D5F2993CCB300941435 /* ParticipantRobot.swift in Sources */,
81718177
82C837E429A5333700CB6B0E /* CallDetailsPage.swift in Sources */,
8178+
4026BEEA2EA79FD400360AD0 /* CallFlow_PerformanceTests.swift in Sources */,
81728179
82C837E229A532C000CB6B0E /* LoginPage.swift in Sources */,
81738180
82392D542993C9E100941435 /* StreamTestCase.swift in Sources */,
81748181
82C837E029A531ED00CB6B0E /* CallPage.swift in Sources */,
@@ -11427,6 +11434,11 @@
1142711434
package = 40AC73B22BE0062B00C57517 /* XCRemoteSwiftPackageReference "stream-video-noise-cancellation-swift" */;
1142811435
productName = StreamVideoNoiseCancellation;
1142911436
};
11437+
40BAD0B22EA7CE3200CCD3D7 /* StreamWebRTC */ = {
11438+
isa = XCSwiftPackageProductDependency;
11439+
package = 82EB8F552B0277730038B5A2 /* XCRemoteSwiftPackageReference "stream-video-swift-webrtc" */;
11440+
productName = StreamWebRTC;
11441+
};
1143011442
40C708D52D8D729500D3501F /* Gleap */ = {
1143111443
isa = XCSwiftPackageProductDependency;
1143211444
package = 4014F1012D8C2EBC004E7EFD /* XCRemoteSwiftPackageReference "Gleap-iOS-SDK" */;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>classNames</key>
6+
<dict>
7+
<key>CallFlow_PerformanceTests</key>
8+
<dict>
9+
<key>test_performance_with2Participants()</key>
10+
<dict>
11+
<key>com.apple.dt.XCTMetric_Memory-io.getstream.iOS.VideoDemoApp.physical_absolute</key>
12+
<dict>
13+
<key>baselineAverage</key>
14+
<real>125000.000000</real>
15+
<key>baselineIntegrationDisplayName</key>
16+
<string>Local Baseline</string>
17+
</dict>
18+
</dict>
19+
</dict>
20+
</dict>
21+
</dict>
22+
</plist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>classNames</key>
6+
<dict>
7+
<key>CallFlow_PerformanceTests</key>
8+
<dict>
9+
<key>test_performance_with2Participants()</key>
10+
<dict>
11+
<key>com.apple.dt.XCTMetric_Memory-io.getstream.iOS.VideoDemoApp.physical</key>
12+
<dict>
13+
<key>baselineAverage</key>
14+
<real>414000.000000</real>
15+
<key>baselineIntegrationDisplayName</key>
16+
<string>Local Baseline</string>
17+
</dict>
18+
<key>com.apple.dt.XCTMetric_Memory-io.getstream.iOS.VideoDemoApp.physical_absolute</key>
19+
<dict>
20+
<key>baselineAverage</key>
21+
<real>414000.000000</real>
22+
<key>baselineIntegrationDisplayName</key>
23+
<string>Local Baseline</string>
24+
</dict>
25+
<key>com.apple.dt.XCTMetric_Memory-io.getstream.iOS.VideoDemoApp.physical_peak</key>
26+
<dict>
27+
<key>baselineAverage</key>
28+
<real>802000.000000</real>
29+
<key>baselineIntegrationDisplayName</key>
30+
<string>Local Baseline</string>
31+
</dict>
32+
</dict>
33+
</dict>
34+
</dict>
35+
</dict>
36+
</plist>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>runDestinationsByUUID</key>
6+
<dict>
7+
<key>72BCA2C7-BCAB-4F29-B5A2-C1B720A9D6C7</key>
8+
<dict>
9+
<key>targetArchitecture</key>
10+
<string>arm64</string>
11+
<key>targetDevice</key>
12+
<dict>
13+
<key>modelCode</key>
14+
<string>iPhone13,1</string>
15+
<key>platformIdentifier</key>
16+
<string>com.apple.platform.iphoneos</string>
17+
</dict>
18+
</dict>
19+
<key>A871F8A3-784B-4A04-8235-A22FE4A40D80</key>
20+
<dict>
21+
<key>localComputer</key>
22+
<dict>
23+
<key>busSpeedInMHz</key>
24+
<integer>0</integer>
25+
<key>cpuCount</key>
26+
<integer>1</integer>
27+
<key>cpuKind</key>
28+
<string>Apple M1 Pro</string>
29+
<key>cpuSpeedInMHz</key>
30+
<integer>0</integer>
31+
<key>logicalCPUCoresPerPackage</key>
32+
<integer>10</integer>
33+
<key>modelCode</key>
34+
<string>MacBookPro18,1</string>
35+
<key>physicalCPUCoresPerPackage</key>
36+
<integer>10</integer>
37+
<key>platformIdentifier</key>
38+
<string>com.apple.platform.macosx</string>
39+
</dict>
40+
<key>targetArchitecture</key>
41+
<string>arm64</string>
42+
<key>targetDevice</key>
43+
<dict>
44+
<key>modelCode</key>
45+
<string>iPhone18,1</string>
46+
<key>platformIdentifier</key>
47+
<string>com.apple.platform.iphonesimulator</string>
48+
</dict>
49+
</dict>
50+
</dict>
51+
</dict>
52+
</plist>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//
2+
// Copyright © 2025 Stream.io Inc. All rights reserved.
3+
//
4+
5+
import Foundation
6+
import XCTest
7+
8+
final class CallFlow_PerformanceTests: StreamTestCase {
9+
10+
private let callDuration: TimeInterval = 1 * 60
11+
private let app = XCUIApplication()
12+
13+
override func setUpWithError() throws {
14+
launchApp = false
15+
try super.setUpWithError()
16+
}
17+
18+
@MainActor
19+
func test_performance_with4Participants() throws {
20+
try XCTSkipIf(TestRunnerEnvironment.isCI, "https://linear.app/stream/issue/IOS-1220/automate-call-performance-testing")
21+
// Reduce noise: fewer iterations for deterministic flows
22+
let options = XCTMeasureOptions()
23+
options.iterationCount = 3
24+
options.invocationOptions = [.manuallyStart, .manuallyStop]
25+
26+
measure(
27+
metrics: [
28+
XCTMemoryMetric(application: app)
29+
],
30+
options: options
31+
) {
32+
app.launch()
33+
app.activate()
34+
35+
startMeasuring()
36+
WHEN("user starts a new call") {
37+
userRobot
38+
.waitForAutoLogin()
39+
.startCall(callId, waitForCompletion: false)
40+
}
41+
42+
// ensure AUT is foreground
43+
app.activate()
44+
idle(for: callDuration)
45+
46+
stopMeasuring()
47+
app.terminate()
48+
}
49+
}
50+
}
51+
52+
extension XCTestCase {
53+
/// Non-blocking idle that won't freeze the app under test.
54+
func idle(for seconds: TimeInterval, file: StaticString = #file, line: UInt = #line) {
55+
let exp = expectation(description: "Idle \(seconds)s")
56+
// Intentionally never fulfill. We expect a timeout.
57+
let result = XCTWaiter.wait(for: [exp], timeout: seconds)
58+
XCTAssertEqual(result, .timedOut, "Idle wait was interrupted", file: file, line: line)
59+
}
60+
}

0 commit comments

Comments
 (0)