QT4i Documentation

Tài liệu tương tự
GIẢI PHÁP NHÀ THÔNG MINH LUMI LIFE HƯỚNG DẪN SỬ DỤNG VOICE CONTROL

Lập trình và ngôn ngữ lập trình

Microsoft Word - HDSD digiTool.doc

Bài 3 Tựa bài

HEADING 1: PHẦN 1: QUẢN LÝ VÀ DUY TRÌ HỆ ĐIỀU HÀNH

Kế thừa

Microsoft Word - status_code_trong_servlet.docx

XJ-UT311WN_XJ-UT351WN

Microsoft Word - server_response_trong_servlet.docx

Giới thiệu

Bài 1:

mySQL - Part 1 - Installation

NGÔN NGƯ LÂ P TRIǸH Biên tập bởi: nguyenvanlinh

Microsoft Word - jsp_syntax.docx

Microsoft Word - su_dung_sqlite_voi_php.docx

Hướng dẫn KHG sử dụng dịch vụ BaaS do Mobifone Global cung cấp Tổng Công ty Viễn thông MOBIFONE là nhà cung cấp dịch vụ Viễn thông và CNTT hàng đầu tạ

Hướng Dẫn Sử Dụng Doanh Nghiệp với Giao AdminLTE Bao gồm: - Trỏ record - Quản trị với giao diện AdminLTE - Cấu hình trên Outlook 2013 ( PO

Exchange Server - Recipient Configuration - Create Mailbox Exchange Server - Recipient Configuration - Create Mailbox Bởi: Phạm Nguyễn Bảo Nguyên Chún

MCSA 2012: Distributed File System (DFS) MCSA 2012: Distributed File System (DFS) Cuongquach.com Ở bài học hôm nay, mình xin trình bày về Distributed

9-KiemThu

Microsoft Word - session_tracking_trong_servlet.docx

Những cơ sở của ngôn ngữ C# Những cơ sở của ngôn ngữ C# Bởi: phamvanviet truonglapvy Trong chương này sẽ trình bày về hệ thống kiểu trong C#; phân biệ

Microsoft Word - client_request_trong_servlet.docx

Microsoft Word - form_trong_html.docx

«3 O ôâ â 13 è LJJ ÂÜ Ñ3 Ñ: Ë 3 Ý I ~ Ô ÑÑ3 1É ê~ [ ð ð è üû

OpenStax-CNX module: m Giới thiệu về ngôn ngữ C và môi trường turbo C 3.0 ThS. Nguyễn Văn Linh This work is produced by OpenStax-CNX and licens

Bài 7. Con trỏ Mục tiêu: 1. Luyện tập sử dụng con trỏ và địa chỉ của các biến 2. Sử dụng con trỏ khi thao tác với mảng. Giới hạn: không dùng các thư v

Lập trình cấu trúc trong Visual Basic Lập trình cấu trúc trong Visual Basic Bởi: Nguyễn Sơn Học xong chương này, sinh viên phải nắm bắt được các vấn đ

Microsoft Word - tao_ung_dung_hello_world_trong_android.docx

Thiết kế website động với mã nguồn Drupal 7 - Phần 1

HƯỚNG DẪN SỬ DỤNG CÁC SẢN PHẨM CỦA OFFICE 365 Hợp đồng số: 25/KTQD-FPT Cung cấp hệ thống Office trực tuyến và thư điện tử Trường Đại Học Kinh Tế Quốc

Lớp và đối tượng-các hàm và các lớp friend Lớp và đối tượng-các hàm và các lớp friend Bởi: Thanh Hiền Vũ CÁC HÀM VÀ CÁC LỚP friend Một hàm friend của

Internet Information Service - IIS Internet Information Service - IIS Bởi: Phạm Nguyễn Bảo Nguyên Chúng ta đã tìm hiểu về cách dựng một NAT Server...

IPSec IPSec Bởi: Phạm Nguyễn Bảo Nguyên Chúng ta đã biết khi ta sao chép dữ liệu giữa 2 máy hoặc thông qua mạng VPN để nâng cao chế độ bảo mật người q

BÀI TẬP THỰC HÀNH

Phụ lục 2: HỒ SƠ NĂNG LỰC NĂM 2014

Microsoft Word - mot_so_tool_trong_android.docx

CÀI ĐẶ T ANDROID TRÊN NETBEAN Yêu cầ u:trong quá trình cài đặ t phả i kế t nố i mạ ng,và phiên bả n này đượ c cài trên windows. 1.Download Netbean(6.7

Nhúng mã-cách khai báo biến Nhúng mã-cách khai báo biến Bởi: Khoa CNTT ĐHSP KT Hưng Yên Nhúng mã javascript trong trang HTML Bạn có thể nhúng JavaScri

Slide 1

Tìm hiểu ngôn ngữ lập trình Visual Basic Tìm hiểu ngôn ngữ lập trình Visual Basic Bởi: Khuyet Danh Tìm hiểu ngôn ngữ lập trình Visual Basic Tổng quan

Phụ lục 2: HỒ SƠ NĂNG LỰC NĂM 2014

Copyright vietjack.com Chuỗi (String) trong C# Trong C#, bạn có thể sử dụng các chuỗi (string) như là mảng các ký

Hướng dẫn sử dụng

ĐỀ CƯƠNG MÔN HỌC NHẬP MÔN TIN HỌC

Microsoft Word - xu_ly_cookie_trong_servlet.docx

27_7193.pdf

Thực hành trên Rose Thực hành trên Rose Bởi: Đoàn Văn Ban Xây dựng biểu đồ thành phần + Tạo lập mới hoặc mở một biểu đồ thành phần đã được tạo lập trư

Backup Cloud Server

Microsoft Word - Huong dan cau hinh mikrotik - Viet Tuan UNIFI.vn

BỘ GIÁO DỤC VÀ ĐÀO TẠO TRƯỜNG ĐẠI HỌC MỞ THÀNH PHỐ HỒ CHÍ MINH ĐỀ CƯƠNG MÔN HỌC 1. THÔNG TIN VỀ MÔN HỌC 1.1. Tên môn học: QUẢN TRỊ HỆ CƠ SỞ DỮ LIỆU 1.

Microsoft Word - danh-sach-lien-ket-doi-trong-c.docx

Slide 1

Chöông 1 (tt.)

ISA Server - Installation ISA Server - Installation Bởi: Phạm Nguyễn Bảo Nguyên Chúng ta không thể phủ nhận rằng trong khoảng vài năm trở lại đây Inte

Microsoft Word - jsp_client_request.docx

Animation, Modules 6 - Hoạt hình, tách file

WICELL User Guide Smart Cloud Wicell Controller Standard Version Manual version

Microsoft Word - Huong dan su dung Mailchimp.docx

Microsoft Word - thuat-ngu-thuong-mai-dien-tu.docx

Microsoft Word - action_trong_jsp.docx

Microsoft PowerPoint - L2-Gioi_thieu_WEKA.ppt [Compatibility Mode]

Yeastar S50 VoIP PBX Installation Guide Version 1.0 Jun. 2016

Modbus RTU - Modbus TCP/IP Converter

Cách viết một ứng dụng trên microsoft windows Cách viết một ứng dụng trên microsoft windows Bởi: Khuyet Danh CÁCH VIẾT MỘT ỨNG DỤNG TRÊN MICROSOFT WIN

Mục lục 1. Chuẩn bị Hướng dẫn cài đặt Casini Web Pro Hướng dẫn cài đặt SQLEEXPRESS Hướng dẫn cài đặt Teamviewer Hướng

PowerPoint Template

BÀI THỰC HÀNH 1: THỰC HÀNH KÍCH HOẠT IPV6 TRÊN HĐH WINDOW, LINUX

TẬP ĐOÀN VIỄN THÔNG QUÂN ĐỘI DỊCH VỤ CHỨNG THỰC CHỮ KÝ SỐ VIETTEL-CA SỔ TAY HƯỚNG DẪN SỬ DỤNG CHỨNG THƯ SỐ VIETTEL-CA MỤC LỤC 1. GIỚI THIỆU VỀ DỊCH VỤ

_Putty

MD Paper-Based Test ELA Vietnamese Script for Administrating PARCC TAM

BÀI LAB SWITCH Người Thực hiện : Đào Thanh Quý # Cấu hình VTP SW1#vlan database SW1(vlan)#vtp domain _TQuy SW1(vlan)#vtp server Device mode al

HƯỚNG DẪN SỬ DỤNG 1) Các thông số cài đặt client (MS Outlook, Outlook Express, Thunder Bird ) 2) Hướng dẫn đổi password 3) Hướng dẫn

Microsoft Word - jsp_file_uploading.docx

ப அற கண ப ற Prepare Q&A 1. எ தர ஈ அ ல தர ப சய ற? a. > b. << c. < d. >> 2. Star Office Calc இல கண ப வ ப க ப வ எ த ற ட த ட க வ? a. & b. = c. # d. $ 3. ப

Slide 1

نظام حماية الخزنة

Microsoft Word - edittext_trong_android.docx

HƯỚNG DẪN SỬ DỤNG CLOUD STORAGE Trân trọng cám ơn các bạn đã sử dụng dịch vụ Cloud Storage của Viettel IDC. Tài liệu hướng dẫn sử dụng nhanh được biên

Chương trình dịch

FAQ: Hướng dẫn cấu hình Wireless Router N300 DIR-612 Release date: 17/12/2018 Model support: DIR-612 H/W: Bx F/W: N/A FAQ: Hướng dẫn cấu hình Wireless

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG TIN HỌC ĐẠI CƯƠNG Bài 5. Kiểu dữ liệu và biểu thức trong C Nội dung 1. Các ki

Operating Instructions

Microsoft Word - LedCenterM_HDSD.doc

Microsoft Word - HDSD_NVR_304&3016.docx

Stored Procedures Stored Procedures Bởi: Khoa CNTT ĐHSP KT Hưng Yên Trong những bài học trước đây khi dùng Query Analyzer chúng ta có thể đặt tên và s

Khoa Quản lý Đất đai và Bất động sản KS. Đinh Quang Vinh ( )

Chương 1:

Microsoft Word - cau-truc-du-lieu-hang-doi.docx

Bài 4 Tựa bài

Hik-Connect làgì? Hướng dẫn sử dụng Hik-Connect Tính năng chia sẻ (Share) Dịch vụ lắp đặt camera quan sát uy tín chất lượng, hệ thống đại

Cách tạo User và Thiết kế Database Cách tạo User và Thiết kế Database Bởi: Khoa CNTT ĐHSP KT Hưng Yên Cách tạo một User Database Chúng ta có thể tạo m

Làm quen với chương trình Microsoft Excel Làm quen với chương trình Microsoft Excel Bởi: unknown Làm quen với chương trình Những thao tác đầu tiên với

26 Khoa hoïc Coâng ngheä LẬP TRÌNH PHÂN TÁN DÙNG CÔNG NGHỆ MOBILE AGENT VỚI SỰ HỖ TRỢ CỦA JAVA VÀ VOYAGER Tóm tắt ThS. Nguyễn Khắc Quốc * Lập trình ph

Microsoft Word - cai_dat_android_studio.docx

Microsoft Word - custom_component_trong_android.docx

Bản ghi:

QT4i Documentation åŕśåÿč 3.3 QTA 2019 åźt 03 æijĺ 12 æůě

Contents 1 ä çťĺæűğæač 2 2 æőěåŕčæűğæač 63 3 çt ćåijţåšňæřijçt ć 85 Python æĺaåiůçt ćåijţ 86 i

QT4i(Quick Test for ios)ïijňå žäžőqtaæŕřä ŻéİćåŘŚiOSåžŤçŤĺçŽĎUIæţŃèŕŢèĞłåŁĺåŇŰæţŃèŕŢèğčåEş Contents 1

CHAPTER 1 ä çťĺæűğæač 1.1 ä çťĺål åğeåd Ğ QT4iä İèţŰQTAFæĺąåİŮïijŇä çťĺål èŕůåŕćèăčãăłtestbaseä çťĺål åğeåd ĞãĂŃäÿĂèŁĆãĂĆ 1.1.1 åğeåd ĞMacçŤţèĎŚ QT4içŽĎæţŃèŕŢéIJĂèęAåIJĺMacäÿŁæL ğèąňïijňéijăèę AåĞ Eåd ĞäÿĂåŔřMacåźűçňęåŘĹäżěäÿŃèę AæśĆïij æş ä IJçşżçż äÿžïijžmac OS X EI CapitanïijĹçL ĹæIJň10.11.6åŔŁäżěäÿŁïijŇæŐĺè Řå ĞçžğåĹřæIJĂ äÿńè QT4içŻÿåĚşçŽĎåůěåĚů åůěåěůåř çğř UISpy QTA-IDE Xcode èąĺ 1: QT4iåůěåĚůæÿĚå Ţ èŕt æÿő æ ěçijńappçžďæőğäżűæăśäżěåŕłæőğäżűqpathçžďåůěåěůïijňèğčåőńå şåŕŕä PythonèĎŽæIJňåijĂåŔŚçŐŕåćČ(åŔŕéĂL æńl èğłåůśåűijæňćçžďide) QT4iä İèţŰçŽĎxcteståžŢåśĆåůěåĚůïijŇXcode6åŔŁäżěäÿŃäÿ æťŕæňa 1.1.2 åğeåd ĞiOSèő åd Ğ QT4ièĞşåřŚéIJĂèęAäÿĂåŔřiOSèő åd ĞïijŇåŔŕäżěæŸŕçIJ æijžæĺűæĺąæń åźĺãăć ä çťĺiosçij æijž 1. éăžè ĞUSBè dæőěiosèő åd ĞåĹřMacïijŇåĹİæňąè dæőěæůűéijăèęaç L å ĚæL ŃæIJžâĂIJæŸŕåŘ 2

2. æ ěèŕćiosèő åd ĞçŽĎèő åd ĞæăĞèŕEçňęUDID æl ŞåijĂXcode, ä İæňąè ŻåĚěèŔIJå ŢWindow->Devices and SimulatorsïijŇæ ěèŕćèőůåŕűiphoneæl ŃæIJžçŽĎUDIDïijŇåęĆäÿŃåŻ æl Ăçd žïijž 3. æl ŞåijĂUI AutomationåŁ èč 1.1. ä çťĺål åğeåd Ğ 3

