วิธีการปลอมเหตุการณ์สัมผัสโดยทางโปรแกรมให้เป็น UIButton อย่างไร


183

ฉันกำลังเขียนการทดสอบหน่วยและเนื่องจากลักษณะของแอพนี้โดยเฉพาะจึงเป็นสิ่งสำคัญที่ฉันจะต้องเพิ่มUIสายโซ่ให้สูงที่สุดเท่าที่จะทำได้ GUIดังนั้นสิ่งที่ผมอยากจะทำคือการเขียนโปรแกรมเรียกปุ่มกดเช่นถ้าผู้ใช้มีการกดปุ่มที่

(ใช่ใช่ - ฉันสามารถโทรหาIBActionตัวเลือกได้ แต่ธรรมชาติของแอพนี้ทำให้ฉันต้องกดปุ่มจริงตามที่IBActionตัวเองเรียกว่าปุ่ม)

วิธีที่ต้องการในการทำเช่นนี้คืออะไร?


คุณช่วยอธิบายได้ไหมว่าทำไมจึงเป็นเรื่องสำคัญที่คุณจะต้องปลอมแปลงปุ่มสัมผัสแทนที่จะเรียกวิธีการกระทำโดยตรง ไม่มีความแตกต่างในทางปฏิบัติจริงๆ
Jasarien

1
@ Jasarien: ดีเพราะมีความแตกต่าง! ;) ในแอพของฉันมีหลายปุ่มที่ใช้วิธีการกระทำที่เหมือนกันและวิธีการแยกวิเคราะห์วิธีการทำงานตามแท็กของปุ่ม ดังนั้นการทดสอบหน่วยนอกเหนือจากการทดสอบหนึ่งรหัสพา ธ ผ่านวิธีการ (a) จำเป็นต้องทดสอบพวกเขาทั้งหมดและ (b) ยังตรวจสอบว่าปุ่มนั้นถูกต่อสายอย่างถูกต้องแล้ว นอกจากนี้มันเป็นนามธรรมของชุดทดสอบหน่วยของฉันเนื่องจากฉันสามารถกำหนดการทดสอบหน่วยเป็นบรรทัดในไฟล์ข้อความที่มีลักษณะดังนี้: "1 + 2 = 3" โดยที่ "3" เป็นจุดสิ้นสุดการแสดงที่คาดไว้และทุกอย่างก่อนหน้านี้ เป็นปุ่มที่จะผลัก
Olie

วิธีการกระทำของคุณไม่มีพารามิเตอร์ผู้ส่ง (id) หรือไม่ คุณไม่สามารถเรียกวิธีการและส่งปุ่มเป็นผู้ส่งได้หรือไม่
Jasarien

3
เนื่องจากธรรมชาติที่เป็นนามธรรมของชุดทดสอบของฉันฉันไม่ทราบวิธีที่จำเป็นต้องเรียกใช้สำหรับปุ่มเฉพาะ ฉันคิดว่าฉันสามารถขุดลงในปุ่มและรับมันได้ แต่การทำ sendActionsForControlEvents: ทำสิ่งนี้ให้ฉันทั้งหมดโดยมีโอกาสน้อยกว่าสำหรับข้อผิดพลาดและเก็บบทคัดย่อการทดสอบและปรับให้เข้ากับการออกแบบ
Olie

คำตอบ:


459

ปรากฎว่า

[buttonObj sendActionsForControlEvents: UIControlEventTouchUpInside];

ทำให้ฉันได้สิ่งที่ฉันต้องการในกรณีนี้

แก้ไข:อย่าลืมทำในหัวข้อหลักเพื่อให้ได้ผลลัพธ์ที่คล้ายกับผู้ใช้กด


สำหรับ Swift 3:

buttonObj.sendActions(for: .touchUpInside)


ซึ่งไม่แตกต่างจากการโทร [myController myActionMethod:myButton1];
Jasarien

