2017-09-26 9 views
2

J'ai une classe Spock qui, lorsqu'elle est exécutée en tant que suite de tests, lance Unable to resolve iconRow as content for geb.Page, or as a property on its Navigator context. Is iconRow a class you forgot to import? sauf si j'annote ma classe avec @Stepwise. Cependant, je vraiment ne veux pas que l'exécution du test s'arrête sur le premier échec, ce que fait @Stepwise.La classe ne peut pas résoudre le module en tant que contenu sauf si @Stepwise est utilisé

J'ai essayé d'écrire (copier et coller) ma propre extension en utilisant this post, mais je reçois toujours ces erreurs. Il utilise mon extension, comme j'ai ajouté quelques instructions de journalisation qui ont été imprimées sur la console.

Voici un de mes modules:

class IconRow extends Module { 
    static content = { 
     iconRow (required: false) {$("div.report-toolbar")} 
    } 
} 

Et une page qui l'utilise:

class Report extends SomeOtherPage { 
    static at = {$("div.grid-container").displayed} 

    static content = { 
     iconRow { module IconRow } 
    } 
} 

Et un extrait du test qui échoue:

class MyFailingTest extends GebReportingSpec { 

    def setupSpec() { 
     via Dashboard 
     SomeClass.login("SourMonk", "myPassword") 
     assert page instanceof Dashboard 

     nav.goToReport("Some report name") 
     assert page instanceof Report 
    } 

    @Unroll 
    def "I work"() { 
     given: 
     at Report 

     expect: 
     this == that 

     where: 
     this << ["some list", "of values"] 
     that << anotherModule.someContent*[email protected] 
    } 

    @Unroll 
    def "I don't work"() { 
     given: 
     at Report 

     expect: 
     this == that 

     where: 
     this << ["some other", "list", "of values"] 
     that << iconRow.columnHeaders*.attr("innerText")*.toUpperCase() 
    } 
} 

Lorsque exécuté en tant que suite I work passe et I don't work échoue car il ne peut pas identifier "iconRow" comme contenu pour la page. Si je change l'ordre des cas de test, I don't work passera et I work échouera. Sinon, si j'exécute chaque test séparément, ils passent tous les deux.

Ce que j'ai essayé:

  • Ajout/suppression de la required: true propriété du contenu des modules
  • préfixant le nom du module avec la classe, comme IconRow.iconRow
  • Définir mes modules @Shared statiques propriétés
  • Initialiser les modules à la fois dans et en dehors de mon setupSpec()
  • thodes dans la classe de chaque module qui renvoient le module et le référencement de contenus tels que IconRow.getIconRow().columnHeaders*.attr("innerText")*.toUpperCase()
  • déplacer le contenu de mon setupSpec() dans setup()
  • Ajout autoClearCookies = false dans mon GebConfig.groovy
  • Faire une variable et le préfixe @Shared Report report tous les modules avec cette tels que report.iconRow

Note très particulière à ce sujet dernier point - il se résout comme par magie les modules qui se font pas le préfixe - il ne résoudra pas report.IconRow mais résoudra juste iconRow - absolument bizarre, parce que si je supprime cette variable, le module qui fonctionnait tout à coup auparavant ne peut pas être résolu à nouveau. J'ai même essayé de déclarer cette variable et de ne rien préfixer, ce qui n'a pas fonctionné non plus.

Un autre problème que je continue à frapper ma tête contre le mur avec est que je ne suis pas sûr de le problème est. L'erreur qu'il génère me porte à croire qu'il s'agit d'un problème de configuration de projet, mais l'exécution de chaque fonctionnalité fonctionne parfaitement, de sorte qu'il semble résoudre les classes très bien. D'autre part, c'est peut-être un problème avec la session et/ou les cookies?Bien que je n'ai encore vu aucune documentation officielle à ce sujet, il semble y avoir un consensus général (d'autres articles et articles que j'ai lus) que l'utilisation de @Stepwise maintiendra votre session entre les méthodes d'entités. Si tel est le cas, pourquoi mon extension ne fonctionne-t-elle pas? C'est à peu près un copier-coller de @Stepwise sans la méthode skipFeaturesAfterFirstFailingFeature (je peux poster si nécessaire), à ​​moins qu'il y ait d'autres choses qui se passent dans les coulisses avec @Stepwise. Excuses pour le mur de texte, mais j'ai essayé de comprendre ceci pendant environ 6 heures maintenant, ainsi mon cerveau est assez frit.

Répondre

2

Geb a un support spécial pour @Stepwise, si une spécification est annotée avec elle, elle n'appelle pas resetBrowser() après chaque test, elle est appelée à la fin de la spécification. Voir le code sur github

Donc, fondamentalement, vous devez changer votre setupSpec à setup de sorte qu'il sera exécuté avant chaque test. En ce qui concerne votre observation, si vous effectuez un test ciblé, le setupSpec est exécuté pour ce test et passe ainsi. Le problème se pose, que le nettoyage est invoqué par la suite et réinitialise le navigateur, rompant les tests suivants.

EDIT

Je vis à vis de votre utilisation where blocs, tout dans le bloc où doit être statique (@Shared) disponibles, en utilisant des constructions de niveau de l'instance ne fonctionnera pas. Réinitialiser le navigateur va également tuer toutes les références, donc juste l'obtenir avant de ne pas travailler non plus. Fondamentalement, n'utilisez pas les objets Geb dans les blocs where!

En regardant votre code, je ne vois aucune raison d'utiliser des tests pilotés par les données ici.

  1. Ceci peut être facilement fait avec une affirmation dans un test normal
  2. Il est bon pour les tests unitaires à tester juste une chose. Cependant, Geb n'est pas un test unitaire mais un test d'acceptation/d'interface. Le problème ici est qu'ils sont beaucoup plus lents que les tests unitaires et il est logique de combiner des assertions sensibles en un seul test.

class MyFailingTest extends GebReportingSpec {  
    def setup() { 
     via Dashboard 
     SomeClass.login("SourMonk", "myPassword") 
     assert page instanceof Dashboard 

     nav.goToReport("Some report name") 
     assert page instanceof Report 
    } 

    def "I work"() { 
     given: 
     at Report 

     expect: 
     ["some list", "of values"] == anotherModule.someContent*[email protected] 
    } 

    def "I don't work"() { 
     given: 
     at Report 

     expect: 
     ["some other", "list", "of values"] == iconRow.columnHeaders*.attr("innerText")*.toUpperCase() 
    } 
} 
+0

J'ai donc essayé de déplacer le contenu de mon setupSpec() à installer juste() et les essais sont encore défaillants, avec la même erreur. Y a-t-il moyen de surcharger ces méthodes dans GebSpec? – SourMonk

+0

@SourMonk J'ai mis à jour la réponse –

+0

Merci, Leonard qui travaille pour moi - je suppose que j'ai eu un simple malentendu sur le framework. Alors qu'est-ce qui permet d'accéder aux objets Geb dans 'attendez' mais pas 'où'? – SourMonk