0
votes

Comment tester une méthode qui répartit le travail de manière asynchrone dans Swift

J'ai besoin d'écrire le test unitaire pour la méthode suivante

func setLabelText(msg: String) {
     DispatchQueue.main.async {
          self.label.text = msg
      }
  }


4 commentaires

Dans votre exemple performUIUpdate , partagez une idée à laquelle vous avez pensé. Mais pourriez-vous partager quelque chose de similaire au code que vous souhaitez tester? Sinon, nous offrons des réponses contre une question vague. Rendez la question plus précise.


J'ai besoin d'écrire le test pour la méthode suivante func setLabelText (msg: String) {DispatchQueue.main.async {self.label.text = msg}}


Pouvez-vous modifier votre question pour y mettre cela?


@JonReid mis à jour


3 Réponses :


0
votes

Bonjour à mon avis, l'utilisation de XCTestExpectation pourrait en bénéficier car cette api était destinée à tester les opérations asynchrones (vous pouvez en savoir plus ici )

En ce qui concerne la comparaison entre les deux, la seule chose à laquelle je pourrais penser est qu'avec XCTestExpectation vous pourrez tester les délais d' XCTestExpectation serveur ( XCTestExpectation que votre API ne répond pas dans le temps prévu. URLSession a un délai par défaut de 60 secondes) avec un code d'erreur et un message spécifiques.


0 commentaires

0
votes

Vous pouvez ajouter une fermeture d'achèvement à displayMessage et appeler expectation.fulfill () dans test. Une autre approche totalement différente consiste à mettre en œuvre un modèle de conception de présentation comme le coordinateur ou le présentateur. Dans ce cas, toute votre présentation d'interface utilisateur sera résumée à des méthodes non asynchrones.


0 commentaires

0
votes

Je vais appliquer quelques techniques de test unitaire iOS par exemple . Supposons que votre configuration de test crée déjà un contrôleur de vue et appelle loadViewIfNeeded() pour connecter toutes les prises. (Ceci provient du chapitre 5, "Charger les contrôleurs de vue".) Et que ce contrôleur de vue est dans une propriété que je sut (ce qui signifie Système sous test).

Si vous écrivez un setLabelText(msg:) test pour appeler setLabelText(msg:) , puis vérifiez immédiatement l'étiquette du contrôleur de vue, cela ne fonctionnera pas.

Si vous aviez un envoi vers un thread d'arrière-plan, nous aurions besoin du test pour attendre la fin du thread. Mais ce n'est pas le cas pour ce code.

Votre code de production appelle setLabelText(msg:) partir de l'arrière-plan. Mais le code de test s'exécute sur le thread principal. Puisqu'il est déjà sur le thread principal, tout ce que nous avons à faire est d'exécuter la boucle d'exécution une fois de plus. Vous pouvez exprimer cela avec une fonction d'assistance que j'introduis dans le chapitre 10, "Test de la navigation entre les écrans:"

func test_setLabelText_withoutExecutingMainRunLoop_shouldNotUpdateLabel() throws {
    sut.label.text = "123"
    
    sut.setLabelText(msg: "TEST")
    
    XCTAssertEqual(sut.label.text, "123")
}

Avec cela, voici un test qui fonctionne:

func test_setLabelText_thenExecutingMainRunLoop_shouldUpdateLabel() throws {
    sut.setLabelText(msg: "TEST")
    executeRunLoop()
    
    XCTAssertEqual(sut.label.text, "TEST")
}

Cela teste avec succès la méthode et se termine rapidement. Mais que se passe-t-il si un autre programmeur vient et modifie setLabelText(msg:) , en tirant l'appel self.label.text = msg dehors de DispatchQueue.main.async ? Je décris ce problème au chapitre 13, «Test des réponses (et fermetures) du réseau», dans une section intitulée «Garder le code asynchrone dans sa fermeture». Fondamentalement, nous voulons tester que l'étiquette ne change pas lorsque la fermeture distribuée n'est pas exécutée. Nous pouvons le faire avec un deuxième test:

func executeRunLoop() {
    RunLoop.current.run(until: Date())
}


0 commentaires