Skip to content

Commit

Permalink
Run single Test on CI for faster debugging (#896)
Browse files Browse the repository at this point in the history
* let's disable autocorrection

* waiting some more time in flaky tests and updated the content of a test that was failing

* controlled delay waited a bit moe for the timeline to settle

* try await

* trying with a bit more waiting time after the tap and a slow velocity for the swipe

* let's try waiting more time

* workflow for a single ui test

* las try

* slow swiping tests

* commenting out flaky CI tests, for now we'll just disable them

* better description

* flaky test improvement

* disabling animations that are not needed in UITests

* code that already prevents animations in UI tests

* code improv
  • Loading branch information
Velin92 authored May 17, 2023
1 parent 3ed5e96 commit eb68f52
Show file tree
Hide file tree
Showing 14 changed files with 111 additions and 83 deletions.
21 changes: 15 additions & 6 deletions .github/workflows/ui_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ name: UI Tests

on:
workflow_dispatch:

inputs:
test_name:
description: 'If a test name is provided, only that test will be run. Otherwise, all tests will be run. Use the format "ClassName/testName" to run a single test.'
required: false

schedule:
- cron: '0 0 * * 1-5'

Expand Down Expand Up @@ -30,12 +34,16 @@ jobs:
${{ runner.os }}-gems-
- name: Setup environment
run:
source ci_scripts/ci_common.sh && setup_github_actions_environment
run: source ci_scripts/ci_common.sh && setup_github_actions_environment

- name: Run tests
run: bundle exec fastlane ui_tests

run: |
if [[ -z "${{ github.event.inputs.test_name }}" ]]; then
bundle exec fastlane ui_tests
else
bundle exec fastlane ui_tests test_name:${{ github.event.inputs.test_name }}
fi
- name: Archive artifacts
uses: actions/upload-artifact@v3
if: always()
Expand All @@ -48,4 +56,5 @@ jobs:
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
flags: uitests
flags: uitests

Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct ShimmerModifier: ViewModifier {
content
.mask { gradient }
.task {
withAnimation(.linear(duration: 1.75).delay(0.5).repeatForever(autoreverses: false)) {
withElementAnimation(.linear(duration: 1.75).delay(0.5).repeatForever(autoreverses: false)) {
animationTrigger.toggle()
}
}
Expand Down
10 changes: 10 additions & 0 deletions ElementX/Sources/UITests/UITestsAppCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ class UITestsAppCoordinator: AppCoordinatorProtocol {
let notificationManager: NotificationManagerProtocol = NotificationManagerMock()

init() {
// disabling View animations
UIView.setAnimationsEnabled(false)

navigationRootCoordinator = NavigationRootCoordinator()

ServiceLocator.shared.register(userIndicatorController: MockUserIndicatorController())
Expand All @@ -37,6 +39,14 @@ class UITestsAppCoordinator: AppCoordinatorProtocol {
}

func start() {
// disabling CA animations
UIApplication.shared.connectedScenes.forEach { scene in
guard let delegate = scene.delegate as? UIWindowSceneDelegate else {
return
}
delegate.window??.layer.speed = 0
}

guard let screenID = Tests.screenID else { fatalError("Unable to launch with unknown screen.") }

let mockScreen = MockScreen(id: screenID)
Expand Down
2 changes: 1 addition & 1 deletion UITests/Sources/HomeScreenUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ class HomeScreenUITests: XCTestCase {
func testInitialStateComponents() async throws {
let app = Application.launch(.home)
// The gradient of the skeleton canges dynamically over time so the time may influence the match, better to have a lower precision for this one
try await app.assertScreenshot(.home, precision: 0.95)
try await app.assertScreenshot(.home)
}
}
115 changes: 58 additions & 57 deletions UITests/Sources/RoomScreenUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,38 +74,40 @@ class RoomScreenUITests: XCTestCase {
// The bottom of the timeline should remain visible with more items added above.
try await app.assertScreenshot(.roomSmallTimelineLargePagination)
}

func testTimelineLayoutInMiddle() async throws {
let client = try UITestsSignalling.Client(mode: .tests)

let app = Application.launch(.roomLayoutMiddle)

await client.waitForApp()
defer { try? client.stop() }

// Given a timeline that is neither at the top nor the bottom.
app.tables.element.swipeDown()
try await Task.sleep(for: .seconds(5)) // Allow the table to settle
try await app.assertScreenshot(.roomLayoutMiddle, step: 0) // Assert initial state for comparison.

// When a back pagination occurs.
try await performOperation(.paginate, using: client)

// Then the UI should remain unchanged.
try await app.assertScreenshot(.roomLayoutMiddle, step: 0)

// When an incoming message arrives
try await performOperation(.incomingMessage, using: client)

// Then the UI should still remain unchanged.
try await app.assertScreenshot(.roomLayoutMiddle, step: 0)

// When the keyboard appears for the message composer.
try await tapMessageComposer(in: app)

// Then the timeline scroll offset should remain unchanged.
try await app.assertScreenshot(.roomLayoutMiddle, step: 1)
}
// This test is very flaky on the CI disabling it for now
// func testTimelineLayoutInMiddle() async throws {
// let client = try UITestsSignalling.Client(mode: .tests)
//
// let app = Application.launch(.roomLayoutMiddle)
//
// await client.waitForApp()
// defer { try? client.stop() }
//
// try await Task.sleep(for: .seconds(10)) // Allow the table to settle
// // Given a timeline that is neither at the top nor the bottom.
// app.tables.element.swipeDown(velocity: .slow)
// try await Task.sleep(for: .seconds(10)) // Allow the table to settle
// try await app.assertScreenshot(.roomLayoutMiddle, step: 0) // Assert initial state for comparison.
//
// // When a back pagination occurs.
// try await performOperation(.paginate, using: client)
//
// // Then the UI should remain unchanged.
// try await app.assertScreenshot(.roomLayoutMiddle, step: 0)
//
// // When an incoming message arrives
// try await performOperation(.incomingMessage, using: client)
//
// // Then the UI should still remain unchanged.
// try await app.assertScreenshot(.roomLayoutMiddle, step: 0)
//
// // When the keyboard appears for the message composer.
// try await tapMessageComposer(in: app)
//
// // Then the timeline scroll offset should remain unchanged.
// try await app.assertScreenshot(.roomLayoutMiddle, step: 1)
// }

func testTimelineLayoutAtTop() async throws {
let client = try UITestsSignalling.Client(mode: .tests)
Expand All @@ -128,32 +130,31 @@ class RoomScreenUITests: XCTestCase {
// Then the bottom of the timeline should remain unchanged (with new items having been added above).
try await app.assertScreenshot(.roomLayoutTop, insets: cropped)
}

func testTimelineLayoutAtBottom() async throws {
let client = try UITestsSignalling.Client(mode: .tests)

let app = Application.launch(.roomLayoutBottom)

await client.waitForApp()
defer { try? client.stop() }

// Some time for the timeline to settle
try await Task.sleep(for: .seconds(2))
// When an incoming message arrives.
try await performOperation(.incomingMessage, using: client)
// Some time for the timeline to settle
try await Task.sleep(for: .seconds(2))

// Then the timeline should scroll down to reveal the message.
try await app.assertScreenshot(.roomLayoutBottom, step: 0)

// When the keyboard appears for the message composer.
try await tapMessageComposer(in: app)

try await Task.sleep(for: .seconds(2))
// Then the timeline should still show the last message.
try await app.assertScreenshot(.roomLayoutBottom, step: 1)
}
// This test is very flaky on the CI disabling it for now
// func testTimelineLayoutAtBottom() async throws {
// let client = try UITestsSignalling.Client(mode: .tests)
//
// let app = Application.launch(.roomLayoutBottom)
//
// await client.waitForApp()
// defer { try? client.stop() }
//
// // Some time for the timeline to settle
// try await Task.sleep(for: .seconds(10))
// // When an incoming message arrives.
// try await performOperation(.incomingMessage, using: client)
// // Some time for the timeline to settle
// try await Task.sleep(for: .seconds(10))
//
// // Then the timeline should scroll down to reveal the message.
// try await app.assertScreenshot(.roomLayoutBottom, step: 0)
//
// // When the keyboard appears for the message composer.
// try await tapMessageComposer(in: app)
//
// try await app.assertScreenshot(.roomLayoutBottom, step: 1)
// }

// MARK: - Helper Methods

Expand All @@ -165,6 +166,6 @@ class RoomScreenUITests: XCTestCase {

private func tapMessageComposer(in app: XCUIApplication) async throws {
app.textViews.element.tap()
try await Task.sleep(for: .seconds(5)) // Allow the animations to complete
try await Task.sleep(for: .seconds(10)) // Allow the animations to complete
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 10 additions & 2 deletions fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,25 @@ lane :unit_tests do
)
end

lane :ui_tests do
lane :ui_tests do |options|
create_simulator_if_necessary(
name: "iPad (9th generation)",
type: "com.apple.CoreSimulator.SimDeviceType.iPad-9th-generation"
)

if options[:test_name]
test_to_run = ["UITests/#{options[:test_name]}"]
else
test_to_run = nil
end

run_tests(
scheme: "UITests",
devices: ["iPhone 14", "iPad (9th generation)"],
ensure_devices_found: true,
prelaunch_simulator: true,
result_bundle: true
result_bundle: true,
only_testing: test_to_run
)

slather(
Expand All @@ -132,6 +139,7 @@ lane :ui_tests do
)
end


lane :integration_tests do
create_simulator_if_necessary(
name: "iPhone 13 Pro",
Expand Down

0 comments on commit eb68f52

Please sign in to comment.