简体   繁体   中英

How can I set flags that my app will see when it's running under XCTest?

KIF works like magic, something puzzled me a lot recently. That is how exactly KIF and XCTest works.

It is said in WWDC 2014 & 2013: Test code is injected into the host application as kind of a plugin, so what information can be eavesdrop from main app as a plugin? What is the relationship between Host Application & Plugin ??

Using KIF, we can sense the Notifications & URL request, but how that works? My first thought is all context in host application is shared with plugin But why in test, we cannot modify variables in the main app?

For example:

we have two targets:

Magic Project

-- MagicApp

-- MagicUITest <- KIFTest target

Suppose I have a file called MagicClass:

class MagicClass {
  static var a = 1
}

Is that possible if I want to modify that variable in MagicUITest?

The problem I faced right now is how can I inject different UIViewController to RootViewController so that I can run KIF test from each individual ViewController and don't need bother going through the login process all the time .. my guess is something like:

in MagicApp:

class AppDelegate : .. , .. {
  func application(application: UIApplication, willFinishLaunchingWithOptions   launchOptions: [NSObject : AnyObject]?) -> Bool {
   if MagicClass.a == 1 {
      window.rootViewController = AViewController()
   } else {
      window.rootViewController = BViewController()
   }
  }
}

in KIFTest's setUp() :

setUp() {
  Magic.a = 2
}

But not work ..

One thing is Magic.a = 2 won't change the Magic.a in MagicApp, second is application(..,..,..) function will end before setUp() is called ..

Any idea ?

While you're correct that the exact code you've tried won't work, you'll be able to use a very similar approach.

This code, for example, is cribbed directly from the app I'm working on right now in a class called RootViewController that's (you guessed it) the app's root view controller:

public override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    if NSProcessInfo.processInfo().environment["TESTING"] == nil {
        loadChildren()
    }
}

What it does is looks for an environment variable to decide if it should automatically continue with loading the app, and if it finds the environment variable it waits for the test stack to finish setting up and telling it what portion of the app to load next. (You could do this in your app delegate, too, if it's a really small app.)

You can set the environment variable by editing the scheme in Xcode: 该屏幕快照描述了如何添加环境变量

All that said, though: take care when using this strategy. You want your tests to be testing features of your app as they exist in your app, and if showing different screens arbitrarily is a feature of your app, that's probably okay. But if you start writing code that makes your app behave differently when under test, you're not really testing your app anymore, are you?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM