Puis-je spécifier un groupe à l’échelle de la classe sur un scénario de test TestNG ?

StackOverflow https://stackoverflow.com/questions/9044

  •  08-06-2019
  •  | 
  •  

Question

J'ai une classe de base qui représente un test de base de données dans TestNG, et je tiens à préciser que toutes les classes s'étendant de cette classe appartiennent à un groupe "db-test", mais j'ai trouvé que cela ne semble pas possible.J'ai essayé l'annotation @Test :

@Test(groups = { "db-test" })
public class DBTestBase {
}

Cependant, cela ne fonctionne pas car l'annotation @Test tentera de transformer un certain nombre de méthodes en tests, et des avertissements/erreurs apparaîtront dans Eclipse lorsque les tests sont exécutés.

J'ai donc essayé de désactiver le test, pour qu'au moins les groupes soient attribués :

@Test(enabled = false, groups = { "db-test" })
public class DBTestBase {
}

mais alors tout @BeforeTest (et autres annotations similaires) est AUSSI désactivé...ce qui n'est bien sûr pas ce que je souhaite.

J'aimerais un moyen d'annoter une classe comme appartenant à un type particulier de groupe, mais cela ne semble pas tout à fait possible dans TestNG.Quelqu'un a-t-il d'autres idées ?

Était-ce utile?

La solution

La réponse passe par une coutume org.testng.IMethodSelector:

C'est inclureMéthode() peut exclure n'importe quelle méthode de notre choix, comme une méthode publique non annotée.

Cependant, pour enregistrer une coutume Java MethodSelector, vous devez l'ajouter au Test XML instance gérée par n'importe quel TestRunner, ce qui signifie que vous avez besoin de la vôtre TestRunner personnalisé.

Mais, pour créer un TestRunner personnalisé, vous devez enregistrer un TestRunnerFactory, à travers le -usine de test option.

MAIS ce -testrunfactory n'est JAMAIS pris en compte par TestNG classe...vous devez donc également définir une classe TestNG personnalisée :

  • afin de remplacer la méthode configure(Map),
  • afin que vous puissiez réellement définir TestRunnerFactory
  • TestRunnerFactory qui vous construira un TestRunner personnalisé,
  • TestRunner qui définira sur l'instance XMLTest un XMLMethodSelector personnalisé
  • XMLMethodSelector qui construira un IMethodSelector personnalisé
  • IMethodSelector qui exclura toutes les méthodes TestNG de votre choix !

D'accord...c'est un cauchemar.Mais c'est aussi un défi de code, donc ça doit être un peu difficile ;)

Tout le code est disponible sur Extraits de zone D.

Comme d'habitude pour un défi de code :

  • une classe Java (et pas mal de classes internes)
  • copier-coller la classe dans un répertoire 'source/test' (puisque le package est 'test')
  • exécutez-le (aucun argument nécessaire)

Mise à jour de Mike Stone :

Je vais accepter cela parce que cela semble assez proche de ce que j'ai fini par faire, mais j'ai pensé que j'ajouterais également ce que j'ai fait.

Fondamentalement, j'ai créé une annotation Groups qui se comporte comme la propriété groups des annotations Test (et autres).

Ensuite, j'ai créé un GroupsAnnotationTransformer, qui utilise IAnnotationTransformer pour examiner tous les tests et classes de tests en cours de définition, puis modifie le test pour ajouter les groupes, ce qui fonctionne parfaitement avec l'exclusion et l'inclusion de groupes.

Modifiez la version pour utiliser le nouveau transformateur d'annotation, et tout fonctionne parfaitement !

Bien...le seul inconvénient est qu'il n'ajoute pas les groupes aux méthodes non-test...parce qu'au moment où j'ai fait cela, il y avait un autre transformateur d'annotation qui vous permet de transformer TOUT, mais il n'était pas inclus dans le TestNG que j'utilisais pour une raison quelconque...c'est donc une bonne idée de faire en sorte que vos méthodes annotées avant/après soient toujoursRun=true...ce qui me suffit.

Le résultat final est que je peux faire :

@Groups({ "myGroup1", "myGroup2"})
public class MyTestCase {
    @Test
    @Groups("aMethodLevelGroup")
    public void myTest() {
    }
}

Et j'ai fait fonctionner le transformateur avec le sous-classement et tout.

Autres conseils

TestNG exécutera toutes les méthodes publiques d'une classe avec une annotation @Test.Peut-être pourriez-vous modifier les méthodes que vous ne souhaitez pas que TestNG exécute pour qu'elles soient non publiques

Il me semble que c'est ce qui suit défi de code (article wiki de la communauté) :

Comment pouvoir exécuter toutes les méthodes de test de la classe Extended du groupe 'aGlobalGroup' sans :

  • spécifier le groupe 'aGlobalGroup' sur la classe Extended elle-même ?
  • tester les méthodes publiques non annotées de la classe Extended ?

La première réponse est simple :
ajouter une classe TestNG(groups = { "aGlobalGroup" }) au niveau de la classe de base

Ce groupe s'appliquera à toutes les méthodes publiques de la classe Base et de la classe Extended.

MAIS:même les méthodes publiques non testantes (sans annotation TestNG) seront incluses dans ce groupe.

DÉFI:évitez d'inclure ces méthodes non-TestNG.

@Test(groups = { "aGlobalGroup" })
public class Base {

    /**
     * 
     */
    @BeforeClass
     public final void setUp() {
           System.out.println("Base class: @BeforeClass");
     }


    /**
     * Test not part a 'aGlobalGroup', but still included in that group due to the class annotation. <br />
     * Will be executed even if the TestNG class tested is a sub-class.
     */
    @Test(groups = { "aLocalGroup" })
     public final void aFastTest() {
       System.out.println("Base class: Fast test");
     }

    /**
     * Test not part a 'aGlobalGroup', but still included in that group due to the class annotation. <br />
     * Will be executed even if the TestNG class tested is a sub-class.
     */
    @Test(groups = { "aLocalGroup" })
     public final void aSlowTest() {
        System.out.println("Base class: Slow test");
        //throw new IllegalArgumentException("oups");
     }

     /**
      * Should not be executed. <br />
      * Yet the global annotation Test on the class would include it in the TestNG methods...
     */
    public final void notATest() {
       System.out.println("Base class: NOT a test");
     }

    /**
     * SubClass of a TestNG class. Some of its methods are TestNG methods, other are not. <br />
     * The goal is to check if a group specify in the super-class will include methods of this class. <br />
     * And to avoid including too much methods, such as public methods not intended to be TestNG methods.
     * @author <a href="http://stackoverflow.com/users/6309/vonc">VonC</a>
     */
    public static class Extended extends Base
    {
        /**
         * Test not part a 'aGlobalGroup', but still included in that group due to the super-class annotation. <br />
         * Will be executed even if the TestNG class tested is a sub-class.
         */
        @Test
        public final void anExtendedTest() {
           System.out.println("Extended class: An Extended test");
        }

        /**
         * Should not be executed. <br />
         * Yet the global annotation Test on the class would include it in the TestNG methods...
         */ 
        public final void notAnExtendedTest() {
            System.out.println("Extended class: NOT an Extended test");
        }
    }

Je ne sais pas comment fonctionne l'héritage des annotations pour TestNG mais ceci article peut être d'une certaine utilité.

En fait, cela peut mieux aider, regardezheritateGroups.

Vous pouvez spécifier l'annotation @Test au niveau de la méthode qui permet une flexibilité maximale.

public class DBTestBase {

    @BeforeTest(groups = "db-test")
    public void beforeTest() {
        System.out.println("Running before test");
    }

    public void method1() {
        Assert.fail(); // this does not run. It does not belong to 'db-test' group.
    }

    @Test(groups = "db-test")
    public void testMethod1() {
        Assert.assertTrue(true);
    }
}

Est-ce que cela fonctionne pour vous ou il me manque quelque chose dans votre question.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top