SenTestKit & Tests U: afficher des msgs sur le mac qd on teste sur le Simulateur

AliGatorAliGator Membre, Modérateur
juin 2009 modifié dans API UIKit #1
[EDIT]
Titre modifié pour mieux coller à  l'évolution du sujet
(le précédent titre de ce sujet était "communiquer entre l'iPhone Simulator et le Mac : NSDistributedNotifs down")
[/EDIT]



Hello les gens,

Alors voilà  pour quelques besoins ponctuels il m'est déjà  arrivé d'utiliser le NSDistributedNotificationCenter sur une appli iPhone pour le cas où j'exécute mon application dans l'iPhone Simulator (les envoyer de l'iPhone Simu et de les écouter dans une appli Mac, typiquement)

Des exemples typiques d'utilisation étaient :
- de pouvoir coupler l'accéléromètre de mon MacBookPro à  l'accéléromètre de l'iPhone Simulator (j'avais une classe dans mes applis qui en mode iPhone Simulator remplaçait le UIAccelerometer et écoutait les NSDistributedNotifications envoyée par une appli mac maison envoyant les données de l'accéléromètre du mac)
- de pouvoir faire envoyer des messages à  l'iPhone Simulator et les récupérer pour les afficher dans une appli Mac à  des fins de debug (en particulier pour les tests unitaires). Une sorte de NSLog avancé, envoyé dans l'appli mac pour affichage dans TableView et tri possible en plus, etc.
...


Mon problème, c'est que j'étais bien content de cette astuce, et donc de voir que sur l'iPhone Simulator le NSDistributedNotificationCenter existait (ça m'a étonné vu que l'iPhone OS n'est pas multitâches) et était partagé avec celui du mac... Mais depuis le SDK 3.0 ce n'est plus le cas ! La classe NSDistributedNotificationCenter n'existe plus dans le SDK 3.0 (ce qui somme toute est compréhensible, en fait, elle n'aurait jamais dû être présente).

Du coup, je cherche comment je pourrais retrouver une telle fonctionnalité, à  savoir dans le cas où j'exécute mon appli sur l'iPhone Simulator pouvoir faire transiter des infos du Mac vers l'iPhone Simulator et vice-versa.

Le but étant si possible de pouvoir intégrer ça facilement, avec un #define (ou au pire une fonction inline), mais éviter tout un branle bas de combat pour envoyer ce message du moins de l'iPhone Simulator au Mac. L'avantage des notifications c'est qu'on a juste à  demander d'envoyer et basta, on a pas à  initialiser un truc comme ça pourrait être le cas avec une solution basée sur des sockets... qui me semble un peu lourde à  mettre en place, elle ?

Réponses

  • LastikoLastiko Membre
    12:50 modifié #2
    j'ai bien l'impression que tu vas devoir passer par les sockets  :o
  • AliGatorAliGator Membre, Modérateur
    12:50 modifié #3
    J'ai commencé à  faire un test avec les named pipes en non bloquant (au cas où y'a pas de reader de l'autre côté) et ça m'a l'air de marcher pas trop mal. Seul inconvénient ça oblige à  faire un open et un close et à  avoir une variable d'instance pour stocker le file descriptor.

    Pour les TestsU (puisque dans mon cas c'est le cas le plus urgent qui me préoccupe) avec SenTestKit ça me gène pas tant que ça, je peux ouvrir mon pipe dans le -setUp et le fermer dans le -tearDown, donc c'est encore acceptable. En ouvrant avec O_NONBLOCK ça permet si le pipe n'est pas lu de l'autre côté de pas bloquer l'appli pour autant, donc ça va.
  • AliGatorAliGator Membre, Modérateur
    juin 2009 modifié #4
    Bon la solution que j'ai adoptée pour mon cas :

    #define REPORT_PIPE_NAME &quot;/tmp/SenTestKitReport&quot;<br />static int __SenTestKit_ReportPipe;<br />#define STMessage(format, ...) do { &#092;<br />	if (__SenTestKit_ReportPipe&lt;=0) __SenTestKit_ReportPipe = open(REPORT_PIPE_NAME, O_WRONLY | O_NONBLOCK); &#092;<br />	if (__SenTestKit_ReportPipe&gt;0) { &#092;<br />		NSString* __str = [NSString stringWithFormat:@&quot;%@ : %@&#092;n&quot;,[NSDate date],[NSString stringWithFormat:format, ##__VA_ARGS__]]; &#092;<br />		write(__SenTestKit_ReportPipe,[__str cStringUsingEncoding:NSUTF8StringEncoding], [__str length]); &#092;<br />	} else { &#092;<br />		NSLog(format, ##__VA_ARGS__); &#092;<br />	} &#092;<br />} while(0)
    
    Je met ça dans un .h que j'inclus dans tous mes tests unitaires, et j'utilise ça comme ça dans le code :
    -(void)test_01<br />{<br />  STMessage(@&quot;Starting test 01&quot;);<br />  int v = [self dummyMethod];<br />  STMessage(@&quot;v = %d&quot;,v);<br />  STAssertEqual(v,5,@&quot;the returned value should be 5 !!&quot;);<br />  STMessage(@&quot;End of test 01&quot;);<br />}
    
    Si j'exécute mes tests U comme ça sans rien faire de particulier, les STMessages auront le même effet qu'un NSLog et seront "mélangés" avec les build results (pas très lisible mais au moins ils seront affichés).

    Si je veux les séparer des build results, il me suffit de lire la FIFO (pipe) nommée /tmp/SenTestKitReport. Ce qui peut se faire via un programme tierce... ou simplement via le terminal, en tapant
    cat /tmp/SenTestKitReport
    
    . Cela va simplement lire la FIFO au fur et à  mesure qu'on écrit dedans, en attendant que les données arrivent (attente bloquante).

    Bien sûr il faut avoir créé la FIFO avant pour que STMessage arrive à  écrire dedans (à  l'aide de [tt]mkfifo[/tt] typiquement). Pour faciliter les choses, j'ai fait un script shell tout bête qui va créer la FIFO /tmp/SenTestKitReport si elle n'existe pas avant d'aller lire dedans :
    #!/bin/sh<br /><br />REPORT_PIPE_NAME=${1:-/tmp/SenTestKitReport}<br /><br />if [ &#092;! -p &quot;$REPORT_PIPE_NAME&quot; ]; then    # if the FIFO does not exist yet<br />  if [ -e &quot;$REPORT_PIPE_NAME&quot; ]; then rm &quot;$REPORT_PIPE_NAME&quot;; fi    # if file exist but not a FIFO, remove it<br />  mkfifo &quot;$REPORT_PIPE_NAME&quot;     # create the FIFO<br />fi<br /><br /># Start listening to data sent to the FIFO and print it to stdout<br />echo<br />echo<br />echo &quot; === SenTestKit Report ===       ($REPORT_PIPE_NAME)&quot;<br />echo<br />echo<br />cat &quot;$REPORT_PIPE_NAME&quot;<br />echo<br />echo &quot; ===-------------------=== &quot;<br />echo<br />
    
    A sauver par exemple dans un fichier SenTestKitReadReport.sh (et donner les droits d'exécution via [tt]chmod +x SenTestKitReadReport.sh[/tt]).

    En conclusion :
    - définir la macro STMessage comme ci-dessus dans un header
    - dans les tests U, utiliser STMessage en lieu et place de NSLog
    - comme ça si vous voulez séparer les messages envoyés par STMessage des autres (et des build results avec lesquels ils s'affichent habituellement dans le cas des tests U), il suffit d'ouvrir un terminal et d'exécuter le script shell sus-cité avant de lancer vos tests. Les messages seront alors affichés dans le terminal où vous avez lancé ce script (dans son stdout quoi) au lieu d'être dans la console / build results.
  • AliGatorAliGator Membre, Modérateur
    juin 2009 modifié #5
    STOP !


    J'ai trouvé bien plus simple en fouillant dans SenTestKit (mais c'est assez caché) : si on écrit dans stderr suivant un formalisme bien particulier, à  savoir "[tt]chemin vers fichier:ligne: keyword: message[/tt]" où [tt]keyword[/tt] vaut "[tt]note[/tt]", "[tt]warning[/tt]" ou "[tt]error[/tt]"... du moment que ça respecte ce format cela va respectivement s'afficher dans les build results sous forme de note, warning ou erreur... Faut le savoir !

    D'ailleurs si qqun trouve de la doc là  dessus disant que c'est uniquement ces lignes là  qu'affichent le panneau "Build results", voire les mots clés qu'on peut mettre s'il y en a d'autres que "note" "warning" ou "error"...


    Du coup mes macros deviennent 100x plus simple, et pas besoin de pipe nommé ou autre chose. Ca résoud en fait uniquement mon problème actuel qui est d'afficher des infos facilement lisibles dans le panneau "Build Result" (notes informatives au fur et à  mesure que les tests U sont exécutés), pas le cas plus générique d'envoyer des infos de l'iPhone Simulator au Mac... mais pour le cas qui m'intéresse, ça correspond quand même.

    #define STMessage(format, ...) fprintf(stderr,&quot;%s:%d: note: ### %s&#092;n&quot;,__FILE__,__LINE__,[[NSString stringWithFormat:format, ##__VA_ARGS__] cStringUsingEncoding:NSUTF8StringEncoding])<br />#define STWarning(format, ...) fprintf(stderr,&quot;%s:%d: warning: ### %s&#092;n&quot;,__FILE__,__LINE__,[[NSString stringWithFormat:format, ##__VA_ARGS__] cStringUsingEncoding:NSUTF8StringEncoding])<br />
    
    Et en plus ça fait les petites bulles jaunes ou rouges automatiquement dans Xcode ensuite :)
  • LastikoLastiko Membre
    12:50 modifié #6
    http://github.com/gabriel/gh-unit/tree/master

    je sais pas si ca va te servir mais bon .....
  • AliGatorAliGator Membre, Modérateur
    12:50 modifié #7
    Oui c'est une autre alternative que le SenTestKit (qui lui est fourni avec les DevTools d'Apple) pour les tests unitaires, mais je n'ai pas l'impression qu'il définisse de même des macros pour afficher des messages informatifs, lui non plus ? genre GHMessage ou GHWarning ?

    Par contre il rajoute une chose que SenTestKit n'as pas, ce sont les tests asynchrones. De là  à  ce qu'il sache aussi gérer les tests interactifs, ça pourrait m'intéresser, à  creuser... enfin pour le prochain projet, car là  je vais pas migrer tous mes tests U vers GitHub :P
  • LastikoLastiko Membre
    12:50 modifié #8
    je me doute mais bon test le car ca peut te simplifier la vie qui sait , enfin apres tu peux le modifier selon tes besoins aussi :D
  • AliGatorAliGator Membre, Modérateur
    12:50 modifié #9
    Si j'avais du temps je m'en donnerai à  coeur joie :P

    Là  j'ai déjà  du retard sur le projet n°1 pour lequel j'ai besoin de faire ces Tests U à  livrer au client, et faut pas que je traà®ne sur le projet n°2 non plus pour pas commencer à  prendre du retard dessus... et faudrait p'tet que je rentre chez moi aussi :P

    Mais courant Juillet où j'espère le planning sera moins chargé, je tâcherai de jeter un oeil car il peut en effet être intéressant. Et du coup applicable aux projets futurs une fois que j'aurais pris le temps de le tester :P
    Donc merci pour le lien en tout cas ;)
  • LastikoLastiko Membre
    12:50 modifié #10
    enfin le jour ou tu rentre chez toi ( enfin si il arrive ) , et que tu as tester , je veux bien que tu me tienne au jus car ton sujet m'a bien intéréssé
    ;-)
  • AliGatorAliGator Membre, Modérateur
    12:50 modifié #11
    En fait faudrait (ça doit bien exister qqpart) un comparatif entre GitHub et le SenTestKit, pour savoir ce que le premier offre de plus que le 2e (que j'utilise actuellement).

    Le SenTestKit (ce qu'utilisent les OC Units quoi) est intégré à  Xcode -- qui nous permet de créer des "Test Bundles" (=ocunit) comme nouveau target sans avoir rien de plus à  faire -- donc c'est pratique. Et les tests unitaires peuvent se lancer tout seuls après la compilation, ça marche bien.

    Ses limitations connues pour l'instant depuis que je l'utilise c'est qu'il ne fonctionne qu'avec l'iPhone Simulator et pas le device (ça c'est connu), et qu'à  l'usage j'ai trouvé dommage qu'il manque les macros que j'ai cité dans mon post précédent, à  savoir STMessage et STWarning permettant d'afficher des messages d'info façon lisible pendant les tests(et distrincte de tout le blabla qui est écrit dans la console de build car tout mélangé c'est pas lisible sinon)... et sinon les tests interactifs.

    Pour les tests asynchrones j'ai fait une boucle qui attend la réponse avec un timeout, ça va c'est acceptable (faut juste penser à  demander à  la [NSRunLoop mainRunLoop] de tourner un peu pendant qu'on est dans le "while" d'attente de la réponse). C'est à  priori ce qui est précaunisé, d'ailleurs je pense que c'est comme ça que l'implémente GitHub aussi.
  • AliGatorAliGator Membre, Modérateur
    juin 2009 modifié #12
    [EDIT]J'ai découpé le sujet en deux, pour séparer l'aspect Tests U d'origine (qui déjà  dérivait de l'aspect "faire communiquer l'iPhone Simulator et le Mac ^^)) de notre discussion sur les SCM et versionning (lien).[/EDIT]
Connectez-vous ou Inscrivez-vous pour répondre.