0

Is there a way to share instances / data between the app and the UI test being run? My understanding is that they run as two different apps and that make it impossible but I wanted to check. I was thinking of something like:

// included in both my app and the UI test
class Foo {
  let shared: Foo()
  var value = ""
}

// In the UI test:
class BasicAccessibility: XCTestCase {
  func testFoo() {
    Foo.shared.value = "bar"
  }
}

// In the app
class FooController: UIViewController {
  override func viewDidLoad() {
    label.value = Foo.shared.value
  }
}

I'm trying to simulate device gyroscope from the UI tests, so in my case Foo would be some gyro manager instance. My best alternative atm it to include a UI element in the app that the test can interact with, which kind of sucks.

=== edit ===

I don't think This question is similar since it's not about UI test and the UI test app has different settings and abilities than a normal app.

Community
  • 1
  • 1
Guig
  • 9,891
  • 7
  • 64
  • 126
  • 1
    I don't think so since the UI test app is quite different from a normal app: it has access to more than normal apps, being able to interact with them without custom settings. I'd look at this question but the UI test app don't have the same settings than a normal app. For instance you can't set the bundle id, and it doesn't even has the `capabilities` settings that the other answer is using. – Guig Mar 06 '17 at 19:26
  • 1
    I have retracted the flag. Good edit to your question. –  Mar 06 '17 at 19:43
  • I've sofar did not find a decent way to achieve this. This approach might work for you, depending on your architecture: http://stackoverflow.com/questions/32320455/how-to-detect-if-ios-app-is-running-in-ui-testing-mode. You could maybe swap in a `TestFoo` at runtime when you set a specific flag? – fguchelaar Mar 06 '17 at 19:53
  • I know how to detect the test environment from the app, which is good for preset things like `if test { ... } else { ... }` but here I'm trying to pass parameter from the test app to the app at runtime. – Guig Mar 06 '17 at 22:40

1 Answers1

1

I don't know if this is a very good idea, but it's something that I'm trying and it seems to work well. If anyone knows a very bad reason to do this let me know.

create a file named Person.swift and add it to both app target and UITestTarget.

struct Person: Codable {
    let name: String
    let age: Int
    let height: Int
    let weight: Int
}

In your UITests "serialize" the object and send it over launch environment dictionary.

class UITestingDataUITests: XCTestCase {

    let app = XCUIApplication()

    override func setUp() {
        continueAfterFailure = false

        let person = Person(name: "Tom Cruise", age: 56, height: 170, weight: 60)
        let json = String(data: try! JSONEncoder().encode(person), encoding: .utf8)

        continueAfterFailure = false
        app.launchArguments.append("isUITesting")
        app.launchEnvironment["custom-object-person"] = json
        app.launch()
    }

In your app delegate access the object:

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {

        let personInfo = ProcessInfo.processInfo.environment["custom-object-person"]!
        let person = try! JSONDecoder().decode(Person.self, from: personInfo.data(using: .utf8)!)
        print(person)

        return true
    }

Nuno Gonçalves
  • 6,202
  • 7
  • 46
  • 66