Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

ಋೖ͢Δʹ͸ʁ

Slide 7

Slide 7 text

6*5FTUTTXJGUΛબ୒

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

ࣗಈੜ੒ίʔυ
 ఺͘Β͍ʁ 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) ͜ͷέʔεͰ͸ɺ݁Ռ൑ఆ͸ɺࣗ෼Ͱॻ͖଍͢ඞཁ͕͋Δ

Slide 10

Slide 10 text

ࣗಈੜ੒ίʔυ
 εϥΠμʔ͸ɺΫϦοΫʹ͞Εͯ͠·͏ 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) ਖ਼͘͠͸

Slide 11

Slide 11 text

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)

Slide 12

Slide 12 text

ςετ͕ΤϥʔʹͳΔϧʔϧ w 9$5"TTFSUؔ਺ w ୳͍ͯ͠ΔϘλϯͳͲ͕ݟ͚ͭΒΕͳ͍ w ͕͔͔࣌ؒΓ͗͢Δ 9DPEF͸ɺඵʁ

Slide 13

Slide 13 text

ςετͷ࣮ߦ

Slide 14

Slide 14 text

݁ՌΛ֬ೝ

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

"DDFTJCJMJUZ*EFOUJpFSͷ
 ηοτํ๏

Slide 21

Slide 21 text

ίʔυͷ৔߹
 ΞϓϦຊମͷίʔυͰ࣮૷ w ɹ
 
 
 
 ˞0CKFDUJWF$ͩͱɺBDDFTTJCJMJUZ*OEFOUJpFS͸ɺϓϩύςΟʹͳ͍ͬͯΔ
 w 
 
 
 
 SwiftUI
 
 Text("") .accessibility(identifier: "label1") AppKit
 
 let button = NSButton() button.setAccessibilityIdentifier(“button1")

Slide 22

Slide 22 text

"DDFTJCJMJUZ*EFOUJpFSͷ
 ֬ೝํ๏ w EFCVH%FTDSJQUJPOϝιου w "DDFTJCJMJUZ*OTQFDUPSΞϓϦ

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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 }

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

"DDFTJCJMJUZ*OTQFDUPS

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

ࡉ͔͍ϊ΢ϋ΢

Slide 30

Slide 30 text

ඵϧʔϧʹ
 Ҿ͔͔ͬΒͳ͍Α͏ʹ଴ͭ
 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") } }

Slide 31

Slide 31 text

%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)[“ॻ͖ग़͠”]

Slide 32

Slide 32 text

*.ͷϞʔυʹ͸
 ؾΛ͚ͭͯʂ w ೔ຊޠೖྗʹ͍ͯ͠ΔͱɺจࣈԽ͚͢Δ͜ͱ΋ w ྫςΩετϑΟʔϧυʹʮࢼݧจࣈྻʯ
 ˠʮ͍͏͋Ε͖ʯ

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

/44BWF/40QFO1BOFM

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

ΞϓϦຊମͷڍಈΛม͑Δ let app = XCUIApplication() app.launchEnvironment = ["UITestOption": jsonString] app.launch() let environment = ProcessInfo.processInfo.environment let jsonString = environment["UITestOption"] 6*5FTUTଆ ΞϓϦຊମଆ

Slide 38

Slide 38 text

/44UBUVT#BSΞϓϦ w ͦ΋ͦ΋"DDFTJCJMJUZ*EFOUJpFSΛηοτͰ͖ͳ͍ w ΞΠίϯ͚ͩͷϘλϯ͕΄ͱΜͲ ςετ͚࣌ͩɺແཧ΍ΓλΠτϧΛ෇͚ͯ୳͠ग़͢

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

จࣈྻͷೖྗ 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)

Slide 42

Slide 42 text

/44DSPMM7JFXͷ
 ֎ͷ͋Δ6*ͷ୳͠ํ w ͻͨ͢Β଴ͭ
 
 ෼୯Ґͷ͕͔͔࣌ؒΔ΋ͷͷɺ଴͍ͬͯΕ͹ɺը໘֎΋ ୳͠ग़͠·͢
 
 ΢Πϯυ΢ͷେ͖͞Λ֮͑ΔΞϓϦͷ৔߹͸
 σΟεϓϨΠΛͰ͖Δ͚ͩߴղ૾౓ʹͯ͠
 ςετલʹɺ࠷େαΠζʹ͓ͯ͘͠

Slide 43

Slide 43 text

PQUJPO ΫϦοΫ ௨ৗબ୒Ͱ͖ͳ͍ɺߴղ૾౓͕બ୒Ͱ͖Δ

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

9DPEF4FSWFS#PUTͷઃఆ

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

&OE