11
คุณมีความยับยั้งชั่งใจอย่างมากในการตอบความคิดเห็นของคุณ;)
Dan Rosenstark

@Jariarien นั้นแตกต่างกันมากเนื่องจากจะส่งเหตุการณ์การสัมผัสไปยังเป้าหมายที่ลงทะเบียนไว้ทั้งหมด (ผู้ฟัง)
htafoya

2
น่าเสียดายที่สิ่งเหล่านี้ไม่ได้ผลเสมอไป - พวกเขาพึ่งพาผู้รับเป็น UIControl มากกว่าที่จะมีท่าทางแตะ
เครื่องมือ

1
@ChenLiYong เหตุผลหนึ่งก็คือถ้าmyActionMethod:ไม่ใช่สาธารณะดังนั้นคุณจึงไม่สามารถเรียกได้โดยตรง
Iulian Onofrei

50

การอัปเดตคำตอบนี้สำหรับ Swift

buttonObj.sendActionsForControlEvents(.TouchUpInside)

แก้ไข : อัปเดตสำหรับ Swift 3

buttonObj.sendActions(for: .touchUpInside)

1
ฉันจะบอกว่า: buttonObj.sendActionsForControlEvents (.TouchUpInside) เป็นสไตล์ที่รวดเร็วยิ่งขึ้น;)
Sajjon

1
ฉันไม่คิดว่ามันจะใช้งานได้ถ้าปุ่มถูกสร้างขึ้นใน XCTestCase โดยไม่รองรับการวนซ้ำแบบรัน
CopperCash

6

หากคุณต้องการทำการทดสอบประเภทนี้คุณจะรักการสนับสนุน UI Automation ใน iOS 4 คุณสามารถเขียน JavaScript เพื่อจำลองการกดปุ่ม ฯลฯ ได้อย่างง่ายดายค่อนข้างง่ายแม้ว่าเอกสาร (โดยเฉพาะส่วนที่เริ่มต้นใช้งาน) จะเป็นบิต เบาบาง


1
ใช่นั่นคือสิ่งที่ยอดเยี่ยม แต่ฉันพยายามที่จะทำมันจากภายในแอปไม่ใช่ผ่านเครื่องมือ (ถ้านั่นเป็นวิธีที่คุณหมายถึง)
Olie

เครื่องมือทำงานกับแอปของคุณ แอพยังคงทำงานอยู่เครื่องมือเพิ่งจำลองการสัมผัส
Jeff Kelley

6
ฉันเข้าใจเครื่องมือ, เจฟ - สิ่งที่ฉันพูดคือ: ฉันต้องการให้หน่วยทดสอบของฉันทำงานในอุปกรณ์ในกระเป๋าของฉันโดยไม่ต้องใช้แล็ปท็อปหรือ XCode หรืออุปกรณ์พกพา หรือคุณรู้เคล็ดลับของการใช้เครื่องมือบนอุปกรณ์? ;)
Olie


5

ในกรณีนี้ได้มาจากUIButton งานนี้สำหรับวัตถุที่ได้มาจากUIControlUIControl

ฉันต้องการนำUIBarButtonItemการกระทำกลับมาใช้กับกรณีการใช้งานเฉพาะ "" ที่นี่UIBarButtonItemไม่เสนอวิธีการsendActionsForControlEvents:

แต่โชคดีที่UIBarButtonItemมีคุณสมบัติสำหรับเป้าหมาย & การกระทำ

 if(notHappy){        
         SEL exit = self.navigationItem.rightBarButtonItem.action;
         id  world = self.navigationItem.rightBarButtonItem.target;
         [world performSelector:exit];
 }

นี่เป็นประเภทrightBarButtonItemUIBarButtonItem


หากคุณใช้ UIBarButtonItem คุณสามารถ [self doAction: self.navigationItem.rightBarButtonItem]; // - doAction: เป็นชื่อการกระทำสลับของ self.navigationItem.rightBarButtonItem
c0ming


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.