50

I have a picker view with few items: "Red", "Green", "Yellow", "Black". In my UI test I need to select a specific item "Green" from it. I am using the XCTest UI testing APIs that were intruduced with Xcode 7.

enter image description here

What I managed to do so far is to swipe the whole picker view up in the unit test. It is not ideal because it always changes the picker view to the bottom item (when swiping up).

let app = XCUIApplication()
app.launch()
app.pickers.elementAtIndex(0).swipeUp()    
XCTAssert(app.staticTexts["Selected: Black"].exists)

Another but very similar way of changing the picker view is to call pressForDuration ... thenDragToElement, which is not what I want.

app.pickers.elementAtIndex(0).pressForDuration(0.1, thenDragToElement: someElement)

When I use the UI test record function it does not record the picker view scrolling events. It does record when I tap on picker view items:

app.pickerWheels["Green"].tap()

but that does not actually work when the test is run (probably because it needs to scroll the picker view first before tapping).

Here is the demo app with the test.

https://github.com/exchangegroup/PickerViewTestDemo

Update

It is now possible to select a picker view since Xcode 7.0 beta 6 .

app.pickerWheels["Green"].adjustToPickerWheelValue("Yellow")
Evgenii
  • 36,389
  • 27
  • 134
  • 170

7 Answers7

59

As noted in the question's update, Xcode 7 Beta 6 added support for interacting with pickers. The newly added method -adjustToPickerWheelValue: should be used to select items on a UIPickerView.

let app = XCUIApplication()
app.launch()
app.pickerWheels.element.adjustToPickerWheelValue("Yellow")

Here's a GitHub repo with a working example. And some more information in a blog post I wrote.

Joe Masilotti
  • 16,815
  • 6
  • 77
  • 87
20

If there are multiple wheels, an easy way to select items it is like this:

precondition: it's a date picker (UIDatePicker), swift language

    app.pickerWheels.elementBoundByIndex(0).adjustToPickerWheelValue("March")
    app.pickerWheels.elementBoundByIndex(1).adjustToPickerWheelValue("13")
    app.pickerWheels.elementBoundByIndex(2).adjustToPickerWheelValue("1990")

where: index "0" is month, "1" is day, "2" is year

Joao_dche
  • 307
  • 3
  • 7
  • 8
    be careful with localization when you use absolute index. The month and day wheels could be different depending which local the device has (us and german locals for exmaple have different layouts) – Peacemoon Oct 30 '15 at 11:08
  • 4
    This is not working. I am always getting: "UI Testing Failure - Internal error: unable to find current value 'Something, 1 of 3' in possible values thing, thing2, thing3 for the picker wheel "Something, 1 of 3" PickerWheel" – Abdalrahman Shatou May 02 '16 at 01:39
  • 1
    : index "0" is month, "1" is day, "2" is year... Works for all country configurations? – Javier Calatrava Llavería May 24 '16 at 11:00
  • This will not work outside of english. In danish, the value for march is "marts", and in french it is "mars". The example code will fail in both. I have not tested the order, but both languages mentioned are ordered day-month-year, instead of month-day-year, so that is potentially an issue as well – Fizker Jun 05 '16 at 15:33
  • 1
    app.pickerWheels.element(boundBy: 0).adjust(toPickerWheelValue: NSLocalizedString("January", comment: "")) – Gene De Lisa Jan 15 '17 at 15:03
9

Swift 4 version of @Joao_dche's answer

app.pickerWheels.element(boundBy: 0).adjust(toPickerWheelValue: "March")
app.pickerWheels.element(boundBy: 1).adjust(toPickerWheelValue: "13")
app.pickerWheels.element(boundBy: 2).adjust(toPickerWheelValue: "1990")
radioaktiv
  • 2,437
  • 4
  • 27
  • 36
2

Objective-C Version of @Joao_dche's Answer

Using UIDatePicker with XCTest for UI Testing:

    XCUIElementQuery *datePickersQuery = app.datePickers;
    [datePickersQuery.pickerWheels.allElementsBoundByIndex[0] adjustToPickerWheelValue:@"May"];
    [datePickersQuery.pickerWheels.allElementsBoundByIndex[1] adjustToPickerWheelValue:@"13"];
    [datePickersQuery.pickerWheels.allElementsBoundByIndex[2] adjustToPickerWheelValue:@"2017"];

    XCUIElement *doneButton = app.buttons[@"Done"];
    [doneButton.firstMatch tap];
Debo
  • 308
  • 2
  • 7
1

Joe's answer working great on iOS 11, but doesn't work for me on iOS 10.3.1 [Xcode 9.2]

I use custom views (labels actually) as picker rows and unfortunately gorgeous Joe's answer doesn't work for me on iOS 10.3.1 while working perfectly on iOS 11. So I had to use

app.pickerWheels["X, Y of Z"].swipeUp()

where

X is my label's text.
Y is row position in picker view. Position number starts with 1, not zero.
Z is number of values in picker view.

So in my case this command looks like

app.pickerWheels["1st, 1 of 28"].swipeUp()
Pavel Vavilov
  • 588
  • 3
  • 8
1

This is one of most popular post for select pickervie(UIPickerView)

If you want to select state/date from picker view. You can try following swift 3 code.

 XCUIApplication().tables.pickerWheels["AK"].adjust(toPickerWheelValue: "MA")

PickerWheels pick from AK and set the target state.

XCUIApplication().tables.pickerWheels["Starting Point" "].adjust(toPickerWheelValue: "Target Place")

enter image description here

N..
  • 906
  • 7
  • 23
-1

I used below code to identify the element displayed now in the picker wheel.

To Find an element in picker

let valueSelected = algorithmsPicker.pickerWheels.element(boundBy: 0).value as! String

To select a value in the picker wheel:

 algorithmsPicker.pickerWheels[valueSelected].adjust(toPickerWheelValue: "BubbleSort")
Sujananth
  • 635
  • 1
  • 10
  • 24