web-dev-qa-db-fra.com

Comment détecter si une application iOS est en cours d'exécution en mode de test d'interface utilisateur

Je souhaite que mon application exécute un code spécial (par exemple, la réinitialisation de son état) lors de l'exécution en mode de test d'interface utilisateur. J'ai examiné les variables d'environnement définies lorsque l'application est exécutée à partir du test d'interface utilisateur et il n'y a pas de paramètres évidents permettant de différencier l'application fonctionnant normalement par rapport au test d'interface utilisateur. Y a-t-il un moyen de le savoir?

Deux solutions de contournement dont je ne suis pas satisfait sont les suivantes:

  1. Définissez XCUIApplication.launchEnvironment avec une variable que je vérifie plus tard dans l'application. Ce n'est pas bon car vous devez le définir dans la méthode setUp de chaque fichier de test. J'ai essayé de définir la variable d'environnement à partir des paramètres du schéma, mais cela ne se propage pas à l'application elle-même lors de l'exécution des tests de test de l'interface utilisateur.
  2. Vérifiez l'absence de la variable d'environnement __XPC_DYLD_LIBRARY_PATH. Cela semble très compliqué et pourrait ne fonctionner que maintenant à cause d'une coïncidence dans la configuration de nos paramètres de construction cibles.
34
Liron Yahdav

J'ai moi-même étudié cette question et suis tombé sur cette question. J'ai fini par aller avec la première solution de contournement de @ LironYahdav:

Dans votre test d'interface utilisateur:

- (void)setUp
{
    [super setUp];

    XCUIApplication *app = [[XCUIApplication alloc] init];
    app.launchEnvironment = @{@"isUITest": @YES};
    [app launch];
}

Dans votre application:

NSDictionary *environment = [[NSProcessInfo processInfo] environment];
if (environment[@"isUITest"]) {
    // Running in a UI test
}

Les solutions de @ JoeMasilotti sont utiles pour unit tests, car elles partagent le même temps d'exécution que l'application à tester, mais ne sont pas pertinentes pour les tests d'interface utilisateur.

47
jnic

Je n'ai pas réussi à définir un environnement de lancement, mais je l'ai obtenu avec des arguments de lancement.

Dans vos tests, la fonction setUp () ajoute:

  let app = XCUIApplication()
  app.launchArguments = ["testMode"]
  app.launch()

Dans votre code de production, ajoutez un chèque tel que:

let testMode =  NSProcessInfo.processInfo().arguments.contains("testMode")
if testMode {
  // Do stuff
}

Vérifié à l'aide de XCode 7.1.1.

8
Ciryon

Vous pouvez utiliser Preprocessor Macros pour cela. J'ai trouvé que vous avez plusieurs choix:

Nouvelle cible

Faites une copie de la cible de l'application et utilisez-la comme cible à tester. Toute macro de préprocesseur dans cette copie cible est accessible en code.

Un inconvénient est que vous devrez également ajouter de nouvelles classes/ressources à la cible de copie et parfois, il sera très facile de les oublier.

Nouvelle configuration de construction

Faites une copie de la configuration de construction Debug, définissez n'importe quelle macro de préprocesseur sur cette configuration et utilisez-la pour votre test (voir les captures d'écran ci-dessous). 

Une erreur mineure: chaque fois que vous voulez enregistrer une session de test d'interface utilisateur, vous devez modifier le Exécuter pour utiliser la nouvelle configuration de test.

Ajouter une configuration en double:

 Add a duplicate conf

Utilisez-le pour votre Test:

 Use it for your *Test*

5
Sandeep Chayapathi

Je viens d'ajouter cette extension

 @available(iOS 9, *)
 extension XCUIApplication {

 func test(){
   launchEnvironment = ["TEST":"true"]
   launch()
  }
 }

Je peux donc simplement utiliser test () au lieu de launch ()

3
andrea sciutto

Swift 3 basé sur les réponses précédentes.

class YourApplicationUITests: XCTestCase {

    override func setUp() {
        super.setUp()

        // Put setup code here. This method is called before the invocation of each test method in the class.

        // In UI tests it is usually best to stop immediately when a failure occurs.
        continueAfterFailure = false
        // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
        let app = XCUIApplication()
        app.launchArguments = ["testMode"]
        app.launch()

        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }

    func testExample() {
        // Use recording to get started writing UI tests.
        // Use XCTAssert and related functions to verify your tests produce the correct results.
    }

}


extension UIApplication {
    public static var isRunningTest: Bool {
        return ProcessInfo().arguments.contains("testMode")
    }
}

Ensuite, appelez simplement UIApplication.isRunningTest dans votre code.

1
GregP

Dans Swift 3, vous pouvez rechercher la clé XCInjectBundleInto ou quelque chose commençant par XC.

let isInTestMode = ProcessInfo.processInfo.environment["XCInjectBundleInto"] != nil

Cela fonctionne aussi sous OS X.

0
Oleander