Skip to content

Commit c6f563e

Browse files
committed
workflows: add unit tests and ci format
1 parent e85f9fa commit c6f563e

3 files changed

Lines changed: 123 additions & 9 deletions

File tree

‎.github/scripts/junit-summary.py‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import glob
2+
import sys
3+
import xml.etree.ElementTree as ET
4+
5+
paths: list[str] = []
6+
for arg in sys.argv[1:]:
7+
paths.extend(glob.glob(arg))
8+
9+
tests = failures = errors = skipped = 0
10+
failed: list[str] = []
11+
12+
for path in paths:
13+
try:
14+
root = ET.parse(path).getroot()
15+
except (ET.ParseError, FileNotFoundError, OSError):
16+
continue
17+
for ts in root.iter("testsuite"):
18+
tests += int(ts.get("tests") or 0)
19+
failures += int(ts.get("failures") or 0)
20+
errors += int(ts.get("errors") or 0)
21+
skipped += int(ts.get("skipped") or 0)
22+
for tc in ts.iter("testcase"):
23+
if tc.find("failure") is not None or tc.find("error") is not None:
24+
name = f"{tc.get('classname', '')}.{tc.get('name', '')}".strip(".")
25+
failed.append(name)
26+
27+
if not paths or tests == 0:
28+
print("## ⚠️ No test results found")
29+
sys.exit(0)
30+
31+
bad = failures + errors
32+
passed = tests - bad - skipped
33+
status = "✅ All tests passed" if bad == 0 else f"❌ {bad} test(s) failed"
34+
35+
print(f"## {status}")
36+
print()
37+
print("| Total | Passed | Failed | Skipped |")
38+
print("|------:|-------:|-------:|--------:|")
39+
print(f"| {tests} | {passed} | {bad} | {skipped} |")
40+
41+
if failed:
42+
print()
43+
print("### Failed tests")
44+
for name in failed:
45+
print(f"- `{name}`")

‎.github/workflows/ci.yml‎

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,31 @@ jobs:
3030
xcodebuild -version
3131
xcrun simctl list runtimes | grep iOS || true
3232
33+
- name: Ensure xcbeautify
34+
run: command -v xcbeautify >/dev/null || brew install xcbeautify
35+
3336
- name: Run unit tests
3437
run: |
3538
set -o pipefail
36-
# Prettify output if xcbeautify is available (it is on GitHub macOS images),
37-
# otherwise fall back to raw xcodebuild output so the run never fails on tooling.
38-
FORMATTER="cat"
39-
if command -v xcbeautify >/dev/null 2>&1; then
40-
FORMATTER="xcbeautify --renderer github-actions"
41-
fi
4239
xcodebuild test \
4340
-project Normal.xcodeproj \
4441
-scheme "$SCHEME" \
4542
-destination "platform=iOS Simulator,name=$SIMULATOR" \
4643
-only-testing:NormalTests \
4744
-resultBundlePath TestResults.xcresult \
4845
CODE_SIGNING_ALLOWED=NO \
49-
| $FORMATTER
46+
| xcbeautify --renderer github-actions --report junit
47+
48+
- name: Summarize results
49+
if: ${{ !cancelled() }}
50+
run: python3 .github/scripts/junit-summary.py build/reports/junit.xml >> "$GITHUB_STEP_SUMMARY"
5051

5152
- name: Upload result bundle
5253
if: ${{ !cancelled() }}
5354
uses: actions/upload-artifact@v4
5455
with:
55-
name: test-results
56-
path: TestResults.xcresult
56+
name: unit-test-results
57+
path: |
58+
TestResults.xcresult
59+
build/reports/junit.xml
5760
if-no-files-found: ignore

‎.github/workflows/ui-tests.yml‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: UI Tests
2+
3+
# Manual / ad-hoc only — never runs on push or PR. Trigger from the Actions tab
4+
# ("Run workflow") or with: gh workflow run ui-tests.yml [-f only=...]
5+
on:
6+
workflow_dispatch:
7+
inputs:
8+
only:
9+
description: "Test identifier to run (e.g. NormalUITests or NormalUITests/ReconcileLifecycleUITests)"
10+
required: false
11+
default: "NormalUITests"
12+
13+
concurrency:
14+
group: ui-tests-${{ github.ref }}
15+
cancel-in-progress: true
16+
17+
jobs:
18+
ui-tests:
19+
name: UI tests
20+
runs-on: macos-15
21+
timeout-minutes: 30
22+
env:
23+
SCHEME: Normal
24+
SIMULATOR: iPhone 16 Pro
25+
ONLY: ${{ inputs.only }}
26+
steps:
27+
- uses: actions/checkout@v4
28+
29+
- name: Select latest stable Xcode
30+
uses: maxim-lobanov/setup-xcode@v1
31+
with:
32+
xcode-version: latest-stable
33+
34+
- name: Ensure xcbeautify
35+
run: command -v xcbeautify >/dev/null || brew install xcbeautify
36+
37+
- name: Boot simulator
38+
run: xcrun simctl bootstatus "$SIMULATOR" -b || true
39+
40+
- name: Run UI tests
41+
run: |
42+
set -o pipefail
43+
xcodebuild test \
44+
-project Normal.xcodeproj \
45+
-scheme "$SCHEME" \
46+
-destination "platform=iOS Simulator,name=$SIMULATOR" \
47+
-only-testing:"$ONLY" \
48+
-resultBundlePath UITestResults.xcresult \
49+
-retry-tests-on-failure \
50+
-test-iterations 3 \
51+
CODE_SIGNING_ALLOWED=NO \
52+
| xcbeautify --renderer github-actions --report junit
53+
54+
- name: Summarize results
55+
if: ${{ !cancelled() }}
56+
run: python3 .github/scripts/junit-summary.py build/reports/junit.xml >> "$GITHUB_STEP_SUMMARY"
57+
58+
- name: Upload result bundle
59+
if: ${{ !cancelled() }}
60+
uses: actions/upload-artifact@v4
61+
with:
62+
name: ui-test-results
63+
path: |
64+
UITestResults.xcresult
65+
build/reports/junit.xml
66+
if-no-files-found: ignore

0 commit comments

Comments
 (0)