ä çťĺiosæĺaæń åźĺ 1. åřŕåłĺiosæĺąæń åźĺ(æšąæijl çžďèŕiïijňåŕŕäżěæűřåżž) 2. æl ŞåijĂUI AutomationåŁ èč ïijňæűźæşţåřňçij æijžçžďæűźåijŕãăć èřčèŕţåeěåţňwebviewåžťçťĺ åęćæ dijä çťĺiosèő åd ĞèřČèŕŢWebViewéąţéİćïijŇéIJĂèęAæL ŞåijĂSafariæţŔèğĹåŹĺçŽĎWebæčĂæ ěåźĺ 1. éăl æńl âăijèő ç ő => SafariæţŔèğĹåŹĺ => éńÿçžğâăi ïijž 1.1. ä çťĺål åğeåd Ğ 4

1.1. ä çťĺål åğeåd Ğ 5

2. åěaèőÿweb InspectoræIJ åłą ïijž 1.1. ä çťĺål åğeåd Ğ 6

1.1. ä çťĺål åğeåd Ğ 7

1.2 å ńéă åěěéůĺ 1.2.1 æţńèŕţéaźçżő æţńèŕţçťĺä Ńå Šåś däžőäÿăäÿłæţńèŕţéąźçżőïijňåijĺèő èőąæţńèŕţçťĺä ŃäźŃåL ïijňåęćæ dijæšąæijl æţn 1.2.2 åől èčěqt4i qt4içžďæ čåÿÿä çťĺä İèţŰãĂŁfbsimctlãĂŃåůěåĚůïijŇéęŰåĚĹéIJĂèęAåőL èčěfbsimctl: $ brew tap facebook/fb $ brew install fbsimctl --HEAD çďűåřőåől èčěqt4i: $ pip install qt4i 1.2.3 éčĺç šxctest Driverè ŘèaŇçŐŕåćČ 1. èřčçťĺæţńèŕţéąźçżőçžďmanage.pyåś äżd ïijňèğčåőńåźűèğłåłĺæl ŞåijĂXCTestAgentçŽĎåůěçĺŃ: $ python manage.py qt4i.setup åęćæ dijæšąæijl åĺżåżžæţńèŕţéąźçżőïijňäź åŕŕäżěæl ğèąňqt4imanageåś äżd äżčçřeäÿłè řåś äżd ïijž $ qt4i-manage setup æşĺèğč: XCTestAgentåůěçĺŃéżŸèőd å ŸæŤ èůŕå Ďäÿž âăij~/xctestagentâăi ãăć 2. éăl æńl âăijbuild SettingsâĂİ>âĂIJCode SigningâĂİäÿĂæăŔãĂĆ 1.2. å ńéă åěěéůĺ 8

åěĺéčĺä őæťźäÿžâăijautomaticâăi>âăijios DeveloperâĂİïijŇå ŞæĹŘåŁ æůżåłăäžeapple IDåŘŐïijŇç åř äijžèğłåłĺåŕÿäÿžèŕěidåŕźåžťçžďç åř èŕaäźęãăć 3. éăl æńl âăijbuild SettingsâĂİ>âĂIJPackagingâĂİäÿĂæăŔïijŇä őæťźâăijproduct Bundle IdentifierâĂİçŽĎåĂijïijŇèęAæśĆbundle idäÿ èč éğ åd ïijňåżžèőőåřeèğłåůśçžďåř å Ůä IJ )ãăć 1.2. å ńéă åěěéůĺ 9

