Nguyên lý thực thi XCTest của tidevice: Giải pháp kiểm thử iOS không cần Xcode

Trong quy trình phát triển iOS truyền thống, việc thực thi các bài kiểm thử tự động (XCTest) thường phụ thuộc hoàn toàn vào môi trường Xcode và công cụ dòng lệnh xcodebuild. Điều này tạo ra rào cản lớn đối với các hệ thống tích hợp liên tục (CI) chạy trên nền tảng Linux hoặc các máy trạm không cài đặt IDE đầy đủ. Công cụ tidevice đã giải quyết vấn đề này bằng cách thiết lập một kênh giao tiếp trực tiếp với thiết bị iPhone, cho phép khởi chạy và điều khiển XCTest mà không cần sự can thiệp của Xcode.

Cơ chế hoạt động cốt lõi

Để hiểu rõ cách tidevice vận hành, chúng ta cần phân tích hai thành phần kỹ thuật quan trọng: XCTestConfigurationXCTestManager.

1. Tạo lập XCTestConfiguration

Trước khi bài kiểm thử được chạy, một đối tượng cấu hình cần được gửi xuống thiết bị. Trong Xcode, việc này được thực hiện tự động, nhưng tidevice phải tự xây dựng gói cấu hình này. Cụ thể, tidevice sẽ đóng gói các thông số như Bundle ID của ứng dụng cần test, các bộ test cụ thể cần chạy, và các tham số môi trường vào một đối tượng XCTestConfiguration được serialization dưới dạng binary plist (bplist).

Dưới đây là ví dụ về cách logic tạo cấu hình có thể được triển khai:

def build_test_config(app_bundle_id, target_app_id, session_id):
    """
    Tạo đối tượng cấu hình XCTest để gửi tới thiết bị.
    """
    config_data = {
        'testBundleURL': app_bundle_id,
        'targetApplicationBundleID': target_app_id,
        'sessionIdentifier': session_id,
        'reportResults': True
    }
    # Chuyển đổi dictionary thành đối tượng bplist
    return BPlDictSerializer.serialize(config_data)

2. Giao tiếp với XCTestManager

Sau khi có cấu hình, tidevice cần một cơ chế để nói chuyện với daemon kiểm thử đang chạy trên iOS. Nó sử dụng giao thức DTX (Debugging Transmission Exchange) để thiết lập proxy kết nối tới interface của XCTestManager.

Điểm mấu chốt trong kết nối này là việc sử dụng đường truyền DTX proxy với định danh cụ thể, cho phép tidevice giả lập vai trò của Xcode:

class DeviceConnection:
    def setup_test_channel(self):
        # Thiết lập kênh giao tiếp với daemon XCTest trên thiết bị
        channel_name = "dtxproxy:XCTestManager_IDEInterface:XCTestManager_DaemonConnectionInterface"
        return self._dtx_channel.connect(channel_name)

Quy trình thực thi kiểm thử

Luồng hoạt động của tidevice khi chạy XCTest diễn ra theo 5 bước chính:

  1. Xác lập kết nối: Kiểm tra kết nối USB với thiết bị iOS và xác minh tính sẵn sàng của ứng dụng Runner (ví dụ: WebDriverAgentRunner).
  2. Dữ liệu cấu hình: Xử lý các tham số dòng lệnh để sinh ra payload XCTestConfiguration.
  3. Khởi tạo phiên: Gửi tín hiệu khởi động process runner trên thiết bị thông qua giao thức lockdown/service.
  4. Điều khiển thực thi: Gửi gói tin cấu hình qua kênh DTX đã thiết lập để kích hoạt các method test.
  5. Theo dõi kết quả: Lắng nghe luồng log (syslog) từ thiết bị, phân tích và hiển thị trạng thái Pass/Fail ra màn hình người dùng.

Ví dụ thực tế

Giả sử chúng ta có ứng dụng cần kiểm thử là com.example.app và gói Runner là com.example.app UITests. Thay vì sử dụng xcodebuild, ta có thể sử dụng tidevice như sau:

tidevice xcuitest --bundle-id com.example.UITests.runner --target-bundle-id com.example.app

Khi lệnh được thực thi, hệ thống sẽ trả về luồng log chi tiết theo thời gian thực:

[Info] Connection established with device.
[Log] Test Suite 'UITests.xctest' started at 2023-10-01 10:00:00.
[Log] Test Case '-[UITests testLoginFunction]' started.
[Log]     t = 0.00s     Launch com.example.app
[Log]     t = 0.15s     Wait for application to idle
[Log] Test Case '-[UITests testLoginFunction]' passed (1.200 seconds).

Nhờ cơ chế này, các kỹ sư kiểm thử có thể dễ dàng tích hợp bài test UI vào các pipeline tự động hóa mà không bị ràng buộc bởi hạ tầng phức tạp của Apple.

Thẻ: iOS tidevice XCTest Automation Testing python

Đăng vào ngày 7 tháng 8 lúc 01:19