From 2c1c04eae50f39a0dbf001b6b177f3e7d98c326a Mon Sep 17 00:00:00 2001 From: Philip Niedertscheider Date: Mon, 12 Oct 2026 09:43:18 +0200 Subject: [PATCH] test(examples): Add app launch smoke test and PR workflow --- .github/workflows/example-ui-tests.yml | 52 ++++++++++++++++++++++++ Example/Example.yml | 16 ++++++++ Example/UITests/ExampleLaunchTests.swift | 26 ++++++++++++ Makefile | 16 ++++++++ 4 files changed, 110 insertions(+) create mode 100644 .github/workflows/example-ui-tests.yml create mode 100644 Example/UITests/ExampleLaunchTests.swift diff --git a/.github/workflows/example-ui-tests.yml b/.github/workflows/example-ui-tests.yml new file mode 100644 index 00000000..7407054b --- /dev/null +++ b/.github/workflows/example-ui-tests.yml @@ -0,0 +1,52 @@ +name: Example UI Tests + +on: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + smoke-test: + name: Example launch (iOS) + runs-on: macos-latest + timeout-minutes: 30 + steps: + - name: Checkout the repository + uses: actions/checkout@v7 + + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + + - name: Install build tools + run: brew install xcodegen xcbeautify + + - name: Prepare iOS Simulator + id: simulator + uses: kula-app/wait-for-services-action/ios-simulator@v1 + with: + platform: iOS + device: iPhone 17 Pro + boot: true + timeout: 300 + + - name: Run example smoke test + env: + IOS_SIMULATOR_OS: ${{ steps.simulator.outputs.runtime }} + IOS_DEVICE_NAME: iPhone 17 Pro + run: make test-example-ios + + - name: Upload test diagnostics on failure + if: failure() + uses: actions/upload-artifact@v7 + with: + name: Example UI Test Diagnostics + path: | + raw-test-example-ios.log + build/ExampleUITests/*.xcresult diff --git a/Example/Example.yml b/Example/Example.yml index a71f3b17..b15e099c 100644 --- a/Example/Example.yml +++ b/Example/Example.yml @@ -58,11 +58,27 @@ targets: ENABLE_USER_SELECTED_FILES: readonly ENABLE_PREVIEWS: YES ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon + ExampleUITests: + type: bundle.ui-testing + platform: iOS + sources: + - path: UITests + dependencies: + - target: Example + settings: + base: + SWIFT_VERSION: "5.0" + GENERATE_INFOPLIST_FILE: YES + TEST_TARGET_NAME: Example schemes: Example: build: targets: Example: all + test: + config: Debug + targets: + - ExampleUITests run: config: Debug profile: diff --git a/Example/UITests/ExampleLaunchTests.swift b/Example/UITests/ExampleLaunchTests.swift new file mode 100644 index 00000000..651d7f84 --- /dev/null +++ b/Example/UITests/ExampleLaunchTests.swift @@ -0,0 +1,26 @@ +// +// ExampleLaunchTests.swift +// TPPDF +// +// Created by Philip Niedertscheider on 12.10.2026. +// Copyright © 2016-2026 techprimate GmbH. All rights reserved. +// + +import XCTest + +final class ExampleLaunchTests: XCTestCase { + @MainActor + func testAppLaunchesWithoutErrors() { + continueAfterFailure = false + let app = XCUIApplication() + app.launch() + defer { app.terminate() } + + XCTAssertTrue(app.navigationBars["Examples"].waitForExistence(timeout: 10)) + XCTAssertEqual(app.state, .runningForeground) + XCTAssertFalse(app.alerts.firstMatch.exists) + XCTAssertFalse(app.staticTexts.matching( + NSPredicate(format: "label BEGINSWITH %@", "Generation failed:") + ).firstMatch.exists) + } +} diff --git a/Makefile b/Makefile index ea9c6f5e..ceadf6dc 100644 --- a/Makefile +++ b/Makefile @@ -214,6 +214,22 @@ build-example-ios: generate-example -derivedDataPath build/Example \ CODE_SIGNING_ALLOWED=NO build | xcbeautify --preserve-unbeautified +## Run the SwiftUI example launch smoke test on iOS Simulator +# +# Builds and launches the example app on the configured iOS Simulator. +# Writes logs to raw-test-example-ios.log and saves results in build/ExampleUITests. +.PHONY: test-example-ios +test-example-ios: generate-example + set -o pipefail && NSUnbufferedIO=YES xcrun xcodebuild \ + -project Example/Example.xcodeproj \ + -scheme Example \ + -destination 'platform=iOS Simulator,OS=$(IOS_SIMULATOR_OS),name=$(IOS_DEVICE_NAME)' \ + -derivedDataPath build/Example \ + -resultBundlePath build/ExampleUITests/$(shell date +%Y%m%d-%H%M%S).xcresult \ + -only-testing:ExampleUITests \ + -parallel-testing-enabled NO \ + CODE_SIGNING_ALLOWED=NO test | tee raw-test-example-ios.log | xcbeautify --preserve-unbeautified + ## Build the SwiftUI example for Mac Catalyst # # Builds the SwiftUI example app without requiring signing credentials.