4. éăl æńl âăijbuild SettingsâĂİ>âĂIJGeneralâĂİäÿĂæăŔïijŇ åń éăl âăijautomatically manage signingâăiïijňæ d æůűåžťèŕěæšąæijl äżżä Ţ鍏èŕŕæŔŘçd ž(åęć 1.2. å ńéă åěěéůĺ 10

5. éăl æńl âăijproductâăi>âăijtestâăiïijňæ dďåżžåŕłè ŘèąŇXCTestAgentãĂĆ 6. åęćæ dijåğžçőřåęćäÿńåijźæąeïijňæÿ çd žç åř åd śèt ěïijňéăl æńl âăijfix is- 1.2. å ńéă åěěéůĺ 11

sueâăiïijňçďűåřőæůżåłăäÿăäÿłapple IDèt ęæĺůïijňéăl æńl èŕěèt ęæĺůä IJäÿžäÿłäžžåijĂåŔŚåŻćéŸ 1.2. å ńéă åěěéůĺ 12

7. åęćæ dijåğžçőřåęćäÿńåijźæąeïijňéijăèę AåIJĺiPhoneäÿŁèő ç őèŕěèt ęæĺůäÿžä ąäżżåijăåŕśèăěãăc è ŻåĚěiPhoneïijŽâĂIJéĂŽçŤĺâĂİ>âĂIJèő åd ĞçőąçŘEâĂİ>âĂIJåijĂåŔŚåŢ EåžŤçŤĺâĂİïijŇä ąäżżèŕěèt ęæĺ 1.2. å ńéă åěěéůĺ 13

8. åęćæ dijåğžçőřåęćäÿńåijźæąeïijňèŕt æÿőbundle idäÿ åňźéě ïijňåřeæl ŃæIJžäÿŁçŽĎap- påĺăéźd ïijňåe éğ æűřè ŘèąŇtestãĂĆ 9. å ŞXcode testæĺřåł è ŘèąŇXCTestAgentïijŇæşĺæĎŔXcodeæL Şå řçžďä ąæaŕïijňæÿŕåřęåğžçőř testãăć 1.2. å ńéă åěěéůĺ 14

10. çąőä İXcode testèč æ čåÿÿè ŘèąŇXCTestAgentåŘŐïijŇåAIJæ ćè ŘèąŇtestïijŇåźűåĚşéŮ XcodeãĂC 1.2.4 çřeèğčuiçżşæ dď iosçžďuiçżşæ dďæűl åŕłäÿl äÿłæęćå ţïijňåžťçťĺ(app)ãăaçłůåŕč(window)ãă AæŐğäżű(Control): App: æŕŕäÿăäÿłiosåžťçťĺæÿŕäÿăäÿłappïijňå şåől èčěåĺřæl ŃæIJžäÿŁçŽĎå ĚæţŃåžŤçŤĺïijŇApp qt4i.app.app åő dçőřãăć Window: äÿăäÿłappåňěåřńåd ŽäÿłWindowïijŇWindowèąĺçd žäÿăäÿłèćńæţńçžďappçłůåŕčçţňéićïijňæĺśäżňéijăèęaåŕźæŕŕäÿłçłůåŕčè ŻèąŇåőŽäźL qt4i.icontrols.window åő dçőř ãăć Control: äÿăäÿłwindowåňěåřńåd ŽäÿłControlïijŇå şæŕŕäÿăäÿłçłůåŕčåňěåřńäžeåd ŽäÿłæŐğäżűå æőğäżűå žçśżçťś qt4i.icontrols.element åő dçőř æl ĂäżěæĹŚäżňéIJĂèęAäżěQT4iäÿ çžďåő dçőřäÿžå žçąăïijňéšĺåŕźäÿl çğ UIåĚČçt ăåĺeåĺńè ŻèąŇåř Aè 1.2.5 çňňäÿăäÿłæţńèŕţçťĺä Ń èğşæ d ïijňè ŘèąŇqt4iæL Ăå ĚèęAçŽĎçŐŕåćČïijŇåůšçżŔæŘ åżžåőňæĺřïijňäź åŕźuiçżşæ dďäź æijl äž äÿ åęĺäżěiosçşżçż èğłåÿęçžďèő ç őåžťçťĺäÿžä Ń(æĺąæŃ åźĺåšňçij æijžéč æijl )ïijňåijăåğńåeźqt4 èŕůåěĺåŕćèăčãăłtestbaseèő èőąæţńèŕţçťĺä ŃãĂŃçE æćl çťĺä Ńå žæijňçżşæ dďãăćçťśåijăåd t åŕŕç demotest:æţńèŕţçťĺä ŃéŻEåŘĹïijŇè ŹéĞŇå ŸåĆĺæL ĂæIJL æţńèŕţçťĺä ŃçŽĎèĎŽæIJňãĂĆ demolib:æţńèŕţäÿžåłąåžşïijňè ŹéĞŇå ŸæŤ æl ĂæIJL æţńèŕţäÿžåłąlibåśćçžďäżčçăaïijňä å Ů settings.py:éąźçżőéě ç őæűğäżűïijňåŕŕäżěéě ç őä ăæl ĂéIJĂèęAçŽĎéąźãĂĆ demotestçżőå ŢäÿŃäijŽèĞłåŁĺçŤ æĺřhello.pyæűğäżűïijňæĺśäżňåijĺèŕěæűğäżűåő dçőřçňňäÿăäÿłçőăå T from qt4i.device import Device from demolib.demotestbase import DemoTestcase from demolib.demoapp import DemoApp class DemoTest(DemoTestcase): 'DemoæţŃèŕŢ' (continues on next page) 1.2. å ńéă åěěéůĺ 15

(çż äÿłéąţ) owner = 'apple' # ----------------------------------------# èďžæijňçžďèő èőąèăě priority = DemoTestcase.EnumPriority.Normal # ----------------- # èďžæijňçžďäijÿåěĺçžğ status = DemoTestcase.EnumStatus.Design # --------------------- # èďžæijňçžďçłűæăą timeout = 5 # ------------------------------------------------- # èďžæijňæl ğèąňèűěæůűåăij ïijĺåĺęéš ïijl def run_test(self): self.start_step('1ãăąçťşèŕůèţďæžřåřŕåłĺdemoapp') device = Device() # --------------------------------------- # çťşèŕůæţńèŕţèő åd Ğ demoapp = DemoApp(device) # ------------------------------- # åřŕåłĺèćńæţńèŕţapp self.start_step('2ãăąæ ěèŕćèő åd Ğä ąæąŕ') isenter = demoapp.enter() # ------------------------------- # è ŻåĚěèő åd Ğä ąæąŕéąţéić self.assertequal("æčăéłňæÿŕåřęæ ěçijńæĺřåł "ïijň isenterïijň True) # --------# æčăæ ěæÿŕåřęè ŻåĚěæĹŘåŁ self.start_step('3ãăąä őæťźèő åd ĞåŘ çğř') name = 'qt4i' ismodify = demoapp.rename(name) # ------------------------- # ä őæťźèő åd ĞåŘ çğř self.assertequal("æčăéłňæÿŕåřęä őæťźæĺřåł "ïijň ismodifyïijň True) # ------# æčăæ ěæÿŕåřęä őæťźæĺřåł è ęåśł: åijĺæţńèŕţçťĺä Ńäÿ åijžçčĺåżžèőőåŕłèřčçťĺlibåřaèčěçžďæőěåŕčåšňæű èĺăæş ä IJïijŇäżě UIåŔŸåŇŰçŤĺä ŃçŽĎéĂżè Śäÿ éijăèęaæťźåłĺïijňåřňæůűäź æijăåd ğéźřåžęåd çťĺlibåřaèčěãăć çżğæl äžőæţńèŕţå žçśż éęűåěĺïijňçťĺä ŃçżğæL äžődemotestbaseæţńèŕţå žçśżïijňéšĺåŕźæţńèŕţå žçśżçžďåřaèčěåŕŕäżěåŕć èőůåŕűèő åd Ğ èőůåŕűè dæőěåijĺmacäÿłçžďçżĺçńŕèő åd ĞïijŇåĹl çťĺ qt4i.device.device çśżåő dä ŃåŇŰæŇĞåőŽèő åd ĞåŕźèśąãĂĆåęĆæ dijæijłæňğåőžèő åd ĞåĹŹèŐůåŔŰéŞ æőěåijĺmacäÿłçž device = Device(udid=None) # äijăåěěèő åd ĞudidåŔŕäżěæŇĞåőŽä çťĺåěůä Şèő åd Ğ 1.2. å ńéă åěěéůĺ 16

è ęåśł: åęćæ dijæšąæijl è dæőěçij æijžåšňåůšçżŕåřŕåłĺçžďæĺąæń åźĺïijňåĺźäijžæłżåğžåijćåÿÿã åő dä ŃåŇŰAppçśż çťşèŕůåĺřèő åd ĞåŘŐïijŇåijĂåğŃåő dä ŃåŇŰä ăçžďåžťçťĺappçśżïijňéšĺåŕźdemoappçžďåřaèčěåŕŕäżě demoapp = DemoApp(device) äÿžåłaéăżè ŚæŞ ä IJ åijĺçťĺä Ńäÿ åŕłèřčçťĺäÿžåłąéăżè ŚæŐěåŔčïijŇèĂŇäÿŽåŁąéĂżè Śåő dçőřåijĺdemolibåžşäÿńçžďåřďä demoapp.enter() # -------------------------------# è ŻåĚěèő åd Ğä ąæąŕéąţéić demoapp.rename(name) # -------------------------# ä őæťźèő åd ĞåŘ çğř èŕěåł èč äijžèğłåłĺè ŻåĚěèő åd Ğä ąæaŕéąţéićïijňåźűäÿťä őæťźèő åd ĞåŘ çğřãăćæl ĂäżěæŐěäÿŃæİ self.assertequal("æčăéłňæÿŕåřęä őæťźæĺřåł ",ismodify,true) #------# æčăæ ěæÿŕåřęä őæťźæĺřåł èğşæ d ïijňäÿăäÿłå žæijňçžďçťĺä ŃåřśåőŇæĹŘäžEãĂĆ 1.3 UIåĚČçt ăåřaèčě iosçłůåŕčäÿ çžďåd ğéčĺåĺeæőğäżűåěčçt ăéijăèę AçŤĺQPathè ŻèąŇåőŽä ãăć 1.3.1 åřaèčěæţńèŕţå žçśż æţńèŕţå žçśżæęćè ř QTAFäÿ åő dçőřçžďæţńèŕţå žçśżãăłtestcaseãăńæŕřä ŻäžEå Ĺåd ŽåŁ èč æőěåŕčïijňåęćçőŕåćčåğe æţńèŕţå žçśżåřaèčě çżőål qt4içžďæţńèŕţå žçśż qt4i.itestbase.itestbase åůšçżŕåő dçőřäžeioséijăèę AçŽĎåÿÿçŤĺåŁ èč ãăćä ăåŕŕäżěåijĺdemolib/demotestbase.pyäÿ åřaèčěä ăçž 1.3. UIåĚČçt ăåřaèčě 17

from qt4i.itestcase import itestcase from qt4i.device import Device from testbase.conf import settings class DemoTestcase(iTestCase): '''DemoæţŃèŕŢçŤĺä Ńå žçśż ''' def pre_test(self): '''åĺiåğńåňűæţńèŕţçťĺä Ń ''' super(itestcaseïijň self).pre_test() self.log_info("%s.pre_test "%self. class. name ) def post_test(self): '''æÿěçřęäÿńæţńèŕţçťĺä Ń ''' super(itestcaseïijň self).post_test() self.clean_login() self.log_info("%s.post_test "%self. class. name ) def clean_login(self): '''æÿěçřęappçžďçźżå ŢçŁűæĂĄ ''' for device in Device.Devices: device.remove_file(settings.app_bundle_idïijň "/ Documents/contents/DemoAccountManager") #èćńæţńappçźżå ŢæĂĄæŰĞäżűçŽĎå ŸåĆĺèůŕå Ď å şåŕŕåő dçőřæţńèŕţçťĺä ŃçŽĎçŐŕåćČåĞEåd ĞæĹŰçŐŕåćČæÿĚçŘ EåŁ èč ãăćéźd äž EäżěäÿŁåř AèčĚçŽ ::æăźæ őè ŻçĺŃåŘ (åŕŕéăžè Ğxcodeæ ěçijń)ïijňèőůåŕűappçžďcrashæůěå Ů: def get_crash_log(self, procname): æŕŕäÿłæ ěéłd ål èğłåőžäźl äÿăäžżæş ä IJïijŇä ŃåęĆæŕŔäÿłæ ěéłd ål éč æl Şå řåğžæůűéůt æ def start_step(self, step): ç L ç L ïijňæżt åd ŽåŔĆèĂČQTAFåŠŇQT4iæŐěåŔčæŰĞæąčãĂĆ è ęåśł: éğ è å žçśżåřďäÿłæőěåŕčæůűïijňå ĚéążæŸ åijŕèřčçťĺå žçśżçžďåğ æţřïijňäżěåě å žçśżç æţńèŕţå žçśżä çťĺ åijĺçťĺä Ńäÿ åřeèŕěçśżä IJäÿžæţŃèŕŢçŤĺä ŃçŽĎå žçśż: 1.3. UIåĚČçt ăåřaèčě 18

class HelloTest(DemoTestBase): 1.3.2 åřaèčěapp AppçśżæęĆè ř åijĺdemolib/demoapp.pyäÿ åřaèčěä ăçžďåžťçťĺappçśżdemoapp,åő dçőřappçśżçžďå žæijňåł èč qt4i.app.app çśżæŕřä ŻäžEåÿÿèğ AåŁ èč ïijňåęćåřŕåłĺapp, åijźçłůåd ĎçŘEç L ãăć AppçśżåřAèčĚ æĺśäżňäż äżědemo Appäÿžä ŃïijŇåőŇæŢt äżčçăaèğ ADemoåůěçĺŃãĂĆèćńæţŃåžŤçŤĺçŽĎå žæijňappçśż from qt4i.icontrols import App from testbase.conf import settings from demolib.infowin import InfoWin from demolib.namewin import NameWin class DemoApp(App): '''DemoApp èt èt čèćńæţńåžťçťĺçžďåřŕåłĺåšňåĺiåğńåňű ''' def init (selfïijň deviceïijň app_name=settings.app_bundle_ IDïijŇ trace_template=noneïijň trace_output=none): '''APPåžŤçŤĺïijĹåŘŕåŁĺAPPïijL teaceå ŸåĆĺèůŕå ĎïijĹäÿŞéąźæţŃèŕŢä çťĺïijňåł èč æţńèŕţéżÿèőd äÿžnoneå şåŕŕïijl :param device : DeviceçŽĎåő dä Ńåŕźèśą :type device : Device :param app_name : APPçŽĎBundleIDïijĹä ŃåęĆïijŽcom. tencent.demoïijl :type app_name : str :param trace_template : traceæĺąæi ïijĺäÿşéąźæţńèŕţä çťĺïijňåł èč æţńèŕţéżÿèőd äÿžnoneå şåŕŕïijl :type trace_template : str :param trace_output : :type trace_output : str ''' App. init (selfïijň deviceïijň app_nameïijň trace_ templateïijň trace_output) self.set_environment() self.start() (continues on next page) 1.3. UIåĚČçt ăåřaèčě 19

def set_environment(self): '''åĺiåğńåňűèğłåłĺåd ĎçŘĘAlertåijźæąĘåžŤåŕźèğĎåĹŹ (çż äÿłéąţ) :param: none :returns: none ''' # æ d èğďåĺźçťĺäžőåd ĎçŘĘéćĎæIJ åęěåőźä ĘéŽ äżěéćďæij åijźåğžæůűæijžçžďalertæąęïi # éě ç őç ŰçŢěåŘŐïijŇåŔłèęĄAlertæąĘåŚ äÿ ç ŰçŢěïijŇå şæňl ç ŰçŢěåd ĎçŘĘãĂĆä ŃåęĆæ self.rules_of_alert_auto_handle = [ # æőĺéăąéăžç ě { 'message_text': 'æőĺéăąéăžç ě Notifications'ïijŇ # æťŕæňąæ čåĺźèąĺè åijŕ 'button_text': '^åě $ ^Allow$ ^åěąèőÿ$' # æťŕæňąæ čåĺźèąĺè åijŕ }ïijň ] # æ d åijăåěşæl ŞåijĂïijŇçŤĺäžŐåd ĎçŘĘäÿ åŕŕéćďæij åęěåőźäÿťäÿ åŕŕéćďæij æůűæijžç # åęćæ dijalertæąęåś äÿ äÿłæűźçžďç ŰçŢěïijŇåĹŹæ d éąźéě ç őåřęèćńèůşè ĞãĂĆ self.flag_alert_auto_handled = False def enter(self): '''è ŻåĚěèő åd Ğä ąæąŕåğ æţř ''' infowin = InfoWin(self) return infowin.enter_info() def rename(selfïijň name): '''éğ åś åř åğ æţř ''' namewin = NameWin(self) return namewin.modify_name(name) äÿłè řäżčçăaåő dçőřå žæijňçžďappåł èč ãăćäÿżèęaåňěæńňappä çťĺè ĞçĺŃäÿ ïijňåğžçőřçşżçż åi Appçśżä çťĺ åijĺçťĺä Ńäÿ çťşèŕůåőňèő åd ĞåŘŐïijŇå şåŕŕåijăåğńåő dä ŃåŇŰèćńæţŃAppïijŇåęĆäÿŃ: app = DemoApp(device) 1.3. UIåĚČçt ăåřaèčě 20

1.3.3 åřaèčěqpath ä çťĺåijžæźŕ æőğäżűçžďåőžä åšňæ ěæl åřaèčěåijĺlibåňěäÿ çžďxxx_win.pyäÿ ïijňåżžèőőappäÿăäÿłçţňéićåŕłè äżěåřaèčěçşżçż èő ç őappçžďâăijéăžçťĺâăiæőğäżűäÿžä Ń: self.updatelocator('éăžçťĺ': {'type': ElementïijŇ 'root': selfïijň 'locator': QPath("/classname = 'Cell' & label = 'éăžçťĺ' & maxdepth = 7")})ïijŇ type: æňğåőžæőğäżűçžďçśżå dńïijňåšňiosäÿ åőžäźl çžďæőğäżűçśżå dńçżÿåŕźåžťïijňåęćtablev SliderïijŇ ActionSheetç L ãăć root: æňğåőžæőğäżűçžďçĺűèłćçćźïijňæňğåőžçĺűèłćçćźåřőïijňæ ěæl æőğäżűæůűïijňäijžå åęćæ dijæňğåőžäÿžselfïijňåĺźèąĺçd žäijžäżőæţt éćůæőğäżűæăśæăźèłćçćźåijăåğńæ ěæl çżőæ locator: æňğåőžqpath QPathèŕ æşţçžďå ęäźăåŕŕåŕćèăčãăłqpathèŕ æşţåšňä çťĺãăńãăćqt4iéăžè ĞQPathåőŽä æőğäżűï è ęåśł: æ ěçijńæőğäżűæăśïijňéijăèęaåěĺéčĺç šxctest Driverè ŘèąŇçŐŕåćČïijŇåĚůä ŞåŔŕåŔĆèĂČãĂŁéČĺç šxctest Driverè ŘèaŇçŐŕåćČãĂŃ ä çťĺuispyå şåŕŕèőůåŕűèő åd Ğå ŞåL éąţéićæőğäżűæăśïijž 1.3. UIåĚČçt ăåřaèčě 21

æşĺèğč: èńěéağåĺřuispyçl ĹæIJňåŠŇQT4içL ĹæIJňäÿ åňźéě çžďæčěåeţïijĺrpcæőěåŕčæl äÿ åĺřïi $ killall -9 python åijĺäÿłè řçňňäÿăäÿłçťĺä Ńäÿ æŕřåŕłçžďinfowinçţňéićåřaèčě: from qt4i.icontrols import Window from qt4i.icontrols import Element from qt4i.qpath import QPath class InfoWin(Window): '''DemoApp è ŞåĚě珿å Ţéąţéİć ''' def init (selfïijň app): Window. init (selfïijň app) self._device = self._app.device locators = { 'éăžçťĺ': {'type': ElementïijŇ 'root': selfïijň (continues on next page) 1.3. UIåĚČçt ăåřaèčě 22

(çż äÿłéąţ) 'locator': QPath("/classname = 'Cell' & label = 'éăžçťĺ' & maxdepth = 7")}ïijŇ 'åěşäžőæijňæijž': {'type': ElementïijŇ 'root': selfïijň 'locator': QPath("/classname = 'StaticText' & label = 'åěşäžőæijňæijž' & visible = true & maxdepth = 12")}ïijŇ 'åř çğř': {'type': ElementïijŇ 'root': selfïijň 'locator': QPath("/classname = 'StaticText' & label = 'åř çğř' & visible = true & maxdepth = 11")}ïijŇ # "Table": {"type": ElementïijŇ "root": selfïijň # "locator": QPath("/classname = 'Table' & visible = true & maxdepth = 10")}ïijŇ # "åř çğř": {"type": ElementïijŇ "root": "@Table"ïijŇ # "locator": QPath("/classname='StaticText' & label ='åř çğř' & maxdepth = 1")}ïijŇ } self.updatelocator(locators) def enter_info(self): '''èt ęåŕůåŕęçăąè ŞåĚě珿å ŢåĞ æţř ''' self.controls['éăžçťĺ'].click() self.controls['åěşäžőæijňæijž'].click() return self.controls['åř çğř'].exist() äżěçťĺä Ńäÿ çžďâăÿåř çğřâăźäÿžä ŃïijŇUISpyæ ěçijńåšňèőůåŕűæőğäżűçžďqpath: 1.3. UIåĚČçt ăåřaèčě 23

æőğäżűçžďqpathåőžä åŕŕäżěå žäžőåěűçżiåŕźèůŕå ĎèŐůåŔŰ(å žäžőwindowæ ěæl )ïijňäź åŕŕäżěå ž "Table": {"type": ElementïijŇ "root": selfïijň "locator": QPath("/classname = 'Table' & visible = true & maxdepth = 10")}ïijŇ "åř çğř": {"type": ElementïijŇ "root": "@Table"ïijŇ "locator": QPath("/classname='StaticText' & label ='åř çğř ' & maxdepth = 1")}ïijŇ QPathäÿ éźd äžeæőğäżűèůŕå ĎæİěéŹŘåĹűåőŽä çňęäźńåd ŰïijŇè ŸåŔŕäżěéĂŽè ĞnameãĂAlabelç L åś ~= *âăiãăć æşĺèğč: å žäžőçţňéićçžďæş ä IJåŠŇåĹd æű éč åžťèŕěåřaèčěåijĺlibåňěçžďxxxwin.pyäÿ ïijňäżěçąőä åŕęåd ŰïijŇåęĆæ dijæőğäżűåěůæijl nameåś dæăğ(åťŕäÿă)ïijňåŕŕäżěçżt æőěä çťĺnameä IJäÿžQPathãĂĆ æşĺæďŕ: åőžä çňęæÿŕqpathçžďå ĚéążæŇĞåőŽæIJĂåd ğæ ěæl æůśåžęïijňåřęåĺźåŕłäijžåijĺwindow åijĺäÿłè řçňňäÿăäÿłçťĺä Ńäÿ æŕřåŕłçžďnamewinçţňéićåřaèčě: 1.3. UIåĚČçt ăåřaèčě 24

from qt4i.icontrols import Window from qt4i.icontrols import Element from qt4i.qpath import QPath class NameWin(Window): '''DemoApp æşĺéťăçźżå Ţéąţéİć ''' def init (selfïijň app): Window. init (selfïijň app) self._device = self._app.device locators = { 'æżt åd Žä ąæąŕ': {'type': ElementïijŇ 'root': selfïijň 'locator': QPath("/classname = 'Button' & label = 'æżt åd Žä ąæąŕ' & visible = true & maxdepth = 11")}ïijŇ 'è ŞåĚěæąĘ': {'type': ElementïijŇ 'root': selfïijň 'locator': QPath("/classname = 'TextField' & visible = true & maxdepth = 11")}ïijŇ 'åř çğřåăij': {'type': ElementïijŇ 'root': selfïijň 'locator': 'qt4i'}ïijň } self.updatelocator(locators) def modify_name(selfïijň name): ''' ''' self.controls['æżt åd Žä ąæąŕ'].click() name_text_field = self.controls['è ŞåĚěæąĘ'] name_text_field.click() name_text_field.value = name name_text_field.send_keys('\n') return self.controls['åř çğřåăij'].exist() äżěçťĺä Ńäÿ çžďâăÿåř çğřåăijâăźäÿžä ŃïijŇUISpyæ ěçijńåšňèőůåŕűæőğäżűçžďqpath: 1.3. UIåĚČçt ăåřaèčě 25

çřeèğčuiçżşæ dď ios UI翪æ dďæijăåd ŰåśĆæŸŕWindowïijŇçĎűåŘŐæŸŕæŐğäżűéĂŘåśĆåţŇåěŮïijŇèęAèő éůőæňğåőžæo 1.3. UIåĚČçt ăåřaèčě 26

åőžä çňę: QPath("/classname='UIAWindow'/classname='UIACollectionView'/ classname='uiacollectioncell' & instance=1") äÿłè řqpathåĺźäijžè ŤåŻ dåż äÿ 1åŔůCollectionCellæŐğäżűïijŇåęĆæ dijèęaè ŤåŻ d2åŕůåšň3åŕůcollec QPath("/classname='UIAWindow'/classname='UIACollectionView'/ classname='uiacollectioncell' & instance=2") #...Q2 QPath("/classname='UIAWindow'/classname='UIACollectionView'/ classname='uiacollectioncell' & instance=3") #...Q3 æşĺèğč: instanceçťĺäžőéźřåőžåěűåůęè źèůŕå ĎæL ĂæŇĞåŕźèśąæŸŕçňňåĞăäÿłæŸŕåő dä ŃïijŇæL Ăäżěäÿ æőğäżűçśżå dńåšňåś dæăğ æőğäżűçśżå dń QT4iæŔŘä ŻElementãĂAAlertãĂ ASliderãĂ AActionSheetåŠŇTableViewå̜䞍çğ æőğäżűçśżå dń: ElementäÿžéĂŽçŤĺæŐğäżűçśżå dńïijňbutton/element/image/toolbarâăęâăęäżěåŕłäÿłè řæijłæŕřå 1.3. UIåĚČçt ăåřaèčě 27

AlertçŤĺäžŐåő dä ŃåŇŰiOS AlertåijźçłŮæŐğäżűïijŇåĚůæIJL titleåšňbuttonsåś dæăğïijňè ŤåŻ dæăğéćÿåšňæl ĂæIJL å ŘæŇL éšőïijż SliderçŤĺäžŐåő dä ŃåŇŰiOS SliderBaræŐğäżűïijŇåĚůæIJL valueåś dæăğïijňèŕżåŕűåšňèő ç őæżśåłĺåiůä ç őïijż ActionSheetçŤĺäžŐåő dä ŃåŇŰiOS ActionSheetæŐğäżűïijŇåĚůæIJL buttonsåś dæăğïijňè ŤåŻ dæl ĂæIJL å ŘæŇL éšőïijż TableViewçŤĺäžŐåő dä ŃåŇŰiOS TableViewæŐğäżűïijŇåĚůæIJL cellsåś dæăğïijňè ŤåŻ dæl ĂæIJL å ŘåĹŮèąĺãĂĆ æőğäżűåś dæăğ éăžåÿÿæőğäżűåěůæijl labelãăanameãă AvalueãĂ Avisibleç L åś dæăğïijňåŕŕäżěéăžè ĞUISpyæ ěçijńå 1.3. UIåĚČçt ăåřaèčě 28

æżt åd ŽåĚşäžŐæŐğäżűåś dæăğåšňæőěåŕčïijňèŕůåŕćèăčæőěåŕčæűğæąčãăć 1.4 åÿÿèğaèő åd ĞæŞ ä IJ åijĺiosèğłåłĺåňűè ĞçĺŃäÿ ïijňéa åě äÿ äžeçžďæÿŕåŕźèő åd ĞçŽĎåŘĎçğ æş ä IJïijŇåęĆåřEå ŞåL A 1.4.1 çćźåğżåśŕåźţ åęćæ dijä ăæčşçżt æőěå žäžőåśŕåźţè ŻèąŇçĆźåĞżæŞ ä IJïijŇåŔŕäżěçŻt æőěèřčçťĺ qt4i.device.device äÿ åőžäźl çžďclick()æűźæşţ: device = Device() device.click() éżÿèőd çćźåğżåśŕåźţæ čäÿ éůt ãăć è ęåśł: éăžåÿÿæčěåeţäÿńèŕůäijÿåěĺä çťĺqt4iåřďäÿłæőğäżűçśżå dńæŕřä ŻçŽĎclickæŐěåŔčåŐżç 1.4.2 æĺaæń æňl éťő iosèő åd ĞäÿŁæIJL å Ĺåd ŽèŹŽæŃ æňl éťőïijňåęćhomeéťőãăaé şéğŕéťőç L ïijňqt4aåřaèčěäž Eå device = Device() çďűåřőåŕŕäżěæĺąæń åŕśéăaåřďçśżæňl éťőïijňåęćhomeéťő device.deactivate_app_for_duration(seconds=-1) #secondsäÿž- 1æŮűïijŇåĹŹæĺąæŃ æňl HomeéŤőçŽĎæŢĹæ dij; secondsäijăåěěæţt æţřåăij, åŕŕäżěåřęå ŞåL Appç őäžőåřőåŕřäÿăåőžæůűéůt éğ åřŕéťő: device.reboot() #éğ åřŕ éťaåśŕåšňèğčåśŕéťő: device.lock() device.unlock() #éťąåśŕ #èğčåśŕ é şéğŕèřčèłć(æĺąæń åźĺæšąæijl ): device._volume('up') #èřčéńÿé şéğŕ åŕęåd Ű, qt4i.device.device çśżåřaèčěçžďæőěåŕčïijňè Ÿä Żsiriäžd äžšïijňæůńè ňåśŕåźţç L æo 1.4. åÿÿèğaèő åd ĞæŞ ä IJ 29

1.4.3 æżśåłĺåśŕåźţ æijl æůűåăźä ăéijăèęaéšĺåŕźåśŕåźţè ŻèąŇæżŚåŁĺïijŇä ŃåęĆèŃěAppçśżåijĂåd t æijl äÿăäžżåź åśłé def drag(self, from_x=0.9, from_y=0.5, to_x=0.1, to_y=0.5, duration=0.5): '' 'åż déą åśŕåźţè źçijÿïijňåěĺåśŕæńűæń ïijĺéżÿèőd åijĺåśŕåźţäÿ åd őäżőåŕşåřśåůęæńű :param from_x: èţůçćź xåąŕçğżçź åĺęæŕť(äżőåůęèğşåŕşäÿž0.0èğş1.0) :type from_x: float :param from_y: èţůçćź yåąŕçğżçź åĺęæŕť(äżőäÿłèğşäÿńäÿž0.0èğş1.0) :type from_y: float :param to_x: çżĺçćź xåąŕçğżçź åĺęæŕť(äżőåůęèğşåŕşäÿž0.0èğş1.0) :type to_x: float :param to_y: çżĺçćź yåąŕçğżçź åĺęæŕť(äżőäÿłèğşäÿńäÿž0.0èğş1.0) :type to_y: float :param duration: æňąçż æůűéůt ïijĺçğšïijl :type duration: float ''' äijăåěěäÿ åřňçžďåiřæăğåăij,ä åŕŕäżěåő dçőřäÿłäÿńåůęåŕşïijňäÿ åřňåźěåžęçžďæżśåłĺãăć 1.4.4 åśŕåźţæĺłåż åijĺæl ğèąňçťĺä Ńè ĞçĺŃäÿ ïijňæijl äžżåijžæźŕéijăèęaæĺłåż äÿńæiěåÿőåłl åĺ Eæ dřïijňåŕŕäżěèřčçť device = Device() device.screenshot(image_path='/user') å ŞçĎűïijŇQT4iåIJĺçŤĺä Ńåd śèt ěæůűäź äijžæĺłåż ä İå ŸAppçŐřåIJžãĂĆåęĆä ăè ŸéIJĂåĚűäżŰæĹłåŻ 1.5 è ŻéŸűæŇĞå Ů äżńçż QT4içŽĎéńŸçžğçL źæăğåšňä çťĺæűźæşţãăć 1.5.1 åijźçłůçžďèğłåłĺåd ĎçŘE QT4iæŔŘä ŻäžEåijźçłŮçŽĎèĞłåŁĺåd ĎçŘ EæIJžåĹűïijŇå ŞèćńæţŃAppåIJĺçŤĺä ŃæL ğèąňäÿ åğžçőřalertå åőžäźl åijźçłůçžďåd ĎçŘEèğĎåĹŹæİěåő dçőřèğłåłĺåd ĎçŘEãĂĆ åijźçłůåd ĎçŘEèğĎåĹŹèŕt æÿő: 1. äijÿåěĺéa åőeçťĺæĺůåőžäźl çžďéćďæij èğďåĺź rules_of_alert_auto_handle åd ĎçŘEïijĹåĚűäÿ message_text èąĺçd žalertæăğéćÿæăŕæűğå ŮïijŇ button_text èąĺçd žalertçžďæňl éšőå ŮæőţïijŇäÿd èăěåiğæťŕæňaæ čåĺźåňźéě ïijl ïijż 1.5. è ŻéŸűæŇĞå Ů 30

2. åęćæ dij1äÿ åőžäźl çžďèğďåĺźäÿ æżąèűşïijňåĺźæňl çěğflag_alert_auto_handledèő ç őçžďèğďåĺ 3. å Ş rules_of_alert_auto_handle èő ç őäÿžtrueïijňä EæŸŕåŔĹåÿŇæIJŻæ ŘäÿłåijźçłŮçŤśçŤ rules_of_alert_auto_handle äÿ æůżåłăåŕłåňěåřńmessage_textçžďèğďåĺźåő dçőřãăć ä çťĺçd žä ŃåęĆäÿŃ: class DemoApp(App): '''èćńæţńappå žçśż ''' def init (self, device, app_name=settings.app_bundle_id, trace_template=none, trace_output=none): App. init (self, device, app_name, trace_template, trace_ output) self.set_environment() self.start() def set_environment(self): '''éě ç őèğłåłĺåd ĎçŘĘAlertåijźæąĘèğĎåĹŹ ''' self.rules_of_alert_auto_handle = [ # æţńèŕţèt ęåŕů { 'message_text' : 'æţńèŕţåŕůçăą', # æťŕæňąæ čåĺźèąĺè åijŕ 'button_text' : '^çąőåőž$' # æťŕæňąæ čåĺźèąĺè åijŕ }, # éăăåğžçźżå Ţ { 'message_text': 'éăăåğžçźżå Ţ', #åśŕèť éăăåğžçźżå ŢçŽĎèĞłåŁĺåd ĎçŘĘ }, ] self.flag_alert_auto_handled = False æşĺèğč: åęćæ dijåijźçłůèćńåd ĎçŘEäž EïijŇä EæŸŕéćĎæIJ çžďæőğäżűåğžçőřæl äÿ åĺřçžďåijžæźŕïijň 1.5.2 åd ŽçżĹçńŕçL źæăğ åd ŽçżĹçńŕçL źæăğæÿŕæňğåijĺåřňäÿăäÿłæţńèŕţçťĺä Ńäÿ åěaèőÿçťşèŕůåd ŽåŔřiOSèő åd Ğè ŻèąŇæţN 1.5. è ŻéŸűæŇĞå Ů 31

åžťçťĺåijžæźŕ åd ŽçżĹçńŕçL źæăğéăćçťĺäžőåd ŽåŔřèő åd ĞäźŃéŮt å Ŕä IJåőŇæĹŘçŽĎæţŃèŕŢåIJžæŹŕïijŇä ŃåęĆïijŽi ä çťĺæűźæşţ åijĺæţńèŕţçťĺä ŃåĹŻåżžäÿĂäÿłæŰřçŽĎDeviceåŕźèśąïijŇå şçťşèŕůäÿăåŕřçżĺçńŕèő åd ĞïijŇåĹŻåżžåd Žäÿ çťşèŕůçžďçňňäÿăåŕřèő åd ĞäÿžæIJňåIJřè dæőěçžďèő åd ĞïijŇåŘŐçż åěűäżűèő åd Ğäÿžè IJçńŕçŽĎå from qt4i.device import Device device = Device() #----------------------------------------# çťşèŕůçňňäÿăåŕřæţńèŕţèő åd Ğ device2 = Device() #----------------------------------------# çťşèŕůçňňäžňåŕřæţńèŕţèő åd Ğ å Ŕä IJèő åd ĞçŽĎèţĎæžŘéĚ ç ő å Ŕä IJèő åd ĞçŽĎèţĎæžŘéĚ ç őæűźæşţæňl çěğçťĺä ŃæL ğèąňæĺąåijŕçžďäÿ åřňïijňåĺeäÿžæijňåijř 1.5. è ŻéŸűæŇĞå Ů 32

æijňåijřèřčèŕţçťĺä Ń 1. åijĺå Ŕä IJMacæIJžåŹĺäÿŁåŘŕåŁĺDriver: è ŘèąŇåůěçĺŃçŻőå Ţäÿ manage.pyèďžæijňïijňåś äżd åęć python manage.py qt4i.restartdriver -t xctest 2. åijĺæijňåijřmacæijžåźĺäÿłçžďåůěçĺńçżőå Ţäÿ settings.pyæűğäżűäÿ éě ç őæ ěéłd 1äÿ çžďå Ŕä QT4I_REMOTE_DRIVERS = [{'ip':'10.68.64.128'},] 1.5.3 åeěåţňwebviewçžďèğłåłĺåňű éšĺåŕźåeěåţňwebviewçžďios AppïijŇ QT4iæŔŘä ŻäžEäÿd çğ UIèĞłåŁĺåŇŰæţŃèŕŢæŰźæąĹ:å žäžőåő å žäžőåő çť æőğäżűæăśçžďæţńèŕţæűźæaĺ å žäžőåő çť æőğäżűæăśçžďæţńèŕţæűźæąĺäź å şæłłwebviewå ŞåAŽåŐ çť æőğäżűïijňæňl çěğqt åŕŕåŕćèăčuiåěčçt ăåřaèčě UIåĚČçt ăåřaèčěãăć å žäžőh5éaţéićdomæăśçžďæţńèŕţæűźæ aĺ æşĺèğč: åijăåğńæijňèłćå ęäźăål ïijňèŕůçe æćl qt4w å žçąăç ěèŕeïijňåřňæůűåŕćèăčãăłèřčèŕţå EĚåţŇWebViewåžŤçŤĺãĂŃäÿĂèŁĆåĞ Eåd Ğåě iosèő åd Ğ AppåAŽèĞłåŁĺåŇŰçŽĎãĂŁdemoãĂŃçd žä ŃïijŇåŔŕä ŻåŔĆèĂČãĂĆ å žäžőåő çť æőğäżűæăśçžďæţńèŕţæűźæąĺåijĺæ Ř䞯æţŃèŕŢåIJžæŹŕäÿ åŕŕèč å ŸåIJĺäÿĂ䞯äÿ èűş äżűæăśåŕijèğt äÿăäžżæőğäżűåěčçt ăäÿćåd śç L ç L ãăćåżăæ d ïijňæĺśäżňæŕřåğžäžeå žäžőh5éąţéićd çžďæ ěæl åőžä ïijňäÿ ä İèţŰåŐ çť æőğäżűæăśïijňåŕŕäżěæijl æţĺåijřèğčåeşåő çť æőğäżűæăśçž éăžè ĞæŞ ä IJåŐ çť æőğäżűïijňè ŻåĚěH5éąţéİć åő dä ŃåŇŰIOSWebView åřaèčěwebpage éăžè ĞWebPageè ŻèąŇWebæŐğäżűçŽĎæ ěæl åšňæş ä IJ åől èčěqt4w åijĺåől èčěäžeqt4iåřőïijňåęćæ dijéijăèęaè ŻèąŇWebèĞłåŁĺåŇŰæţŃèŕŢïijŇè ŸéIJĂèę AéĂŽè ĞpipåőL pip install qt4w 1.5. è ŻéŸűæŇĞå Ů 33

IOSWebViewçŽĎåőŽäźL qt4i.web.ioswebview æÿŕqt4iåő dçőřçžďwebviewçśżïijňæŕřä ŻiOSçńŕçŽĎwebæŐğäżűçŽĎæŐěå webæőğäżűçžďçćźåğżãăaæżśåłĺãă AéŢ æňl ãă AæŰĞæIJňè ŞåĚěäżěåŔŁjsæşĺåĚěç L åł èč ãăćçťĺæ from qt4i.icontrols import Window class BrowserWindow(Window): ''' æţŕèğĺåźĺçłůåŕčå žçśż ''' def init (self, app): self._app = app Window. init (self, self._app) scroll_win = Window(self._app, "webroot") locators = { 'webview' : {'type':ioswebview, 'root':scroll_win, 'locator':'webview', 'url':'index', 'title':'demo'}, } self.updatelocator(locators) åěűäÿ titleåšňurlæÿŕåŕŕéăl åŕćæţřïijňéżÿèőd éč äÿ æŕřä ŻçŽĎèŕİïijŇäżŐWebInspectorçŽĎçijŞå Ÿä title: åŕźåžťh5éąţéićçžď document.title çžďåeěåőź url: åŕźåžťh5éąţéićçžď location.href çžďåeěåőź, æťŕæňaæ čåĺźèąĺè åijŕ WebPageçŽĎåřAèčĚ äÿăäÿłwebpageåŕźåžťäÿăäÿłh5éąţéićïijňéăžåÿÿçťśäÿăäÿł ui_map å ŮåĚÿçżĎæĹŘïijŇåĚűäÿ åňěåřńäžeåŕźå ŞåL H5éąţéİćäÿ çžďèńěåźš webæőğäżű(webelement)çžďåőžäźl ïijňæŕŕäÿłwebæőğäżűçžďåőžäźl åňěåřńæőğäżűåř ãăaæőğäżűçśżå èąĺ 2: webæőğäżűçžďåś dæăğèŕęèğč åś dæăğåř å ĚéĂL éæŕŕè ř aź æőğäżűåř Y åňěåřńåŕźwebæőğäżűçžďæűğæijňæŕŕè řïijňåŕźåžťäžőå ŮåĚÿä type N æőğäżűçśżå dńïijňéżÿèőd åăijäÿžwebelementïijňåęćæ dijéijăèęaå locator Y WebæŐğäżűåőŽä çňęïijňä çťĺxpathæŕŕè ř ui_map N åőžäźl å ŞåL WebæŐğäżűçŽĎå ŘæŐğäżűçŽĎåś dæăğå ŮåĚÿïijŇå æşĺèğč: webæőğäżűçžďxpathåŕŕäżěéăžè ĞèŃźæ dijåőÿæűźçžďåůěåěů Safari Technology Preview æ ěçijń äÿńéićçžďäżčçăaçl ĞæőţåśŢçd žäž EäÿĂäÿłWebPageçŽĎåř AèčĚ: 1.5. è ŻéŸűæŇĞå Ů 34

from qt4w import XPath from qt4w.webcontrols import WebElement, WebPage, ui_list class LifePrivilegePage(WebPage): '''çť æt żçl źæičéąţéić ''' ui_map = { 'éźřæůűçęŕåĺl åĺůèąĺ': { 'type': ui_list(webelement), 'locator': XPath('//div[@class="mod-list list-walfare"]/ ul/li'), 'ui_map':{ 'åř çğř': XPath('//div[@class="info"]/h3'), 'æŕŕè ř': XPath('//div[@class="info"]/p[1]'), 'æĺśèęąæłć': XPath('//p[@class="surplus-time"]/ button') } } } æşĺèğč: webæőğäżűçžďxpathåŕŕäżěéăžè ĞèŃźæ dijåőÿæűźçžďåůěåěů Safari Technology Preview æ ěçijń webæőğäżűçžďæ ěæl åšňæş ä IJ åijĺäżńçż åőňæĺřwebviewåőžäźl åšňwebpageåřaèčěäźńåřőïijňæőěäÿńæiěåřśçżźåd ğåőűèőšèğčåęćä 1. éęűåěĺè ŻåĚěAppçŽĎH5éąţéİć 2. åĺiåğńåňűwebview 3. ä çťĺæ ěéłd 2äÿ çžďwebviewåĺiåğńåňűwebpage 4. ä çťĺcontrol(âăÿæőğäżűåř âăź)çžďæűźåijŕæ ěæl webæőğäżű 5. å žäžőwebelementæŕřä ŻçŽĎæŐěåŔčèŐůåŔŰwebæŐğäżűçŽĎåś dæăğåšňåŕźwebæőğäżűè ŻèąŇç äÿńéićçžďäżčçăaçl ĞæőţåśŢçd žäž EWebæŐğäżűçŽĎæ ěæl åšňæş ä IJçŽĎåĚůä Şæ ěéłd : device = Device() app = DemoApp() app.enter_h5_page() # è ŻåĚěH5éąţéİć webview = BrowserWindow(app).Controls['webview'] # åĺiåğńåňűwebview page = LifePrivilegePage(webview) # åĺiåğńåňűwebpage for elem in page.control('éźřæůűçęŕåĺl åĺůèąĺ'): # æ ěæl 'éźřæůűçęŕåĺl åĺůèąĺ' name = elem.control('åř çğř').inner_text (continues on next page) 1.5. è ŻéŸűæŇĞå Ů 35

(çż äÿłéąţ) 1.5.4 AppèĞłåŁĺåŇŰåŔŕæţŃæĂğæŔŘå Ğ äżăäźĺæÿŕåŕŕæţńæăğ :in- description = elem.control('æŕŕè ř').inner_text WebPageåŠŇWebElementçśżæŔŘä ŻäžEèŕÿåd ŽWebçŻÿåĚşæŐěåŔč(ä ŃåęĆ ner_text)åŕŕåŕćèăčãăłqt4wãăńçžďæűğæąčãăć è ŕäżűæţńèŕţäÿ çžďåŕŕæţńæăğïijĺtestabilityïijl äÿăèĺňæÿŕæňğåŕźçşżçż çžďåŕŕæőğæăğãăaåŕŕèğćå åŕźæţńèŕţçžďåŕńåě çĺńåžęåšňçżÿåžťçžďæţńèŕţæĺřæijňãăćåěůä ŞåĹřiOS AppçŽĎUIèĞłåŁĺåŇŰæţŃèŕŢäÿ ïijňäÿżèęaä ŞçŐřåIJĺiOS AppèĞłèžńèąŇäÿžçŽĎçĺşåőŽæĂğäżěåŔŁæŐğäżűçŽĎåŔŕèŕEåĹńæĂğäÿŁãĂĆäÿŃéİć åřeäżőè Źäÿd äÿłçżt åžęæőćèőĺåęćä ŢæŔŘå ĞiOS AppçŽĎåŔŕæţŃæĂğãĂĆ åęćä ŢæŔŘå ĞiOS AppçŽĎåŔŕæţŃæĂğ ä Ůèŕİèŕt ïijňåůğåęğéž äÿžæůăçśşäźńçćłãăćuièğłåłĺåňűæţńèŕţåůěä IJäź æÿŕåřňæăůéaşçř EïijŇQT App æijňèžńåźűäÿ åěůåd ĞåŔŕæţŃæĂğïijŇéĆčæĹŚäżňäź å ĹéŽ éąžåĺl åijăåśţèğłåłĺåňűæţńèŕţåůěä IJ AppçŽĎåŔŕæţŃæĂğæŸ å Ůåřd äÿžéğ èęaãăć æőšéźd ios AppçŽĎåd ŰéČĺåźšæL řïijňæŕřå ĞèĞłèžńçŽĎçĺşåőŽæĂğ ios Appä IJäÿžUIèĞłåŁĺåŇŰçŽĎèćńæţŃåŕźèśąïijŇèĞłèžńèąŇäÿžçŽĎçĺşåőŽæĂğçŻt æőěåeşåőžäž EUIèĞłå æőšéźd åd ŰéČĺåŻăçt ăçžďåźšæl řãăćäÿńéićäżńçż äÿăäžżåÿÿçťĺçžďæŕřå ĞiOS AppèĞłåŁĺåŇŰçĺşåőŽæĂğçŽĎæŰźæşŢãĂĆ 1. åśŕèť Appäžd äžšäÿ çžďåźšæl řèąňäÿžãăćä ŃåęĆïijŽiOS Appä çťĺæţńèŕţåÿřåŕůæůűïijňåřőåŕřç ŰçŢěäijŽåIJĺäžd äžšè ĞçĺŃäÿ éćiåd ŰåĞžçŐřæţŃèŕŢåijźæąEæ åłąæijňèžńçžďåł èč çl źæăğïijňèăňäÿťçťĺä ŃèĎŽæIJňäÿ èğłåłĺåd ĎçŘEè Źçśżåijźæą Eäÿ çĺşåőžïijl æől èćńæţńappäÿ çžďæ d çśżåijźæąeïijżåŕźäžőios AppåŘŕåŁĺæŮűçŽĎæŐĺéĂAéĂŽç ěæőĺæičåijźæąe çžďåğžçőřè ĞæŮl åŕijèğt çžďæţńèŕţçťĺä Ńåd śèt ěãăć 1.5. è ŻéŸűæŇĞå Ů 36

2. åĺiåğńåňűçőŕåćčïijňä İèŕAæţŃèŕŢçŐŕåćČçŽĎäÿĂèĞt æăğãăćä ŃåęĆïijŽæÿĚçŘ EæţŃèŕŢåÿŘåŔů 3. çż äÿăéćďç őæiąäżűïijňä İèŕAäžd äžšçžďäÿăèğt æăğãăćä ŃåęĆïijŽæűL åŕłéăl åŕűæűğäżűçžďæ åijĺiosæţńèŕţæijžåźĺäÿłçžďåż åžşäÿ éćďç őçżÿåřňåř çğřçžďæűğäżűåd źåšňçżÿåřňæţřéğŕçžďç èŕaéăl åŕűæűğäżűçžďuiæş ä IJçŽĎäÿĂèĞt æăğåšňçĺşåőžæăğãăć 1.5. è ŻéŸűæŇĞå Ů 37

åĺiæőćaccessibilityïijňæŕřå ĞæŐğäżűçŽĎåŔŕèŕEåĹńæĂğ åŕźäžőios AppçŽĎçşżçż æţńèŕţåřňå ęïijňåd ğéč ç ěéaşvoiceoveréÿěèŕżåł èč åšň accessibility åś dæăğäźńéůt çžďæÿăåřďåěşçşżïijňä EæŸŕUIèĞłåŁĺåŇŰåŠŇaccessibility äźńéůt åŕĺæijl çiăæăőæăůçžďå ČäÿİäÿĞçijŢçŽĎèAŤçşżåŚćïij äÿńéićæĺśäżňäÿăèţůèţřè Żaccessibilit AppçŽĎæŐğäżűåŔŕèŕEåĹńæĂğçŽĎæIJL æţĺéăťå ĎãĂĆ 1.5. è ŻéŸűæŇĞå Ů 38

ios accessibilityçžďå žæijňäżńçż ios accessibilityçžďçżÿåěşåś dæăğçťśäÿd äÿłåÿÿèğaçžďå ŔèőőçżĎæĹŘïijĹUIAccessibility ProtocolåŠŇUIAccessibilityIdentification ProtocolïijL ïijň VoiceOverä çťĺäžeuiaccessibility ProtocolïijŇUIèĞłåŁĺåŇŰçŽĎæţŃèŕŢæąEæ dűuiautomationåĺźåřňæůűä çťĺäžeäÿd äÿłå ŔèőőïijŇåęĆäÿ è Źäÿd äÿłå ŔèőőåŇĚåŘńäžEaccessibilityå Ĺåd Žåś dæăğïijňèŕęèğa èńźæ dijåőÿæűźæňğå Ů ïijň è ŹéĞŇæĹŚäżňéĞ çćźäżńçż åšňuièğłåłĺåňűçżÿåěşçžďåżżäÿłåś dæăğ accessibilityidentifierïijĺèğłåłĺåňűçžďäÿşåś dæőğäżűåś dæăğïijňåŕźåžťuispyäÿ æőğäżűçžďname accessibilitylabelïijĺvoiceoveråšňèğłåłĺåňűåěňçťĺçžďæőğäżűåś dæăğïijňåŕźåžťuispyäÿ æőğäż accessibilityvalueïijĺvoiceoveråšňèğłåłĺåňűåěňçťĺçžďæőğäżűåś dæăğïijňåŕźåžťuispyäÿ æőğäż accessibilitytraitsïijĺvoiceoveråšňèğłåłĺåňűåěňçťĺçžďæőğäżűåś dæăğïijňåeşåőžuispyäÿ æőğäz åěűäÿ ïijňaccessibilityidentifieræÿŕä IJäÿžèŕEåĹńæŐğäżűçŽĎéęŰéĂL åś dæăğïijňåżăäÿžåőčæůćäÿ äijžå çžďåŕÿæżt åŕśçť åŕÿåňűïijĺçĺşåőžæăğè Čåě ïijl ïijżaccessibilitylabelçżt æőěåŕźåžťvoiceoverçžďæ äÿžæőğäżűèŕeåĺńçžďèąěåěěåś dæăğïijżaccessibilityvalueéăžåÿÿçťĺäžőå ŸæŤ åłĺæăaçžďå EĚåőźïijŇå åś dæăğéăžåÿÿæčěåeţäÿńäÿ çťĺå ŢçŃňèő ç őïijňéżÿèőd äijžåěşèaťäÿłäÿăäÿłæăğåğ EæŐğäżűçśżå dń åŕŕäżěèăčèźś èő ç őaccessibilitytraitsåś dæăğ ãăć ios accessibilityæijăä şåő dèůţ äÿńéićçżşåřĺåğăäÿłåěÿå dńåijžæźŕïijňçżźåğžæŕřå ĞæŐğäżűçŽĎåŔŕèŕEåĹńæĂğçŽĎæIJĂä şåő dèůţãă 1.5. è ŻéŸűæŇĞå Ů 39

æőğäżűçśżå dńäÿ èč åťŕäÿăæăğèŕeæőğäżű: QPath: /classname=âăÿuiawindowâăź/classname=âăÿuiabuttonâăÿ ãăřèğčåeşæűźæşţãăśios AppäżčçăAäÿ èő ç őæőğäżűçžďaccessibilityidentifieråś dæăğïijĺèğaäÿńåż ç cäżčçăaïijl ïijň çżşåřĺæőğäżűçśżå dńåšňæőğäżűnameåś dæăğä IJäÿžæŐğäżűçŽĎQPathãĂĆ customview.accessibilityidentifier = @"æřijçt ć"; èő ç őåřőçžďqpath: /classname=âăÿuiawindowâăź/ classname=âăÿuiabuttonâăÿ & name=âăÿæřijçt ćâăź æőğäżűçžďlabelåś dæăğåłĺæăaåŕÿåňű: QPath: /classname=âăÿuiawindowâăź/classname=âăÿuiatableviewâăź/ classname=âăÿuiatablecellâăź & label=âăÿåijăéăžäijžåśÿâăź /classname=âăÿuiawindowâăź/classname=âăÿuiatableviewâăź/ classname=âăÿuiatablecellâăź & label=âăÿæĺśçžďäijžåśÿâăź /classname=âăÿuiawindowâăź/classname=âăÿuiatableviewâăź/ classname=âăÿuiatablecellâăź & label=âăÿæĺśçžďèűěçžğäijžåśÿ' 1.5. è ŻéŸűæŇĞå Ů 40

ãăřèğčåeşæűźæşţãăśappäżčçă Aäÿ èő ç őæőğäżűçžďaccessibilityidentifieråś dæăğïijĺèő ç őæűźæşţåř 1.5. è ŻéŸűæŇĞå Ů 41

èő ç őåřőçžďqpath: /classname=âăÿuiawindowâăź/ classname=âăÿuiatableviewâăź/classname=âăÿuiatablecellâăź & name=âăÿäijžåśÿäÿ å ČâĂŹ åeěåţňwebviewïijĺh5éąţéićïijl çžďæőğäżűåęćä Ţèŕ EåĹń ãăřèğčåeşæűźæşţãăśçżőål UIèĞłåŁĺåŇŰæŔŘä ŻäžEäÿd çğ èŕeåĺńæl Ńæőţ 1. æÿăåřďäÿžnativeæőğäżűçžďæűźåijŕïijžæijl textæăğç çžďïijňaccessibilitylabelèğłåłĺçżğæl tex labelåś dæăğå şåŕŕãăć <div id="fkbx-hspch" tabindex="0" aria-label="æ čåijĺæťűåřň"></div> 2. QT4W(æ čåijĺåijăæžřäÿ )ïijžèő ç őwebviewéąţéićçžďæăğéćÿïijĺçąőä İåŤŕäÿĂæĂğïijL ïijňçťĺäžo çżijäÿłïijňæŕřå ĞiOSæŐğäżűçŽĎåŔŕèŕEåĹńæĂğçŽĎæIJĂä şåő dèůţäÿž: 1. äijÿåěĺèő ç őiosæőğäżűçžďaccessibilityidentifieråś dæăğïijĺæőğäżűidïijl ïijňåźűåřeåěűä IJäÿžQP 2. ios AppçŽĎUIäÿżçŢŇéİćçŽĎåĚěåŔčæŐğäżűæĹŰèĂĚéĂŽçŤĺæŐğäżűçŽĎaccessibilityIdentifieråś dæăğåř éğŕåżžåňűäÿńæiěïijňä İæŇAäÿ åŕÿïijňä ŃåęĆïijŽ iphoneqqäÿ çžďäijžåśÿåěěåŕčæőğäżűãăaaioäijžèŕiçłůåŕčçžďè ŤåŻ dæňl éšőç L ïijż 3. åŕźäžőhybrid App, äijÿåěĺèăčèźśéğğçťĺqt4wèŕeåĺńwebviewïijňä İèŕ AWebViewçŽĎæăĞéćŸåT çől è ňiosçžďéżśé ŤæşŢïijŇæŔ çğÿios AppæŐğäżűidèĞłåŁĺçŤ æĺřæűźæaĺ åijĺçe æćl äž EaccessibilityçŽĎæİěé ŹåŐżèĎL äźńåřőïijňæĺśäżňç ěé AŞåęĆä Ţç Aţæt żåijřçżźèćńæţńa äÿăäÿłäÿăäÿłæl ŃåůěæůżåŁăïijŇåijĂåŔŚèąĺçd žæůűéůt çt ğè ńïijňéÿ æćĺåśśåd ğãăćçl źåĺńæÿŕåŕźäžőä æijl æšąæijl äÿăæ džâăijéşűåijźâăiïijňåŕŕäżěå ńéă èąěåěĺè ŹäžŻæŐğäżűidåŚćïij ç ŤæąĹæŸŕèĆŕåőŽç ål Űæ dřæőğäżűidèğłåłĺçť æĺřåő çře è ŹéĞŇæL Ăèŕt çžďioséżśé ŤæşŢåřśæŸŕMethod SwizzlingïijŇåőČæŸŕåĹl çťĺobjective- CçŽĎè ŘèąŇæŮűçL źæăğïijňæťźåŕÿæĺűèăěæl l åśţåő æijl çžďåğ æţřåł èč ïijňåő dçőřåŕźåő æijl æőğäżűidèğłåłĺçť æĺřæ čæÿŕåĺl çťĺè ŹäÿłçL źæăğïijňåłĺæăaæż æ ćuiviewçśżçžďaccessibilityiden äÿńéićåěůä ŞäżŃçż Method SwizzlingçŽĎæŞ ä IJæ ěéłd ãăć åő dçőřæňğåőžåğ æţřçžďæl l åśţåł èč ïijĺèğłçťśåŕśæňěïijl - (void)swizzled_viewdidappear:(bool)animated { // èřčçťĺåő æűźæşţ [self swizzled_viewdidappear:animated]; // æ d åd Ďäÿ æÿŕéăšå ŠèřČçŤĺïijŇåIJĺè ŘèąŇæŮűäijŽèćńæŻ æ ćæĺřåő æűźæşţ // æl l åśţåł èč ïijňæ d åd ĎäżĚæL Şå řæůěå Ů NSLog(@"swizzled:%@",NSStringFromClass([self class])); } æż æ ćåő æijl åğ æţřïijĺæăğåğeæĺąæi ïijl 1.5. è ŻéŸűæŇĞå Ů 42

+ (void)swizzlemethods:(class)class originalselector:(sel)origsel swizzledselector:(sel)swizsel { Method origmethod = class_getinstancemethod(class, origsel); Method swizmethod = class_getinstancemethod(class, swizsel); BOOL didaddmethod = class_addmethod(class, origsel, method_ getimplementation(swizmethod), method_ gettypeencoding(swizmethod)); if (didaddmethod) { // åő æűźæşţäÿ å ŸåIJĺïijŇèĂŇæŸŕçżğæL äžęçĺűçśżçžďåő dçőřïijňåĺźåřęçĺűçśżçžďåő dçőř class_replacemethod(class, swizsel, method_ getimplementation(origmethod), method_ gettypeencoding(origmethod)); } else { //åő æűźæşţåůšå ŸåIJĺïijŇçŻt æőěäžd æ ćæűźæşţ method_exchangeimplementations(origmethod, swizmethod); } } åŕżæl æşĺåěěæůűæijžïijňåłăè æűřåł èč ïijĺloadæűźæşţåijĺçśżåłăè æůűäijžèćńèğłåłĺèřčçťĺä + (void)load { SEL origsel = @selector(viewdidappear:); SEL swizsel = @selector(swiz_viewdidappear:); static dispatch_once_t oncetoken; dispatch_once(&oncetoken, ^{ [UIViewController swizzlemethods:[self class] originalselector:origsel swizzledselector:swizsel]; }); } æżt åd ŽMethod SwizzlingèŕůåŔĆèĂČ è ŹéĞŇ äżńçż æőğäżűidçžďçť æĺřèğďåĺź éăžåÿÿæčěåeţäÿńïijňçťśäžőuiautomationåŕłåěşæşĺæőğäżűæăśäÿ çžďåŕűå ŘèŁĆçĆźåŕźåžŤçŽĎæŐğ åźűäÿ æÿŕäÿěæăijåŕźåžťäżčçăaäÿ UIæŐğäżű翪æ dďïijňèăňæÿŕäżčçăaäÿ æőğäżűæăśçžďçőăåňűçl Ĺ åŕijèğt æőğäżűæăśçžďè Ğåžęåž dåd ğïijňå śåş UIæŐğäżűçŽĎæ ěæl æţĺçőğïijňåęćäÿńåż æl Ăçd žã 1.5. è ŻéŸűæŇĞå Ů 43

åżăæ d ïijňéăl æńl åřĺéăćçžďidçť æĺřèğďåĺźåřśæÿ å Ůåřd äÿžéğ èęaïijňåěůä ŞèğĎåĹŹæŇL äijÿ 1. IdïijĹaccessibilityIdentifierïijL äÿ äÿžçl žïijňäź å şidåeěåőźåijĺäżčçă AåůšçżŔèő ç őïijňçżt æőěè Ťå 2. èńěidäÿžçl žïijňåĺźéăl æńl UIæŐğäżűåő dä ŃçŽĎåŔŸéĞŔåŘ ä IJäÿžæŐğäżűidïijŇåĚůä ŞèŐůåŔŰ - (NSString *)getvarnamewithinstance:(uiview *) instance { unsigned int numivars = 0; NSString *key=nil; Ivar * ivars = class_copyivarlist([self class], &numivars); for(int i = 0; i < numivars; i++) { Ivar thisivar = ivars[i]; const char *type = ivar_gettypeencoding(thisivar); NSString *stringtype = [NSString stringwithcstring:type encoding:nsutf8stringencoding]; if (![stringtype hasprefix:@"@"]) { // è Ğæżd æől éi docçśżå dń continue; } if ((object_getivar(self, thisivar) == instance)) { key = [NSString stringwithutf8string:ivar_ getname(thisivar)]; break; } } free(ivars); return key; } 1.5. è ŻéŸűæŇĞå Ů 44

accessibilityla- ãăřèŕt æÿőãăśéšĺåŕźuiimageviewïijňéijăèęaå ŢçŃňhook beläżěåő dçőřaccessibilityidentifieråś dæăğçžďèő ç őãăć 3. èńěæ ěéłd 2äÿ çžďuiæőğäżűçžďåő dä ŃåŔŸéĞŔåŘ äÿžçl žæůűïijňåŕŕäżěæ džäÿ äżěäÿńåÿÿçťĺu 1ïijL UILabelïijŽä çťĺtextä IJäÿžid 2ïijL UIButtonïijŽä çťĺtitlelabel.textä IJäÿžid 3ïijL UIImageViewïijŽä çťĺimageçžďæűğäżűåř ä IJäÿžidïijĹæ d åd ĎéIJĂèęAhook imageçžďåłăè åğ æţřïijl 4ïijL åěűäżűappèğłåőžäźl çžďuiæőğäżűå ĚèąěåĚĚ 1.5.5 æŕšæal çl źæăğ æŕšæąl çl źæăğæÿŕæňğéăžè ĞåŕźèćńæţŃAppæşĺåĚěäżčçăAïijŇæŔŘéńŸAppåŔŕæţŃæĂğçŽĎäÿĂçğ æű éiźæăaæŕšæąl ïijžåijĺåůšæijl çżőæăğappæžřçă AçŽĎåL æŕřäÿńïijňåłăåěěåő dçőřçžďframewo åłĺæăaæŕšæąl ïijžåijĺæšąæijl çżőæăğappæžřçă AçŽĎåL æŕřäÿńïijňéăžè ĞäÿĂ䞯æŁĂæIJŕæ è ŹæŸŕäÿĂçğ ä ţåěěåijŕèğłåłĺåňűæţńèŕţæűźæąĺïijňä çťĺåřĺéăćïijňåŕŕäżěèőůå ŮçŘEæČşçŽĎæŢ çżőål ïijňqt4iåijĺ qt4i.device.device äÿ æŕřä ŻéĂŽçŤĺæąl çžďèřčçťĺæőěåŕč: call_qt4i_stub(method, params, clazz=none) '''QT4i StubéĂŽçŤĺæŐěåŔč :param method: åğ æţřåř :type method: str :param params: åğ æţřåŕćæţř :type params: list :param clazz: çśżåř :type clazz: str :return: æŕšæąl æőěåŕčè ŤåŻ dåăij :rtype: str ''' åžťçťĺåijžæźŕ QT4iæŸŕå žäžőappleåőÿæűźæŕřä ŻçŽĎXCTestæąEæ dűåő dçőřçžďïijňåŕůéźřäžőxcteståšňèćńæţńa èăňæŕšæąl çžďæţńèŕţæűźæąĺå Ĺåě çžďåijěèąěäžexctestçžďäÿ èűşïijňåżăäÿžæŕšæąl ä İèŕAäž EæţŃ äÿńéićåĺůäÿ åğžåğăçğ æŕšæąl åijĺqt4ièğłåłĺåňűæţńèŕţçžďåěÿå dńåžťçťĺïijž appçžďæšźçżšèő éůőïijžèŕżåŕűæšźçżšçżőå ŢïijŇ æÿěéźd çźżå ŢæĂAæŰĞäżűïijŻ(åŕźæŕŤåĹl çť èő éůőçşżçż çżÿåeňïijžäÿłäijăåż çl ĞïijŇæŕŤåŕźåŻ çl ĞïijŻ(獜äžŐçşżçż çżÿå EŇäÿ çžďåż çl èőůåŕűèğłåłĺåňűæţńèŕţèţďæžřïijż(è ňåęćèğłåłĺåňűçťĺä ŃéIJĂèęAäÿĂ䞯æŕŤè Čåd ğçžďèğe åłĺæăaä őæťźå ŞåL çłůåŕčæ ŘæŐğäżűçŽĎåś dæăğïijż 1.5. è ŻéŸűæŇĞå Ů 45

èŕżåŕűå ŞåL çłůåŕčæőğäżűçžďèŕęçżeæţřæ őïijż åęćä ŢæL l åśţqt4iéăžçťĺæal äÿłåż æÿŕåęćä ŢæL l åśţqt4iéăžçťĺæąl ïijňåő dçőřèřčçťĺappè ŻçĺŃåEĚæŰźæşŢçŽĎæţ AçĺŃåŻ ãăćäÿ qt4i.device.device.download_file äÿ ïijňå žäžőéăžçťĺæąl æőěåŕčåő dçőřçžďåd ğæűğäżűä 1 ãăaæl l åśţqt4istubæűźæşţ, åijĺqt4istubåůěçĺńçżőå ŢäÿŃQT4iManager.mæŰĞäżűäÿ åő dçőřåęćäÿn - (BOOL) createfile:(nsstring *)filename withpath:(nsstring *)path size:(nsinteger)size {...åő dçőřæűğäżűäÿńè éăżè Ś... } åřeæl l åśţåřőçžďqt4istubåĺűä IJæĹŘframeworkïijŇä åŕŕäżěåijăåğńæŕšæąl äž EãĂĆ 2ãĂAåŕźçŻőæăĞAppè ŻèąŇæŔŠæąl ïijňæňl éijăåĺ EäÿžéİŹæĂ AæŔŠæąl åšňåłĺæă AæŔŠæąl ãăć éiźæăaæŕšæąl åřeäÿłè řæl l åśţåřőçžďframeworkçżt æőěåłăåěěappæžřçă Aäÿ ïijňåřňæůűéijăèęaåijĺappåřŕåłĺèřc #import <QT4iStub/QT4iStub.h> @implementation AppDelegate - (BOOL)application:(UIApplication *)application didfinishlaunchingwithoptions:(nsdictionary *)launchoptions { ViewController * vc = [[ViewController alloc] init];...... [self.window makekeyandvisible]; [[QT4iManager sharedmanager] startexplorer]; // éijăèęąåłăåěěçžďäżčçăą return YES; } åšňappæžřçăaäÿăèţůçijűèŕśå şåŕŕãăć åłĺæăaæŕšæąl 1.5. è ŻéŸűæŇĞå Ů 46

çťśäÿłéićåŕŕç ěåłĺæăaæŕšæąl ïijňæÿŕéšĺåŕźæšąæijl æžřçă AçŽĎæČĚå EţïijŇéĂŽè ĞåůěåĚůçŤ æĺřd åłăåěěäÿłè řæl l åśţåřőçžďframeworkïijňåĺűä IJdylib æşĺåěěçżőæăğappïijňä İèŕAçŻőæăĞåŘŕåŁĺæŮűäijŽåŁăè hookçžďåłĺæă AåžŞ éğ ç åř çżőæăğappïijňä İèŕAä őæťźåřőçžďappèč åijĺéi dèűłçńśçžďæl ŃæIJžäÿŁèČ åől èčěå åijĺæŕšæąl åő çřeäÿ äijžåŕźåłĺæăaæŕšæąl å AŽèŕęçż Eèŕt æÿőãăć 3ãĂAéĂŽè ĞåIJĺçŤĺä Ńäÿ èřčçťĺqt4iæŕřä ŻçŽĎéĂŽçŤĺæąl èřčçťĺæőěåŕčïijĺçąőä İäijăåĚěæŰźæşŢåŘ StubæL l åśţçžďæűźæşţ: def download_file(self, file_url, dst_path): '''äżőç ŚäÿŁäÿŃè æňğåőžæűğäżűåĺřæijňåijř :param file_url: æűğäżűçžďurlèůŕå ĎïijŇæŤŕæŇĄhttpåŠŇhttpsèůŕå Ď, éijăèęąåŕźappæŕšæąl :type file_url: str :param dst_path: æűğäżűåijĺæl ŃæIJžäÿŁçŽĎå ŸåĆĺèůŕå ĎïijŇä ŃåęĆïijŽ/Documents :type dst_path: str ''' method = 'createfile:withpath:size:' params = [file_url, dst_path, 1] self.call_qt4i_stub(method, params) æşĺèğč: QT4i StubæŸŕåŔŕæL l åśţçžďïijňåŕłéijăæňl çěğäÿłè řæţaçĺńïijňåő dçőřæl ĂéIJĂæŰźæşŢïijŇ 1.5. è ŻéŸűæŇĞå Ů 47

æŕšæal åő çř E æijăåřőïijňäżńçż QT4iéĂŽçŤĺæŔŠæąl çžďåő dçőřåő çřeïijňæţ AçĺŃåŻ åęćäÿńïijž QT4iæąEæ dűèő èőąèğłäÿłèăňäÿńæÿŕapiåśćãăadriveråśćåšňdeviceåść: éšĺåŕźæŕšæąl ïijňåijĺapiåśćæŕřä Żcall_qt4i_stubæŰźæşŢïijŇäijăåĚěåŔĆæŢřåŠŇæŰźæşŢåŘ æĺűçśżåř åijĺiosèő åd ĞäÿŁïijŇXctestAgentä IJäÿžclientçńŕïijŇåřEä ąæ AŕåŔŚéĂ A翏APPåŁăè æůűåřŕåłĺçžďqt ServerçńŕïijŇäżŐèĂŇè åĺřèřčçťĺappè ŻçĺŃåEĚçŽĎæŰźæşŢçŽĎçŻőçŽĎãĂĆ è ŹéĞŇïijŇçİĂéĞ äżńçż äÿńåłĺæăaæŕšæąl åő çř EïijŇäżěäÿŁèŁĆæL l åśţéăžçťĺæąl äÿžä Ń: âśă éęűåěĺïijňéăžè ĞåůěåĚůãĂŁtheosãĂŃæĹŰãĂŁMonkeyDevãĂŃåĹŻåżžiOS tweakåůěçĺńïijňäżětheosäÿžä ŃïijŽ 1.5. è ŻéŸűæŇĞå Ů 48

æşĺèğč: ä Ţäÿžtweak? Tweakåő dèt ĺäÿłæÿŕiosåźşåŕřçžďåłĺæăaåžşïijňäżědylibè Źçğ å ćåijŕå ŸåIJĺïij äÿńçžď.dllïijňlinux äÿńçžď.soãăćäÿőéiźæăaåžşçżÿåŕ ïijňåłĺæăaåžşåijĺçijűèŕśæůűåźűäÿ äijžèćń çďűåřőïijňåřeæl l åśţçžďqt4istub frameworkåłăåěěåĺřäÿłåż çť æĺřçžďtweakåůěçĺńäÿ çžďïijňæl çąőä İappåŘŕåŁĺæŮűïijŇåŘŕåŁĺæŔŠæąl çžďserver: #import <QT4iStub/QT4iStub.h> #import <objc/runtime.h> attribute ((constructor)) static void entry() { NSLog(@"QT4iManager starting..."); [[QT4iManager sharedmanager] startexplorer]; } åęćæ dijéijăèęahookæžřçă Aäÿ çžďæ ŘäÿłæŰźæşŢïijŇåŔŕäżěä çťĺtheosæŕřä ŻçŽĎäÿĂåěŮãĂŁLogos %hook AppDelegate // Hooking an instance method with an argument. - (void)applicationdidenterbackground:(uiapplication *)application { NSLog(@"App entered background!!!"); %orig; // Call through to the original function with its original arguments. } %end åŕłéijăçżt æőěåijĺtweakåůěçĺńäÿńéićmakeäÿăäÿńïijňä åŕŕäżěçť æĺřæl ĂéIJĂçŽĎdylibæŰĞäżűçŽĎ æşĺèğč: ä ŢäÿžLogosïij åijĺlogosåś äżd èčňåřőïijňtheosåőžäźl äžeäÿăçşżåĺůçžďåőŕåšňåğ æţřïijňå cçžďruntimeçl źæăğæiěæż æ ćçşżçż æĺűèăěçżőæăğappçžďåğ æţř(method Swizzling)ïijŇäżŐèĂŇåő dçőřåŕźçżőæăğappçžďhookãăć âśą äÿžäžeä İèŕ AçŻőæăĞappè ŘèąŇæŮűåŁăè çť æĺřçžďdylibïijňå Ěéążä İèŕ Aappäÿ å ŸåĆĺæIJL æň åijĺä őæťźäźńål ïijňåěĺäžeèğčäÿńiosäÿ Mach-OåŔŕæL ğèąňæűğäżűçžďæăijåijŕïijňåęćåż : 1.5. è ŻéŸűæŇĞå Ů 49

Mach-Oåd t éčĺïijĺmach headerïijl :æŕŕè řäžemach- OçŽĎcpuæ dűæ dďãăaæűğäżűçśżå dńäżěåŕłåłăè åś äżd ç L ä ąæaŕãăć åłăè åś äżd ïijĺload commandïijl :æŕŕè řäžeæűğäżűäÿ æţřæ őçžďåěůä ŞçżĎçżĞ翪æ dďïijňäÿ Data: Dataäÿ çžďæŕŕäÿłæőţïijĺsegmentïijl çžďæţřæ őéč ä İå ŸåIJĺè ŹéĞŇïijŇæőţçŽĎæęĆå ţäÿo äžeèğčäž EMach-OæŰĞäżűæăijåijŔåŘŐïijŇä æÿőçź æĺśäżňåŕłéijăåijĺçżőæăğappçžďåŕŕæl ğèąňæűg CommandéČĺåĹEæůżåŁăäÿĂäÿłåŁăè åś äżd LC_LOAD_DYLIBæŇĞåŘŚçŤ æĺřçžďdylibïijňä åŕŕäżěä âść æijăåřőä çťĺèŕaäźęåŕźäÿłè řæűğäżűè ŻèąŇéĞ ç åř åřśåŕŕäżěäžeïijňéğ ç åř åůěåěůå Ĺåd Ž app-signerãăńæş ä IJæ ěéłd åęćäÿńïijž ä çťĺcodesign -fs +èŕaäźę + dylibåś äżd ïijňåŕźçť æĺřdylibè ŻèąŇéĞ ç åř ïijż 1.5. è ŻéŸűæŇĞå Ů 50

åřeéğ ç åř åřőçžďdylibæť åěěçżőæăğappèğčåőńåřőçžďpayload/appåř çžďçżőå ŢäÿŃïijŻ ä çťĺéğ ç åř åůěåěůïijňåŕźæţt äÿłåől èčěåňěä çťĺæijl æţĺçžďèŕaäźęéğ ç åř ïijż è ęåśł: éğ ç åř èŕaäźęäÿăåőžèę Aä çťĺèłśéšśäźřçžďäÿłäžžåijăåŕśèăěèŕ AäźęæĹŰèĂĚäij AäÿŽèŕA 1.6 Q&A èőřå ŢQT4iä çťĺäÿ çžďåÿÿèğaéůőéćÿåŕłèğčå EşæŰźæąĹãĂĆ 1.6.1 åől èčěqt4iæłěéťź åől èčěqt4iæůűïijňäijžåől èčěä İèţŰpymobiledevice-qtaïijŇèŕěåŇĚçŽĎåőL èčěäijžä İèţŰäžŐM2CryptoåŁ éčĺåĺemacosåijĺçijűèŕśåől èčěm2cryptoåžşæůűïijňåŕŕèč äijžæłěåęćäÿńäÿd çğ éťźèŕŕ: è ŹæŸŕåŻăäÿžM2CryptoåžŞçijŰèŕŚåőL èčěæůűïijňä İèţŰäžŐçşżçż CçŐŕåćČçŽĎèůŕå ĎåŠŇçL ĹæIJňäÿ å 1.6. Q&A 51

1.6.2 æl ŃæIJžçşżçż åijźæa E åřŕåłĺappåd śèt ěïijňæłěåśłäÿ æÿ çd žéťźèŕŕåăeæăĺ: Fault: <Fault 1: <type 'exceptions.exception'>:devicedisabled> æ ěçijńæĺłåż 1.6. Q&A 52

QT4i Documentation, år S åÿc 3.3 èg c åes æ U z æs T : äžžåu e çc z åg z æn L éšo âa IJåe âa I ïijn åe s éu åijz æae 1.6.3 ç S çz IJéU o éc Ÿ çt l ä N çz z å T åd s èt e 1.6. Q&A 53

èğčåeşæűźæşţ: æčăæ ěæl ŃæIJžWiFiè dæőěæÿŕåřęæ čåÿÿïijňåęćæ dijæijłè dæőěç ŚçżIJïijŇéIJĂèęAæL ŃåŁĺéĞ è dã 1.6.4 Macèğčæ dřhostnameåijćåÿÿ è ŘèąŇåĞžçŐřäżěäÿŃ鍏èŕŕ: 1.6. Q&A 54

èğčåeşæűźæşţ: æ ěçijń çşżçż åaŕåě èő ç ő->åěśäžń->çťţèďśåř çğřïijňä İèŕAâĂIJçŤţèĎŚåŘ çğřâăiäÿőhostnam æűźæşţäÿăïijž åijĺçżĺçńŕè ŘèąŇåęĆäÿŃåŚ äżd :ïijĺåěűäÿ newname.localæż æ ćæĺřçşżçż åaŕåě èő ç ő- >åěśäžńæ ěåĺřçžďåęćäÿłåż æl Ăçd žåeěåőźïijl $ sudo scutil --set HostName newname.local ïijĺæűźæşţäÿăæl ğèąňåőňéťźèŕŕäż åijĺä çťĺæűźæşţäžňïijl æűźæşţäžňïijž 1.6. Q&A 55

ål å ĂMacintosh HD -> Library/èţĎæžŘåžŞ -> Preferences -> SystemConfigurationïijŇåĹăéŹd äżěäÿńæűğäżű: com.apple.airport.preferences.plist NetworkInterfaces.plist Preferences.plist éğ åřŕèőąçőůæijž 1.6.5 çńŕåŕčèćńå ăçťĺåijćåÿÿ æijňåijřèřčèŕţçťĺä ŃæŮűïijŇåĞžçŐřAddress already in useåijćåÿÿ: File "build/bdist.macosx-10.13-intel/egg/qt4i/driver/rpc.py ", line 41, in call return self.method. get (self.instance, self. owner)(*args, **kwargs) File "build/bdist.macosx-10.13-intel/egg/qt4i/driver/xctest/ wda.py", line 95, in dismiss_alert self.agent.execute(command.qta_alert_dismiss, env) File "build/bdist.macosx-10.13-intel/egg/qt4i/driver/xctest/ wda.py", line 69, in get val = self.func(instance) File "build/bdist.macosx-10.13-intel/egg/qt4i/driver/xctest/ wda.py", line 108, in agent return self.agent_manager.get_agent(self.udid) File "build/bdist.macosx-10.13-intel/egg/qt4i/driver/xctest/ agent.py", line 125, in get_agent return self.start_agent(device_id) File "build/bdist.macosx-10.13-intel/egg/qt4i/driver/xctest/ agent.py", line 91, in start_agent self._agents[device_id] = XCUITestAgent(device_id, server_ ip, server_port, keep_alive, retry, timeout) File "build/bdist.macosx-10.13-intel/egg/qt4i/driver/xctest/ agent.py", line 189, in init self.start(retry, timeout) (continues on next page) 1.6. Q&A 56

(çż äÿłéąţ) File "build/bdist.macosx-10.13-intel/egg/qt4i/driver/xctest/ agent.py", line 287, in start self._tcp_relay() File "build/bdist.macosx-10.13-intel/egg/qt4i/driver/xctest/ agent.py", line 205, in _tcp_relay raise self._relay_error error: [Errno 48] Address already in use èğčåeşæűźæşţ ïijž âśăåŕŕéăžè ĞåŚ äżd æ ěçijń8100çńŕåŕčèćńåşłäÿłè ŻçĺŃå ăçťĺ: $ lsof -i :8100 âśąæăźæ őè ŻçĺŃPID ïijňkillæől å ăçťĺè ŻçĺŃ: $ kill -9 ïijĺè ŻçĺŃPIDïijL âśćéğ æűřèůśçťĺä Ńå şåŕŕãăć 1.6.6 UISpyè dæőěåd śèt ěæłěéťź æl ŞåijĂUISpyïijŇçĆźåĞżè dæőěïijňæłěéťź: File "build/bdist.macosx-10.13-intel/egg/qt4i/driver/rpc.py", line 64, in _dispatch return m(*params) File "build/bdist.macosx-10.13-intel/egg/qt4i/driver/rpc.py", line 41, in call return self.method. get (self.instance, self.owner)(*args, ** kwargs) File "build/bdist.macosx-10.13-intel/egg/qt4i/driver/host.py", line 65, in list_devices return DT().get_devices() File "build\bdist.win32\egg\testbase\util.py", line 158, in call File "build/bdist.macosx-10.13-intel/egg/qt4i/driver/tools/dt.py", line 77, in init self.xcode_version = DT.get_xcode_version() File "build/bdist.macosx-10.13-intel/egg/qt4i/driver/tools/dt.py", line 96, in get_xcode_version raise Exception('get_xcode_version error:%s' % e.output) Exception: get_xcode_version error:xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/ Library/Developer/CommandLineTools' is a command line tools instance åś äżd èąňäÿ åŕŕæ ěçijńçşżçż éżÿèőd XCodeåőL èčěèůŕå Ď: 1.6. Q&A 57

$ xcode-select -p /Library/Developer/CommandLineTools æ čåÿÿçžďxcodeèůŕå ĎåžŤèŕěæŸŕ: /Applications/Xcode.app/Contents/Developer èğčåeşåł dæşţ: ä çťĺåęćäÿńåś äżd åĺğæ ćxcodeäÿžæ čçąőèůŕå ĎïijŽ: $ sudo xcode-select -s +Xcodeèůŕå Ď ïijĺåd ĞæşĺïijŽXcodeèůŕå ĎåŔŕäżěåřĘxcodeçŻt æőěæńűåěěterminalçżĺçńŕïijl åĺğæ ćåőňäźńåřőïijňåŕŕäżěéăžè ĞåŚ äżd çąőèőd : $ xcode-select -p 1.6.7 çčaçżÿçl žéůt äÿ èűş Xcodeè ŘèąŇäijŽäžğçŤ åd ğéğŕæůěå ŮæŰĞäżűïijŇåŕijèĞt MacæIJžåŹĺçčAçŻŸçl žéůt äÿ èűş: åś äżd èąňïijňè ŻåĚěXcodeçŽĎçijŞå ŸçŻőå ŢDerivedData: $ cd ~/Library/Developer/Xcode/DerivedData/ åŕŕäżěçijńåĺřèŕěçżőå ŢäÿŃæIJL äÿăäÿłäżěâăijxctestagentâăiåijăåd t çžďçżőå ŢïijŇåŘŐçijĂæŸŕéŽŔ çżt æőěåĺăéźd èŕěçżőå ŢäÿŃçŽĎå ŘçŻőå Ţ/Logs/TestäÿŃçŽĎåĚĺéČĺæŰĞäżű: 1.6. Q&A 58

1.6.8 çťśäžőä aäżżæűğäżűéůőéćÿåŕijèğt çžďæl ŃæIJžåőL èčěéťźèŕŕ ä çťĺqt4içžďinstallæőěåŕčåől èčěappæłěéťźïijňæůěå ŮåăEæăĹåęĆäÿŃ: è ŹæŸŕåŻăäÿžiPhoneæL ŃæIJžä ąäżżmacåřőåijĺæijňåijřçijşå ŸçŽĎåŕEéŠěåŕźåd śæţĺïijňæl Ăäżěèę AéG $ cd ~/.pymobiledevice/ æÿěçřeçżőå ŢäÿŃçŽĎæL ĂæIJL æűğäżű: éğ æűřæŕšæńťæl ŃæIJžïijŇäijŽåijźåĞžä ąäżżåijźæąeïijňéăl æńl âăijä ąäżżâăi: 1.6. Q&A 59

1.6.9 åęćä ŢéŸżæ ćiosèő åd ĞçŽĎçşżçż å ĞçžğåijźçłŮ iosèő åd ĞçŽĎçşżçż å ĞçžğåijźçłŮéćŚçźAåĞžçŐřäijŽå śåş èğłåłĺåňűäżżåłąïijňåęćä ŢåIJĺäÿ å Ğçžğç 1ãĂAåIJĺæL ŃæIJžäÿŁæL ŞåijĂsafariïijŇåIJřåİĂæăŔè ŞåĚě: https://beta.thuthuatios.com/tvos12/tvos_12_beta_profile. mobileconfig 2ãĂAåŻ dè ęäźńåřőæňl çěğèęaæśćåől èčěæ d provisionæűğäżűå şåŕŕïijňæijăåřőéğ åřŕæl ŃæIJžå 1.6.10 XCTestAgentçijŰèŕŚæŁě鍏 çťśäžőusbæŕšåŕčéůőéćÿïijňåŕijèğt è dæőěéăžéaşèŕůæśćèćńæńšçżiïijňåŕŕäżěéăžè ĞæŻt æ ćusb 1.6.11 UISpyæĹŰèĂĚEclipseåőL èčěæl ŞåijĂæŁě鍏 èńěå ŞåL Macçşżçż äÿž10.12åŕłäżěäÿłçl ĹæIJňïijŇåĹŹéęŰæňąæIJL åŕŕèč åğžçőřæ Ř䞯åőL èčěåňě éijăèęaåd ğåőűæl ŞåijĂâĂIJåĚ Aèőÿäżżä ŢæİěæžŘâĂİæŰźåŔŕåőL èčěïijňåěůä Şæ ěéłd åęćäÿńïijž 1.6. Q&A 60

æl ŞåijĂåŚ äżd èąňçżĺçńŕâăťâăťspotlightæřijçt ć(å ńæ ůéťőïijžcommand+çl žæăijæĺűåŕşäÿłèğ è ŞåĚěåŚ äżd ïijňåż dè ęåřőè ŞåĚěä ăçžďmacçťţèďśåŕeçă A: sudo spctl --master-disable åż dåĺřçşżçż åaŕåě èő ç őçžďâăijåől åěĺäÿőéžřçğ AâĂİïijŇåŃ éăl âăijåě Aèőÿäżżä ŢæİěæžŘâA 1.6. Q&A 61

åęćæ dijäżěäÿłæ ěéłd ä İæŮğäÿ èąňïijňèŕůåřeappçğżåĺř çżőå ŢãĂĆ âăij/applicationsâăi 1.6. Q&A 62

CHAPTER 2 æőěåŕčæűğæač 2.1 æőěåŕčæűğæač 2.1.1 qt4i.app Package ios App class qt4i.app.app(device, bundle_id, trace_template=none, trace_output=none, **params) å žçśżïijžobject ios Appå žçśż add_rule_of_alert_auto_handle(message_text, button_text) èğłåłĺåd ĎçŘEAlertèğĎåĹŹïijŇæŰřåć däÿăéąź åŕćæţř message_text (str) AlertåEĚæŰĞæIJňçL ĞæőţïijŇæŤŕæŇ Aæ čåĺźèąĺè åijŕï button_text (str) AlertåEĚæŇL éšőçžďæűğæijňïijňæťŕæň Aæ čåĺźèąĺè å device è ŤåŻ dappæl ĂåIJĺçŽĎèő åd Ğ è ŤåŻ dçśżå dń qt4i.device.device driver è ŤåŻ dappæl Ăä çťĺçžďdriver è ŤåŻ dçśżå dń RPCClientProxy flag_alert_auto_handled èğłåłĺåěşéů AlertæąE :rtype: boolean 63

get_text(text) èőůåŕűtextåŕźåžťçžďæijňåijřèŕ èĺăæűğæijň åŕćæţř text (str) æăğåğeæűğæijňïijňäÿ éžŕèŕ èĺăçőŕåćčåŕśçť åŕÿåňűçžďå è ŤåŻ d str - æijňåijřèŕ èĺăçžďæűğ language appçžďå ŞåL èŕ èĺă release() çżĺæ ćapp è ŤåŻ dçśżå dń str rules_of_alert_auto_handle èőůåŕűåůšèő ç őçžďèğłåłĺåd ĎçŘEAlertèğĎåĹŹ start() åřŕåłĺapp è ŤåŻ dçśżå dń list - [ {âăijmessage_textâăi: âăijmessage_textâăi, âăijbutton_textâăi: âăijbutton_textâăi},.. ] class qt4i.app.nlctype å žçśżïijžobject æĺąæń åijśç ŚçżIJçśżå dń class qt4i.app.preferences(device) å žçśżïijžqt4i.app.app çşżçż app èő ç ő reset_host_proxy() åěşéů hostäżčçře set_host_proxy(server, port, wifi_name) èő ç őhostäżčçře åŕćæţř server (str) æij åłąåźĺåř port (int) çńŕåŕčåŕů wifi (str) wifiåř switch_network(network_type, nlc_type= None, timeout=1) ç ŚçżIJåĹĞæ ć åŕćæţř network_type (int) ç ŚçżIJçśżå dńïijňåęćäÿńïijž 0:æŮăWIFIæŮă4G 1:æŮăWIFiæIJL 4G 2:æIJL WIFIæŮă4G 3:æIJL WIFIæIJL 4G 4:éč dèąňæĺąåijŕ 5:ä İæŇAäÿ åŕÿ,äżěèő ç őåijśç Ś nlc_type (NLCType) æĺąæń åijśç ŚçżIJçśżå dń 2.1. æőěåŕčæűğæač 64

class qt4i.app.safari(device=none, url_scheme=false) å žçśżïijžqt4i.app.app SafariæţŔèğĹåŹĺ find_by_url(url, page_cls=none, timeout=10) åijĺå ŞåL æl ŞåijĂçŽĎéąţéİćäÿ æ ěæl æňğåőžurl,è ŤåŻ dwebpageåő dä ŃïijŇåęĆæ dijæijłæ åŕćæţř url (str) èęaæ ěæl çžďéąţéićurl page_cls (qt4w.webcontrols. WebPage) çťĺæĺůåő dçőřçžďweb- Pageå ŘçśżïijŇéżŸèőd äÿ åąńåeźåĺźä çťĺå žçśżwebpage timeout (int/float) æ ěæl èűěæůűæůűéůt ïijňå Ţä ïijžçğš è ŤåŻ dçśżå dń qt4w.webcontrols.webpage open_url(url, page_cls=none) æl ŞåijĂSafariæţŔèğĹåŹĺïijŇèůşè ňæňğåőžç ŚïijŇè ŤåŻ dpage_clsçśżçžďåő dä Ń åŕćæţř url (str) urlåijřåiă page_cls (qt4w.webcontrols. WebPage) çťĺæĺůåő dçőřçžďweb- Pageå ŘçśżïijŇéżŸèőd äÿ åąńåeźåĺźä çťĺå žçśżwebpage è ŤåŻ dçśżå dń qt4w.webcontrols.webpage 2.1.2 qt4i.device Package iosèő åd ĞæĺąåİŮ class qt4i.device.device(attrs={}, devicemanager=none) å žçśżïijžobject iosèő åd Ğå žçśżïijĺåňěåřńå žäžőèő åd ĞçŽĎUIæŞ ä IJæŐěåŔčïijL call_qt4i_stub(method, params, clazz=none) QT4i StubéĂŽçŤĺæŐěåŔč åŕćæţř method (str) åğ æţřåř params (list) åğ æţřåŕćæţř clazz (str) çśżåř è ŤåŻ d æŕšæąl æőěåŕčè ŤåŻ dåăij è ŤåŻ dçśżå dń str 2.1. æőěåŕčæűğæač 65