About UITests

About UITests

4780d783ef27d0980f14b47894012ce2?s=128

HIRAI Hiroaki

September 08, 2019
Tweet

Transcript

  1. 6*5FTUTʹ͍ͭͯ *OOPGBDFגࣜձࣾ ୅දऔక໾ฏҪത໌

  2. Ξϯέʔτ w 2ࣗ෼͸ɺϓϩάϥϜΛॻ͍͍ͯΔ w 26*5FTUT͸ɺ஌͍ͬͯΔɾࢼͨ͜͠ͱ͕͋Δ w 26*5FTUTΛ೔ࠒ͔Β׆༻͍ͯ͠Δ

  3. ςετ࢓༷ॻ ςετखॱ
 ࠨͷೖྗϑΟʔϧυʹʮʯΛೖྗ
 ӈͷೖྗϑΟʔϧυʹʮʯΛೖྗ
 ϦλʔϯΩʔΛԡ͢ ظ଴݁Ռ
 ߹ܭͷཝʹʮʯ͕දࣔ͞ΕΔ

  4. ςετͷ؀ڥͷྫ NBD04ɺNBD04ɺNBD04
 º
 ೔ຊޠɺӳޠɺϑϥϯεޠɺεϖΠϯޠ
 º
 .BD#PPL"JSɺJ.BD
 
 
 ೥ܦͭͱɺ࠷৽ͷNBD04YͰɺ·ͨಉ͡ςετɾɾɾ

  5. ࣗಈԽ͢ΔϝϦοτ w ςελʔʹཔ·ͳͯ͘΋ɺࣗಈͰςετ͕ग़དྷΔ

  6. ಋೖ͢Δʹ͸ʁ

  7. 6*5FTUTTXJGUΛબ୒

  8. ࿥ըͱ͍͏͔ɾɾɾ
 ίʔυͷࣗಈੜ੒ػೳ ͝ػݏࣼΊʹͳΓ͕ͪͰɺ%JTBCMFͳ࣌΋ɾɾɾ

  9. ࣗಈੜ੒ίʔυ
 ఺͘Β͍ʁ let app = XCUIApplication() app.launch() let window =

    XCUIApplication().windows["Window"] let field1TextField = window.textFields["field1"] field1TextField.click() field1TextField.typeText("10") let field2TextField = window.textFields["field2"] field2TextField.click() field2TextField.typeText("20\r") XCTAssert("30" == window.staticTexts["result"].value as? String) ͜ͷέʔεͰ͸ɺ݁Ռ൑ఆ͸ɺࣗ෼Ͱॻ͖଍͢ඞཁ͕͋Δ
  10. ࣗಈੜ੒ίʔυ
 εϥΠμʔ͸ɺΫϦοΫʹ͞Εͯ͠·͏ let app = XCUIApplication() app.launch() let window =

    XCUIApplication().windows["Window"] let valueIndicator = XCUIApplication().windows["Window"].sliders["slider1"].children(matching: .valueIndicator).element valueIndicator.click() //ਅΜதΛΫϦοΫ͢Δ͚ͩ valueIndicator.click() //ਅΜதΛΫϦοΫ͢Δ͚ͩ let app = XCUIApplication() app.launch() let slider = XCUIApplication().windows["Window"].sliders["slider1"] slider.adjust(toNormalizedSliderPosition: 1.0) slider.adjust(toNormalizedSliderPosition: 0.0) ਖ਼͘͠͸
  11. 6*5FTUTͷίʔυ  4UFQɿΞϓϦىಈ
 
 
 4UFQɿϘλϯ΍ϝχϡʔͳͲΛ୳͢
 4UFQɿ୳͠ग़ͨ͠ϘλϯͳͲΛΫϦοΫͳͲ͢Δ
 
 4UFQʙ̏Λ܁Γฦͯ͠
 


    
 
 
 4UFQ-BTUɿ࠷ऴతͳ݁ՌΛ֬ೝ͢Δ XCUIApplication().launch() app.windows[“໊শະઃఆ”].buttons["બ୒…"].click()
 app.menuBars.menuBarItems["ฤू"].click() app.menuBars.menuItems["ϖʔετ"].click() XCTAssert("30" == window.staticTexts["result"].value as? String)
  12. ςετ͕ΤϥʔʹͳΔϧʔϧ w 9$5"TTFSUؔ਺ w ୳͍ͯ͠ΔϘλϯͳͲ͕ݟ͚ͭΒΕͳ͍ w ͕͔͔࣌ؒΓ͗͢Δ 9DPEF͸ɺඵʁ

  13. ςετͷ࣮ߦ

  14. ݁ՌΛ֬ೝ

  15. 6*5FTUTͷ࢓૊Έ w 6*5FTUT3VOOFSͱ͍͏ΞϓϦ͕Ϗϧυ͞Εͯ
 ਓʹ୅Θͬͯɺૢ࡞ͯ͘͠Ε·͢ w ܽ఺ɿ6*5FTUT3VOOFS͸
 ΞϓϦຊମͷϓϩηεͱҧ͏ϓϩηεͰಈ࡞

  16. ϓϩηε͕ҧ͏ͱ͍͏͜ͱ͸ w ΞϓϦຊମͷɺΫϩʔδϟʔ͕࢖͑ͳ͍ w ΞϓϦຊମͷɺσϦήʔτϝιου͕ݺ͹Εͳ͍ w ΞϓϦຊମͷɺ/PUJpDBUJPO͕དྷͳ͍ w ΞϓϦຊମͷɺίʔϧόοΫؔ਺͕࢖͑ͳ͍ ϙʔϦϯάͰɺ6*ͷมԽΛ؂ࢹ͢Δ͔͠ͳ͍

  17. ୳͠ํ͸ɺ௨Γ w "DDFTTJCJMJUZ*EFOUJpFSΛ୳͢ w ϘλϯͳͲͷϥϕϧɾλΠτϧΛ୳͢ w ॱ൪Ͱ୳͢JOEFY

  18. ݴޠϩʔΧϥΠζ͞Ε͍ͯΔ ը૾ϦιʔεͰɺιʔείʔυͷςΩετͰࢦఆͰ͖ͳ͍ ಉ͡ϥϕϧͷϘλϯ͕ը໘্ʹ͍ͭ͘΋ฒͿ ೔ຊޠ؀ڥ ӳޠ؀ڥ

  19. ೔ຊޠ؀ڥ ӳޠ؀ڥ "DDFTJCJMJUZ*EFOUJpFS͕
 Ұ൪໌ࣔ͠΍͍͢ DBODFM QMBZ TUPQ TFMFDU*NBHF TFMFDU*NBHF TFMFDU4PVOE

    TFMFDU4PVOE
  20. "DDFTJCJMJUZ*EFOUJpFSͷ
 ηοτํ๏

  21. ίʔυͷ৔߹
 ΞϓϦຊମͷίʔυͰ࣮૷ w ɹ
 
 
 
 ˞0CKFDUJWF$ͩͱɺBDDFTTJCJMJUZ*OEFOUJpFS͸ɺϓϩύςΟʹͳ͍ͬͯΔ
 w 


    
 
 
 SwiftUI
 
 Text("") .accessibility(identifier: "label1") AppKit
 
 let button = NSButton() button.setAccessibilityIdentifier(“button1")
  22. "DDFTJCJMJUZ*EFOUJpFSͷ
 ֬ೝํ๏ w EFCVH%FTDSJQUJPOϝιου w "DDFTJCJMJUZ*OTQFDUPSΞϓϦ

  23. "QQMFࣾఏڙͷ6*ͳͲΛ
 ஌Δඞཁ͕͋Δ

  24. print(XCUIApplication().windows["Window"].debugDescription) ΢Πϯυ΢ͷ্ʹɺͲΜͳ6*͕৐͍ͬͯΔͷ͔ʁ Attributes: Window (Main), {{340.0, 781.0}, {480.0, 292.0}}, identifier:

    '_NS:10', title: 'Window', Disabled Element subtree: →Window (Main), 0x600003b00b60, {{340.0, 781.0}, {480.0, 292.0}}, identifier: '_NS:10', title: 'Window', Disabled Button, 0x600003b00c40, {{493.0, 882.0}, {81.0, 32.0}}, identifier: 'button1', title: 'Button', Keyboard Focused Button, 0x600003b00d20, {{347.0, 784.0}, {14.0, 16.0}}, identifier: '_XCUI:CloseWindow' Button, 0x600003b00e00, {{387.0, 784.0}, {14.0, 16.0}}, identifier: '_XCUI:FullScreenWindow' Button, 0x600003b00ee0, {{367.0, 784.0}, {14.0, 16.0}}, identifier: '_XCUI:MinimizeWindow' StaticText, 0x600003b00fc0, {{553.0, 784.0}, {53.0, 16.0}}, value: Window Path to element: →Application, 0x600003b00a80, pid: 89463, title: 'sampleapp', Disabled ↳Window (Main), 0x600003b00b60, {{340.0, 781.0}, {480.0, 292.0}}, identifier: '_NS:10', title: 'Window', Disabled Query chain: →Find: Target Application 'jp.co.innoface.sampleapp' Output: { Application, pid: 89463, title: ‘sampleapp', Disabled } ↪Find: Descendants matching type Window Output: { Window (Main), {{340.0, 781.0}, {480.0, 292.0}}, identifier: '_NS:10', title: 'Window', Disabled } ↪Find: Elements matching predicate '"Window" IN identifiers' Output: { Window (Main), {{340.0, 781.0}, {480.0, 292.0}}, identifier: '_NS:10', title: 'Window', Disabled }
  25. print(XCUIApplication().windows["Window"].debugDescription) ΢Πϯυ΢ͷ্ʹɺͲΜͳ6*͕৐͍ͬͯΔͷ͔ʁ Button, ɾɾɾ identifier: 'button1', title: 'Button', ɾɾɾ Button,

    ɾɾɾ identifier: '_XCUI:CloseWindow' Button, ɾɾɾ identifier: '_XCUI:FullScreenWindow' Button, ɾɾɾ identifier: '_XCUI:MinimizeWindow' ※΢Πϯυ΢ࠨ্ͷϘλϯ͸ɺݻఆͷidentifier͕APIͱͯ͠ఏڙ͞Ε͍ͯΔ
 let XCUIIdentifierCloseWindow: String
 let XCUIIdentifierFullScreenWindow: String
 let XCUIIdentifierMinimizeWindow: String
  26. "DDFTJCJMJUZ*OTQFDUPS

  27. None
  28. None
  29. ࡉ͔͍ϊ΢ϋ΢

  30. ඵϧʔϧʹ
 Ҿ͔͔ͬΒͳ͍Α͏ʹ଴ͭ
 FYQFDUBUJPO let expectation = self.expectation(description: "Download File") DispatchQueue.global(qos:

    .default).async(execute: { //ϙʔϦϯάͰɺEnableঢ়ଶͷButton͕ݟ͔ͭΔͷΛ଴ͭ var isNeedCheck = true repeat { Thread.sleep(forTimeInterval: 0.1) DispatchQueue.main.sync(execute: { if okButton.isEnabled { okButton.click() //expectation͕ແࣄʹ࣮ߦͰ͖ͨ expectation.fulfill() isNeedCheck = false } }) } while isNeedCheck }) self.waitForExpectations(timeout: 300) { error in if nil != error { XCTFail("Download Timeout") }else{ print("Download Success") } }
  31. %JTBCMFʹؾΛ͚ͭͯʂ w %JTBCMFঢ়ଶͷϘλϯͰ΋ɺΫϦοΫͯ͠0,ʹͳΔ
 ˞ਓؒͷςελʔͰ͸ɺ·ͣ͋Γ͑ͳ͍ͷͰ஫ҙʂʂʂ
 let button = XCUIApplication().windows["Window"].buttons["ॻ͖ग़͠"] if button.isEnabled

    { button.click() }else{ XCTFail() } let predicate = NSPredicate(format:"isEnabled == TRUE") app.ɾུɾ.buttons.matching(predicate)[“ॻ͖ग़͠”]
  32. *.ͷϞʔυʹ͸
 ؾΛ͚ͭͯʂ w ೔ຊޠೖྗʹ͍ͯ͠ΔͱɺจࣈԽ͚͢Δ͜ͱ΋ w ྫςΩετϑΟʔϧυʹʮࢼݧจࣈྻʯ
 ˠʮ͍͏͋Ε͖ʯ

  33. ͔͜͜Βઌͷ
 6*5FTUTͷίʔυΛॻ͘ʹ͸
 ৺ͷ޿͞ɾॊೈੑ͕ඞཁͰ͢

  34. /44BWF/40QFO1BOFM

  35. "QQMFࣾͷΞϓϦ
 ݴޠϦιʔε IUUQTEFWFMPQFSBQQMFDPNKQJOUFSOBUJPOBMJ[BUJPO

  36. EJSFDUPSZ63-
 /4/BW-BTU3PPU%JSFDUPSZ Ұக͍ͯ͠Δ৔߹ Ұக͍ͯ͠ͳ͍৔߹

  37. ΞϓϦຊମͷڍಈΛม͑Δ let app = XCUIApplication() app.launchEnvironment = ["UITestOption": jsonString] app.launch()

    let environment = ProcessInfo.processInfo.environment let jsonString = environment["UITestOption"] 6*5FTUTଆ ΞϓϦຊମଆ
  38. /44UBUVT#BSΞϓϦ w ͦ΋ͦ΋"DDFTJCJMJUZ*EFOUJpFSΛηοτͰ͖ͳ͍ w ΞΠίϯ͚ͩͷϘλϯ͕΄ͱΜͲ ςετ͚࣌ͩɺແཧ΍ΓλΠτϧΛ෇͚ͯ୳͠ग़͢

  39. 6*5FTUͷ࠷େͷܽ఺ʁ w ͱʹ͔͕͔͔࣌ؒ͘Δ
 ͦΕͰ΋ɺਓؒͷςελʔΑΓ͸ɾɾɾ

  40. ϝχϡʔͷબ୒ w .FOV*UFNΛΫϦοΫ͢ΔΑΓ w γϣʔτΧοτΩʔ͕͓નΊ textField.typeKey("f", modifierFlags:.command)

  41. จࣈྻͷೖྗ w γϣʔτΧοτΩʔ͕͓નΊ let pasteboard = NSPasteboard.general pasteboard.clearContents() pasteboard.setString(“SampleText",
 forType:

    NSPasteboard.PasteboardType.string) ɾ
 ɾ
 ɾ
 textField.click() textField.typeKey("a", modifierFlags:.command) textField.typeKey("v", modifierFlags:.command)
  42. /44DSPMM7JFXͷ
 ֎ͷ͋Δ6*ͷ୳͠ํ w ͻͨ͢Β଴ͭ
 
 ෼୯Ґͷ͕͔͔࣌ؒΔ΋ͷͷɺ଴͍ͬͯΕ͹ɺը໘֎΋ ୳͠ग़͠·͢
 
 ΢Πϯυ΢ͷେ͖͞Λ֮͑ΔΞϓϦͷ৔߹͸
 σΟεϓϨΠΛͰ͖Δ͚ͩߴղ૾౓ʹͯ͠


    ςετલʹɺ࠷େαΠζʹ͓ͯ͘͠
  43. PQUJPO ΫϦοΫ ௨ৗબ୒Ͱ͖ͳ͍ɺߴղ૾౓͕બ୒Ͱ͖Δ

  44. pSTU.BUDI w ࣮֬ʹը໘্ʹҰ͔ͭ͠ͳ͍
 JEFOUJpFSɺϥϕϧɺλΠτϧͱ෼͔͍ͬͯΔ৔߹͸
 ݟ͚ͭͨͱ͜ΖͰɺݕࡧΛ΍Ίͯ͘ΕΔ textFields["field1"].firstMatch

  45. Ϛ΢εͱΩʔϘʔυΛ
 ৐ͬऔΒΕͳ͍ͨΊʹ w ผΞΧ΢ϯτͷϢʔβʔʹςετͯ͠΋Β͏
 ϑΝʔετϢʔβʔεΠον 
 9DPEFͷ1SFGFSFODF͔ΒɺϢʔβʔΛ௥ՃͰ͖Δ w Ծ૝Խ؀ڥΛ࢖͏
 7.XBSF'VTJPOͳͲ

  46. 9DPEF4FSWFS#PUTͷઃఆ

  47. ·ͱΊ w Ұ౓ࣗಈԽͯ͠͠·͑͹ɺେ෯ʹख͕ؒݮΔ w ςετ࣌ͷΦϓγϣϯΛมߋͯ͠ɺԿ౓΋ࢼ͠΍͘͢ͳΔ
 4BOJUJ[FSΦϓγϣϯͳͲ

  48. &OE