iOS unité de test: Comment créer/mettre à jour/examiner firstResponder?
Comment écrivez-vous des premiers intervenants des tests unitaires?
Je suis en train d'écrire un test pour confirmer qu'une méthode active pour le prochain champ de texte. controller
est un descendant de UIViewController
. Mais cette phase exploratoire test échoue:
- (void)testFirstResponder
{
[controller view];
[[controller firstTextField] becomeFirstResponder];
STAssertTrue([[controller firstTextField] isFirstResponder], nil);
}
La première ligne entraîne l'affichage d'être chargé de façon à ce que ses points de vente sont en place. Les champs de texte sont non-nulle. Mais le test ne passe jamais.
Je devine que becomeFirstResponder
ne définit pas les premiers à avoir répondu tout de suite, mais les horaires pour plus tard. Donc, il y a une bonne façon d'écrire un test unitaire contre elle?
Tirant réponse de commentaire à accepté de répondre... Laisser les choses s'exécuter pendant un court laps de temps:
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate date]];
J'ai trouvé aussi j'ai besoin de créer un UIWindow et de la baisse de la vue du contrôleur de vue, comme indiqué dans la plus upvoted réponse.
OriginalL'auteur Jon Reid | 2011-05-21
Vous devez vous connecter pour publier un commentaire.
Je suppose que la gestion/modifier le premier intervenant de la chaîne est en quelque sorte accompli dans la boucle principale, lorsque l'INTERFACE utilisateur est mise à jour de la préparation pour le prochain événement de la manipulation. Si cette hypothèse est correcte, je voudrais simplement faire ce qui suit:
Note: j'ai utilisé une 0.0 retard parce que je veux simplement que le message est mis sur la file d'attente d'événements et expédiés dès que possible. J'ai juste besoin d'un moyen de revenir à la boucle principale, pour son ménage. Cela devrait produire aucun retard dans votre cas. Si vous êtes l'exécution de plusieurs essais du même genre, c'est à dire à plusieurs reprises de changer le contrôle qui est le premier intervenant, cette technique devrait garantir que tous ces événements correctement commandés avec ceux générés par
performSelector
.Si vous exécutez vos tests à partir d'un autre thread, vous pouvez utiliser
– performSelectorOnMainThread:withObject:waitUntilDone:
STAssertTrue
àSTAssertFalse
ne fait aucune différence.Bon, cela ne fonctionnera pas... comme une autre astuce, je viens de trouver que vous pouvez exécuter pour un certain temps l'exécution de la boucle avant de tester la condition:
[[NSRunLoop currentRunLoop] runUntilDate:fiveSecondsFromNow];
(à partir de: stackoverflow.com/questions/1077737/...). Je ne suis pas entièrement sûr que cette solution est vraiment "élégant", mais il devrait fonctionner et peut être adapté pour les "petits" cas (lorsque vous n'avez pas vraiment besoin d'aller avec Frank)...Excellent! Même en spécifiant une durée d'exécution de zéro fait le tour.
OriginalL'auteur sergio
À l'aide de Xcode 5.1 et
XCTestCase
, cela semble fonctionner ok:Pour une vue/sous-vue de devenir intervenant de première ligne, il doit être partie d'un point de vue de la hiérarchie, en ce sens que sa racine de la vue de la fenêtre de propriété doit être ensemble.
Jon et Sergio mentionner que vous avez peut-être besoin de
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate date]]
après l'appel debecomeFirstResponder
sur de votre choix sous-vue, mais j'ai trouvé que ce n'était pas nécessaire dans notre cas.Cependant, votre kilométrage peut varier (même selon la version de Xcode que vous utilisez), de sorte que vous peut ou peut ne pas avoir besoin d'inclure de tels appels.
Comme d'iOS 10.3, cela fonctionne sans en faire la clé de la fenêtre.
OriginalL'auteur JRG-Developer
Vous devez vous assurer que le champ est installé dans le point de vue de la hiérarchie.
Si la vue de la fenêtre des biens détient un UIWindow objet, il a été installé en vue de la hiérarchie; si elle renvoie nil, la vue est détaché de toute hiérarchie.
J'espère que cela aide....
J'ai maintenant ma réponse. +1 pour remplir la partie du puzzle.
OriginalL'auteur adam