Skip to content

Commit 11c9904

Browse files
authored
Add UI tests for performance [SwiftUI] (#1246)
* Add UI tests * Fix styling * Add TODO
1 parent 9a4f6c6 commit 11c9904

File tree

5 files changed

+167
-110
lines changed

5 files changed

+167
-110
lines changed

performance/SwiftUIPerformanceQuickstart/PerformanceExample/PerformanceExample.xcodeproj/project.pbxproj

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
4102056426A631F5004B24B3 /* PerformanceExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4102055626A631F4004B24B3 /* PerformanceExampleApp.swift */; };
1111
4102056626A631F5004B24B3 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4102055726A631F4004B24B3 /* MainView.swift */; };
1212
4102056826A631F5004B24B3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4102055826A631F5004B24B3 /* Assets.xcassets */; };
13-
4102057926A63210004B24B3 /* Tests_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4102057826A63210004B24B3 /* Tests_iOS.swift */; };
14-
414C55A726B87EFB00114089 /* Tests_tvOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 414C55A626B87EFB00114089 /* Tests_tvOS.swift */; };
13+
419700ED26C30DA500F186C3 /* UITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 419700EC26C30DA500F186C3 /* UITests.swift */; };
14+
419700EE26C30DA500F186C3 /* UITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 419700EC26C30DA500F186C3 /* UITests.swift */; };
1515
419AADCE26B86A94005C4817 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 419AADCD26B86A94005C4817 /* GoogleService-Info.plist */; };
1616
419AADCF26B86A94005C4817 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 419AADCD26B86A94005C4817 /* GoogleService-Info.plist */; };
1717
41BFA1EA26B1D36C0013EB90 /* PerformanceExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4102055626A631F4004B24B3 /* PerformanceExampleApp.swift */; };
@@ -44,11 +44,10 @@
4444
4102055826A631F5004B24B3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
4545
4102055D26A631F5004B24B3 /* PerformanceExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PerformanceExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
4646
4102057626A63210004B24B3 /* Tests_iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests_iOS.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
47-
4102057826A63210004B24B3 /* Tests_iOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests_iOS.swift; sourceTree = "<group>"; };
4847
410FF76926B1CEB500CA084F /* PerformanceExample (tvOS).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "PerformanceExample (tvOS).app"; sourceTree = BUILT_PRODUCTS_DIR; };
4948
413CB73826B4AE8200E995E2 /* PerformanceExample--tvOS--Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "PerformanceExample--tvOS--Info.plist"; sourceTree = "<group>"; };
5049
414C55A426B87EFB00114089 /* Tests_tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests_tvOS.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
51-
414C55A626B87EFB00114089 /* Tests_tvOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests_tvOS.swift; sourceTree = "<group>"; };
50+
419700EC26C30DA500F186C3 /* UITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITests.swift; sourceTree = "<group>"; };
5251
419AADCD26B86A94005C4817 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../GoogleService-Info.plist"; sourceTree = "<group>"; };
5352
41BFA1EF26B1D8B80013EB90 /* Process.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Process.swift; sourceTree = "<group>"; };
5453
/* End PBXFileReference section */
@@ -91,8 +90,6 @@
9190
419AADCD26B86A94005C4817 /* GoogleService-Info.plist */,
9291
413CB73826B4AE8200E995E2 /* PerformanceExample--tvOS--Info.plist */,
9392
4102055526A631F4004B24B3 /* Shared */,
94-
4102057726A63210004B24B3 /* Tests_iOS */,
95-
414C55A526B87EFB00114089 /* Tests_tvOS */,
9693
4102055E26A631F5004B24B3 /* Products */,
9794
);
9895
sourceTree = "<group>";
@@ -103,6 +100,7 @@
103100
4102055626A631F4004B24B3 /* PerformanceExampleApp.swift */,
104101
4102055726A631F4004B24B3 /* MainView.swift */,
105102
41BFA1EF26B1D8B80013EB90 /* Process.swift */,
103+
419700EC26C30DA500F186C3 /* UITests.swift */,
106104
4102055826A631F5004B24B3 /* Assets.xcassets */,
107105
);
108106
path = Shared;
@@ -223,13 +221,15 @@
223221
};
224222
4102057526A63210004B24B3 = {
225223
CreatedOnToolsVersion = 13.0;
224+
LastSwiftMigration = 1300;
226225
TestTargetID = 4102055C26A631F5004B24B3;
227226
};
228227
410FF76826B1CEB500CA084F = {
229228
CreatedOnToolsVersion = 13.0;
230229
};
231230
414C55A326B87EFB00114089 = {
232231
CreatedOnToolsVersion = 13.0;
232+
LastSwiftMigration = 1300;
233233
TestTargetID = 410FF76826B1CEB500CA084F;
234234
};
235235
};
@@ -305,7 +305,7 @@
305305
isa = PBXSourcesBuildPhase;
306306
buildActionMask = 2147483647;
307307
files = (
308-
4102057926A63210004B24B3 /* Tests_iOS.swift in Sources */,
308+
419700ED26C30DA500F186C3 /* UITests.swift in Sources */,
309309
);
310310
runOnlyForDeploymentPostprocessing = 0;
311311
};
@@ -323,7 +323,7 @@
323323
isa = PBXSourcesBuildPhase;
324324
buildActionMask = 2147483647;
325325
files = (
326-
414C55A726B87EFB00114089 /* Tests_tvOS.swift in Sources */,
326+
419700EE26C30DA500F186C3 /* UITests.swift in Sources */,
327327
);
328328
runOnlyForDeploymentPostprocessing = 0;
329329
};
@@ -516,6 +516,7 @@
516516
4102057D26A63210004B24B3 /* Debug */ = {
517517
isa = XCBuildConfiguration;
518518
buildSettings = {
519+
CLANG_ENABLE_MODULES = YES;
519520
CODE_SIGN_STYLE = Automatic;
520521
CURRENT_PROJECT_VERSION = 1;
521522
GENERATE_INFOPLIST_FILE = YES;
@@ -530,6 +531,7 @@
530531
PRODUCT_NAME = "$(TARGET_NAME)";
531532
SDKROOT = iphoneos;
532533
SWIFT_EMIT_LOC_STRINGS = NO;
534+
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
533535
SWIFT_VERSION = 5.0;
534536
TARGETED_DEVICE_FAMILY = "1,2";
535537
TEST_TARGET_NAME = "PerformanceExample (iOS)";
@@ -539,6 +541,7 @@
539541
4102057E26A63210004B24B3 /* Release */ = {
540542
isa = XCBuildConfiguration;
541543
buildSettings = {
544+
CLANG_ENABLE_MODULES = YES;
542545
CODE_SIGN_STYLE = Automatic;
543546
CURRENT_PROJECT_VERSION = 1;
544547
GENERATE_INFOPLIST_FILE = YES;
@@ -629,6 +632,7 @@
629632
isa = XCBuildConfiguration;
630633
buildSettings = {
631634
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
635+
CLANG_ENABLE_MODULES = YES;
632636
CODE_SIGN_STYLE = Automatic;
633637
CURRENT_PROJECT_VERSION = 1;
634638
GENERATE_INFOPLIST_FILE = YES;
@@ -642,6 +646,7 @@
642646
PRODUCT_NAME = "$(TARGET_NAME)";
643647
SDKROOT = appletvos;
644648
SWIFT_EMIT_LOC_STRINGS = NO;
649+
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
645650
SWIFT_VERSION = 5.0;
646651
TARGETED_DEVICE_FAMILY = 3;
647652
TEST_TARGET_NAME = "PerformanceExample (tvOS)";
@@ -653,6 +658,7 @@
653658
isa = XCBuildConfiguration;
654659
buildSettings = {
655660
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
661+
CLANG_ENABLE_MODULES = YES;
656662
CODE_SIGN_STYLE = Automatic;
657663
CURRENT_PROJECT_VERSION = 1;
658664
GENERATE_INFOPLIST_FILE = YES;

performance/SwiftUIPerformanceQuickstart/PerformanceExample/Shared/Process.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class Process: ObservableObject {
2323
@Published var action: ProcessAction?
2424
@Published var image: UIImage?
2525
var categories: [(category: String, confidence: VNConfidence)]?
26-
let precision: Float = 0.4
26+
let precision: Float = 0.2
2727
let site = "https://firebase.google.com/downloads/brand-guidelines/PNG/logo-logomark.png"
2828

2929
#if swift(>=5.5)
@@ -217,5 +217,6 @@ enum ProcessStatus {
217217
enum ProcessAction: String, CaseIterable {
218218
case download = "Download"
219219
case classify = "Classify"
220-
case upload = "Upload"
220+
// TODO: implement upload functionality
221+
// case upload = "Upload"
221222
}
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
//
2+
// Copyright 2021 Google LLC
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
import XCTest
18+
19+
class UITests: XCTestCase {
20+
var app: XCUIApplication = XCUIApplication()
21+
22+
override func setUpWithError() throws {
23+
#if !os(iOS) && !os(tvOS)
24+
throw Error("Unsupported platform.")
25+
#endif
26+
27+
continueAfterFailure = false
28+
29+
app.launch()
30+
}
31+
32+
override func tearDownWithError() throws {
33+
app.terminate()
34+
}
35+
36+
func checkButtons(_ functions: [String], timeout: TimeInterval = 1) throws {
37+
for function in functions {
38+
let button = app.buttons["\(function) Image"]
39+
XCTAssert(button.waitForExistence(timeout: timeout), "Missing \(function) button.")
40+
XCTAssert(button.isEnabled, "\(function) button not enabled.")
41+
XCTAssert(button.isHittable, "\(function) button not in view.")
42+
}
43+
}
44+
45+
func checkText(_ text: String, timeout: TimeInterval = 1) throws {
46+
let element = app.staticTexts[text]
47+
XCTAssert(element.waitForExistence(timeout: timeout), "Missing text '\(text)'.")
48+
XCTAssert(element.isHittable, "Text '\(text)' not in view.")
49+
}
50+
51+
func checkStatus(_ status: String, timeout: TimeInterval = 1) throws {
52+
#if os(iOS)
53+
try checkText(status, timeout: timeout)
54+
#endif
55+
}
56+
57+
func goBack(timeout: TimeInterval = 1) throws {
58+
#if os(iOS)
59+
XCTAssert(app.buttons["Performance"].isHittable, "Reached invalid state.")
60+
app.buttons["Performance"].tap()
61+
#else
62+
XCUIRemote.shared.press(.menu)
63+
XCTAssert(app.navigationBars["Performance"].waitForExistence(timeout: timeout), "Timeout.")
64+
#endif
65+
}
66+
67+
func classify(image: Bool = false) throws {
68+
#if os(iOS)
69+
XCTAssert(app.buttons["Classify Image"].isHittable, "Reached invalid state.")
70+
app.buttons["Classify Image"].tap()
71+
#else
72+
if !image {
73+
XCUIRemote.shared.press(.down)
74+
sleep(1)
75+
XCTAssert(app.cells["Classify Image"].hasFocus, "Reached invalid state.")
76+
}
77+
XCUIRemote.shared.press(.select)
78+
#endif
79+
}
80+
81+
func download(timeout: TimeInterval = 10) throws {
82+
#if os(iOS)
83+
XCTAssert(app.buttons["Download Image"].isHittable, "Reached invalid state.")
84+
app.buttons["Download Image"].tap()
85+
#else
86+
XCUIRemote.shared.press(.up)
87+
sleep(1)
88+
XCTAssert(app.cells["Download Image"].hasFocus, "Reached invalid state.")
89+
XCUIRemote.shared.press(.select)
90+
#endif
91+
92+
XCTAssert(app.images.firstMatch.waitForExistence(timeout: timeout), "Failed to retrieve image.")
93+
}
94+
95+
func testAllViews() throws {
96+
let buttons = ["Download", "Classify"]
97+
98+
XCTAssert(app.navigationBars["Performance"].exists, "Missing navigation title.")
99+
XCTAssert(app.navigationBars["Performance"].isHittable, "Navigation title not in view.")
100+
101+
// Classify - Empty
102+
try checkStatus("⏸ Idle")
103+
try checkButtons(buttons)
104+
try classify()
105+
try checkText("No image found!\nPlease download an image first.")
106+
try checkStatus("⏸ Idle")
107+
try goBack()
108+
109+
// Download - Image
110+
try checkButtons(buttons)
111+
try checkStatus("⏸ Idle")
112+
try download()
113+
try checkStatus("✅ Success")
114+
try goBack()
115+
116+
// Classify - Image
117+
try checkStatus("✅ Success")
118+
try checkButtons(buttons)
119+
try classify()
120+
try checkButtons(["Classify"])
121+
try classify(image: true)
122+
try checkText("Categories found:", timeout: 5)
123+
try checkStatus("✅ Success")
124+
try goBack()
125+
126+
// Download - Done
127+
try checkStatus("✅ Success")
128+
try checkButtons(buttons)
129+
try download()
130+
try checkStatus("✅ Success")
131+
try goBack()
132+
133+
// Classify - Done
134+
try checkStatus("✅ Success")
135+
try checkButtons(buttons)
136+
try classify()
137+
try checkText("Categories found:")
138+
try checkStatus("✅ Success")
139+
try goBack()
140+
}
141+
142+
func testLaunchPerformance() throws {
143+
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
144+
// This measures how long it takes to launch your application.
145+
measure(metrics: [XCTApplicationLaunchMetric()]) {
146+
XCUIApplication().launch()
147+
}
148+
}
149+
}
150+
}

performance/SwiftUIPerformanceQuickstart/PerformanceExample/Tests_iOS/Tests_iOS.swift

Lines changed: 0 additions & 50 deletions
This file was deleted.

performance/SwiftUIPerformanceQuickstart/PerformanceExample/Tests_tvOS/Tests_tvOS.swift

Lines changed: 0 additions & 50 deletions
This file was deleted.

0 commit comments

Comments
 (0)