IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Dart Discussion :

[Flutter] Tests : d'où sort le widget HeroControllerScope ?


Sujet :

Dart

  1. #1
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    729
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 729
    Par défaut [Flutter] Tests : d'où sort le widget HeroControllerScope ?
    Bonjour.

    J'ai un test unitaire qui échoue
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    ══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
    The following TestFailure was thrown running a test:
    Expected: exactly one matching node in the widget tree
      Actual: _WidgetPredicateFinder:<zero widgets with widget matching predicate (Closure: (Widget) =>
    bool) (ignoring offstage widgets)>
       Which: means none were found but one was expected
    En utilisant debugDumpApp();, je me rends compte que l'application ressort le widget HeroControllerScope :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    AutomatedTestWidgetsFlutterBinding - DEBUG MODE
    [root](renderObject: RenderView#ae39a)
    └View-[GlobalObjectKey TestFlutterView#81a0a]
     └_ViewScope
      └_MediaQueryFromView(state: _MediaQueryFromViewState#6ab7a)
       └MediaQuery(...)
        └StreamBuilder<XFile>(state: _StreamBuilderBaseState<XFile, AsyncSnapshot<XFile>>#d6910)
         └BlocProvider<BlocXXX>(state: ProviderState#31496)
          └MaterialApp(state: _MaterialAppState#41775)
           └ScrollConfiguration(behavior: MaterialScrollBehavior)
            └HeroControllerScope
    ...
                                                         └AnimatedTheme(duration: 200ms, state: _AnimatedThemeState#ba34b(ticker inactive, ThemeDataTween(ThemeData#662fa → ThemeData#662fa)))
                                                          └Theme(ThemeData#662fa, dependencies: [DefaultSelectionStyle])
                                                           └_InheritedTheme
                                                            └CupertinoTheme(...)
                                                             └_InheritedCupertinoTheme
    ....
    Je ne sais vraiment pas d'où ça sort, à aucun moment je n'ai utilisé HeroControllerScope, et il n'apparait lors d'un Ctrl+F que dans flutter\SDK\packages\flutter\lib\src\.

    Le test en question :
    Code dart : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    void main() {
      TestWidgetsFlutterBinding.ensureInitialized();
    
      group("Bottom bar", () {
        late BlocXXX blocXXX;
        late StreamBuilder<XFile> testedStream;
    
        Widget snapshotBottomBar(BuildContext context, AsyncSnapshot<XFile> snapshot) {
          return BlocProvider<BlocXXX>(
              bloc: blocXXX,
              child: const MaterialApp(
                locale: Locale('fr', 'FR'),
                localizationsDelegates: [
                  DefaultWidgetsLocalizations.delegate,
                  DefaultMaterialLocalizations.delegate
                ],
                home: BottomBar("_title"))
          );
        }
    
        setUp(() {
          blocXXX = BlocXXX();
          testedStream = StreamBuilder(
              initialData: XFile("lalilulelo"),
              stream: blocXXX.stream,
              builder: snapshotBottomBar
          );
        });
    
        testWidgets('nominal', (WidgetTester tester) async {
          FlutterError.onError = ignoreOverflowErrors;
          await tester.pumpWidget(testedStream);
    
          debugDumpApp();
    
          expect(
              find.byWidgetPredicate((widget) => widget is FloatingActionButton &&
                  widget.child == const Icon(Icons.camera)
              ),
              findsOneWidget);
        });
      });
    }

    Note : j'utilise l'architecture BLoC, qui complique sensiblement les tests... à mon grand désarroi. Mais ça fonctionne.
    Note 2 : la partie ignoreOverflowErrors et TestWidgetsFlutterBinding.ensureInitialized(); proviennent de cette page (pour ignorer les erreurs de RenderFlex Overflow).

    Le BottomBar utilise cette hiérarchie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class BottomBar extends StatelessWidget {
      Directionality(
        SizedBox(
          Column(
            Container(
              Text(),
            ),
            Container(
              StreamBuilder<XFile>(
                Row(
                  FloatingActionButton(),
                  FloatingActionButton(),
                  FloatingActionButton()
                )
              ),
            ),
          )
        ),
      )
    }
    Quant au bloc il est simplissime :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class BlocXXX extends Bloc {
      XFile? selected;
      final StreamController<XFile> _imgCtrl = StreamController<XFile>();
      Stream<XFile> get stream => _imgCtrl.stream;
      Sink<XFile> get sink => _imgCtrl.sink;
     
      // D'autres fonctions
    }
    Je jette une bouteille à la mer. Est-ce que quelqu'un a déjà eu ce HeroController qui sort de nulle part ? Pourquoi je ne retrouve pas ma BottomBar lors du test ?

    J'avoue que je sèche.

  2. #2
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2015
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2015
    Messages : 77
    Par défaut
    Pour moi la notion de 'Hero' dans Flutter est lié au rechargement des widgets dans l'arbo et éventuellement la notion d'animation (entre ces rechargements).
    Ce 'HeroControllerScope' doit être un truc interne pour piloter le système de Hero.

    Est-ce que ton stream sert à recharger des widgets ou à effectuer une animation ?

    Ton test crash mais est ce que la fonctionnalité coté run fonctionne elle ?

    Je ne fais pas encore de TU sous Flutter mais il y a sans doute un truc dans ta mécanique de test qui procède différemment que le run et qui n'aime pas ton Stream.

  3. #3
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    729
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 729
    Par défaut
    Bonjour.

    Citation Envoyé par dorus-one Voir le message
    Ton test crash mais est ce que la fonctionnalité coté run fonctionne elle ?
    Oui, je n'ai pas regardé la hiérarchie des widgets, mais tout fonctionne parfaitement côté run.

    Citation Envoyé par dorus-one Voir le message
    Est-ce que ton stream sert à recharger des widgets ou à effectuer une animation ?
    C'est lié à l'architecture BLoC. Pour être honnête c'est le seul moyen que j'ai trouvé pour tester le widget en lui fournissant des données.

    Si ça vient des stream, ça me donne une piste pour avancer

  4. #4
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2015
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2015
    Messages : 77
    Par défaut
    N'hésite pas à nous tenir au courant de l'avancée de la résolution de ton problème.
    Cela pourra aider d'autres dev (et moi ca m'intéresse également)

Discussions similaires

  1. Réponses: 0
    Dernier message: 14/01/2013, 10h55
  2. [1.x] test sur une valeur du widget
    Par Ontolingua dans le forum Symfony
    Réponses: 6
    Dernier message: 22/10/2010, 09h40
  3. Test sur des widget Tk
    Par Perl53 dans le forum Interfaces Graphiques
    Réponses: 0
    Dernier message: 14/11/2008, 16h18
  4. Trier un tableau() as integer sans Sort - Deux méthodes testées
    Par ouskel'n'or dans le forum Macros et VBA Excel
    Réponses: 26
    Dernier message: 25/10/2008, 22h52

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo