-2

I'm new to Swift and followed a simple tutorial to make a magic 8 ball Cocoa App that every time I click the ball it shows a different piece of advice. I am now trying to practice my UI automated tests by asserting (XCTAssert) that the "Piece of Advice" label is equal to one of the string values in my array. My array looks like this and is in my ViewController.swift:

var adviceList = [
    "Yes",
    "No",
    "Tom says 'do it!'",
    "Maybe",
    "Try again later",
    "How can I know?",
    "Totally",
    "Never",
    ]

How can I make an assertion in my UITests.swift file that asserts that the string that is shown is equal to one of the string values in the array above?

halfer
  • 19,824
  • 17
  • 99
  • 186
Thomas Ni
  • 11
  • 1
  • 3
  • 1
    Possible duplicate of [How to check if an element is in an array](http://stackoverflow.com/questions/24102024/how-to-check-if-an-element-is-in-an-array) – John Montgomery Apr 05 '17 at 21:02
  • assert true on the contains method an array maybe? – DatForis Apr 06 '17 at 13:51
  • Meta advice moved from an answer: Welcome to Stack Overflow! You're getting a couple of downvotes because people are seeing the question as 'how do I check if an array contains a value' which has been asked multiple times already. Next question you ask take a quick look over ['how to ask a good question'](https://stackoverflow.com/help/how-to-ask) to make sure it's not misinterpreted. – halfer Apr 10 '17 at 15:21

1 Answers1

1

It's possible that you're asking how to access application state from a UI test, or just in general UI testing.

I think it's a pretty interesting question so I'm going to answer because it's something that I don't know a lot about and hopefully will prompt other people to chime in and correct.

Background: A basic Magic 8 Ball project

I set up a basic project with a view controller that contains two views: a label and a button. Tapping the button updates the label text with a random message:

import UIKit

struct EightBall {
    static let messages = ["Yes", "No", "It's not certain"]

    var newMessage: String {
        let randomIndex = Int(arc4random_uniform(UInt32(EightBall.messages.count)))
        return EightBall.messages[randomIndex]
    }
}

class ViewController: UIViewController {

    let ball = EightBall()

    @IBOutlet weak var messageLabel: UILabel!

    @IBAction func shakeBall(_ sender: Any) {
        messageLabel.text = ball.newMessage
    }
}

A basic UI test

Here's a commented UI test showing how to automate tapping on the button, and grabbing the value of the label, and then checking that the value of the label is a valid message.

import XCTest

class MagicUITests: XCTestCase {

    // This method is called before the invocation of each test method in the class.
    override func setUp() {
        super.setUp()

        // In UI tests it is usually best to stop immediately when a failure occurs.
        continueAfterFailure = true
        // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
        XCUIApplication().launch()
    }

    func testValidMessage() {

        // Grab reference to the application
        let app = XCUIApplication()

        // #1
        // Grab reference to the label with the accesability identifier 'MessageLabel'
        let messagelabelStaticText = app.staticTexts["MessageLabel"]

        // Tap the button with the text 'Shake'
        app.buttons["Shake"].tap()

        // get the text of the label
        let messageLabelText = messagelabelStaticText.label

        // #2
        // check if the text in the label matches one of the allowed messages
        let isValidMessage = EightBall.messages.contains(messageLabelText)

        // test will fail if the message is not valid
        XCTAssert(isValidMessage)
    }
}

At #1 The approach that I'm using to get the label is to access the labels accessibilityIdentifier property. For this project I entered this through storyboard, but if you're setting your views up in code you can directly set the accessibilityIdentifier property yourself.

The other thing that's confusing here is that to get access to elements in the view you're not navigating the view hierarchy, but a proxy of the hierarchy, which is why the syntax to get a label is the odd 'staticTexts' (The references at the bottom of the post explain this in more detail).

enter image description here

For #2 I'm inspecting the structure defined in my project. In a unit test you could access this my importing @testable import ProjectName but unfortunately this approach doesn't work for UI Test.

Instead, you'll have to make sure that any source file you want to access from the UI test is included as a target. You can do this in Xcode from this panel by checking the name of your UI test:

enter image description here

More UI testing references:

halfer
  • 19,824
  • 17
  • 99
  • 186
MathewS
  • 2,267
  • 2
  • 20
  • 31
  • Thanks so much :) – Thomas Ni Apr 06 '17 at 18:20
  • This is a splendid answer, nice work! I hope it's OK that I've moved the meta commentary to a comment, since we want posts to be focussed on the material itself here. Comments are much freer, so they are a more appropriate for notes about questions or answers themselves. – halfer Apr 10 '17 at 15:24