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

C++ Discussion :

Logiciel de tests unitaires fait maison


Sujet :

C++

  1. #1
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut Logiciel de tests unitaires fait maison
    Bonjour,

    Je me suis amusé à me créer mon propre logiciel de test unitaire, qui me semble assez simple à utiliser :
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    TEST_FILE_D(Assertions)
    TEST_FILE_D(Exceptions)
     
     
    TEST_SERIE_D(Assertions, success)
    {
        INIT_FUNCTION
        {
            std::cout << "Begin serie" << std::endl;
        };
     
        BEFORE_FUNCTION
        {
            std::cout << "Begin test" << std::endl;
        };
     
        AFTER_FUNCTION
        {
            std::cout << "Test finished" << std::endl;
        };
     
        DESTROY_FUNCTION
        {
            std::cout << "Serie finished" << std::endl;
        };
     
        TEST(success)
        {
            SUCCESS; // quit
        };
     
     
        TEST(success_continue)
        {
            int * i = new int(2);
            C_SUCCESS; // continue
            delete i;
        };
     
        TEST(success_on)
        {
            int i = 3;
            SUCCESS_ON(i == 3); // quit with success if true
            FAIL("ERROR");
        };
     
        TEST(success_continue_on)
        {
            int * i = new int(2);
            C_SUCCESS_ON(*i == 3) // continue
            else
                C_FAIL("ERROR");
            delete i; // we can free this ressource
        };
     
        TEST(empty) // = SUCCESS
        {
        };
     
    };
    END_SERIE
     
     
    TEST_SERIE_D(Assertions, failure)
    {
        int i = 5; // you can declare variables
     
        TEST(failure)
        {
            FAIL("Because"); // quit
        };
     
     
        TEST(failure_continue)
        {
            int * i = new int(2);
            C_FAIL("Because"); // continue
            delete i;
        };
     
        TEST(failure_on)
        {
            FAIL_ON(i == 5, "Error"); // quit with error if true
        };
     
        TEST(failure_continue_on)
        {
            int * i = new int(2);
            C_FAIL_ON(*i == 3, "Error") // continue
            else
                C_SUCCESS;
            delete i; // we can free this ressource
        };
     
    };
    END_SERIE
     
     
    TEST_SERIE_D(Assertions, warning)
    {
        int i; // you can declare variables
     
        INIT_FUNCTION
        {
            i = 5; // and used here;
        };
     
        TEST(warning)
        {
            WARNING("Because"); // quit
        };
     
     
        TEST(warning_continue)
        {
            int * i = new int(2);
            C_WARNING("Because"); // continue
            delete i;
        };
     
        TEST(warning_on)
        {
            WARNING_ON(i == 5, "lu"); // quit with warning if true
        };
     
        TEST(warning_continue_on)
        {
            int * i = new int(2);
            C_WARNING_ON(*i == 3, "warnin") // continue
            else
                C_SUCCESS;
            delete i; // we can free this ressource
        };
     
    };
    END_SERIE
     
     
    TEST_SERIE_D(Assertions, alea)
    {
     
        int tab[4][2][1];
     
        REPEATABLE_TEST(alea)
            VAR(i, tab) // for each i in tab
            VAR(j, i)   // and for each j in i
            VAR(k, j)   // and for each k in j
                START_REPEATABLE_TEST
                {
                    ALEA(k, "Error"); // Error with the value k
                }
        END_REPEATABLE_TEST
     
        REPEATABLE_TEST(alea_continue)
            VAR(i, tab) // for each i in tab
            VAR(j, i)   // and for each j in i
            VAR(k, j)   // and for each k in j
                START_REPEATABLE_TEST
                {
                    int * i = new int;
                    C_ALEA( (std::size_t)j, "Error"); // Error with the value j
                    delete i;
                }
        END_REPEATABLE_TEST
     
        REPEATABLE_TEST(alea_on)
            VAR(i, tab) // for each i in tab
            VAR(j, i)   // and for each j in i
            VAR(k, j)   // and for each k in j
                START_REPEATABLE_TEST
                {
                    ALEA_ON(k, k == 0, "Error"); // Error with the value k
                }
        END_REPEATABLE_TEST
     
        REPEATABLE_TEST(alea_continue_on)
            VAR(i, tab) // for each i in tab
            VAR(j, i)   // and for each j in i
            VAR(k, j)   // and for each k in j
                START_REPEATABLE_TEST
                {
                    int * i = new int;
                    C_ALEA_ON( (std::size_t)i, k == 0, "Error"); // Error with the value i
                    delete i;
                }
        END_REPEATABLE_TEST
     
    };
    END_SERIE
     
    TEST_SERIE_D(Exceptions, no_policy )
    {
        TEST( throws )
        {
            throw int(1);
        };
     
        TEST( throws_with )
        {
            FAIL_ON_CATCH("Erreur !!!");
            throw int(2);
        };
     
        TEST( nothrow )
        {
     
        };
    };
    END_SERIE
     
     
    TEST_SERIE_D(Exceptions, policy)
    {
        POLICY_WARNING_ON_CATCH("Exception uncaught");
     
        TEST( throws )
        {
            throw int(3);
        };
     
        TEST( throws_with )
        {
            FAIL_ON_CATCH("Erreur !!!");
            throw int(4);
        };
     
        TEST( throws_with2 )
        {
            SUCCESS_ON_CATCH("Erreur !!!");
            throw int(5);
        };
    };
    END_SERIE
    Pour le lancer actuellement :
    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
    int main(void)
    {
        LT::UnitTestsManager testManager;
     
        // les deux lignes suivantes disparaîtront dans une future version, il chargera les tests comme des bibliothèques dynamique
        // pour activer/désactiver/échanger des tests sans recompiler.
        testManager.addUnitTestsFile("Assertions", __LT__TestsFileAssertions() );
        testManager.addUnitTestsFile("Exceptions", __LT__TestsFileExceptions() );
     
        testManager.launch();
     
        LT::UnitTestsPrinter printer(testManager); // affiche les résultats
     
        return 0;
    }
    Et voici l'affichage des résultats :
    Begin serie
    Begin test
    Test finished
    Begin test
    Test finished
    Begin test
    Test finished
    Begin test
    Test finished
    Begin test
    Test finished
    Serie finished
    #####################
    ########## BEGIN TEST
    #####################






    =======================
    ====== 1/2 Assertions
    =======================




    ======
    == 1/4 success
    ======
    1/5 [O] success :
    2/5 [O] success_continue :
    3/5 [O] success_on :
    4/5 [X] success_continue_on : ERROR
    5/5 [O] empty :
    ======
    == Resume
    ======
    4/5 [X] success_continue_on : ERROR
    ======
    == X:1 A:0 W:0 on 5 tests
    ======


    ======
    == 2/4 failure
    ======
    1/4 [X] failure : Because
    2/4 [X] failure_continue : Because
    3/4 [X] failure_on : Error
    4/4 [O] failure_continue_on :
    ======
    == Resume
    ======
    1/4 [X] failure : Because
    2/4 [X] failure_continue : Because
    3/4 [X] failure_on : Error
    ======
    == X:3 A:0 W:0 on 4 tests
    ======


    ======
    == 3/4 warning
    ======
    1/4 [W] warning : Because
    2/4 [W] warning_continue : Because
    3/4 [W] warning_on : lu
    4/4 [O] warning_continue_on :
    ======
    == Resume
    ======
    1/4 [W] warning : Because
    2/4 [W] warning_continue : Because
    3/4 [W] warning_on : lu
    ======
    == X:0 A:0 W:3 on 4 tests
    ======


    ======
    == 4/4 alea
    ======
    1/4 [A] alea : Error
    2/4 [A] alea_continue : Error
    3/4 [A] alea_on : Error
    4/4 [A] alea_continue_on : Error
    ======
    == Resume
    ======
    1/4 [A] alea : Error
    2/4 [A] alea_continue : Error
    3/4 [A] alea_on : Error
    4/4 [A] alea_continue_on : Error
    ======
    == X:0 A:4 W:0 on 4 tests
    ======


    =======================
    ====== Resume tests
    =======================
    4/5 of 1/4 [X] success_continue_on/success : ERROR
    1/4 of 2/4 [X] failure/failure : Because
    2/4 of 2/4 [X] failure_continue/failure : Because
    3/4 of 2/4 [X] failure_on/failure : Error
    1/4 of 4/4 [A] alea/alea : Error
    2/4 of 4/4 [A] alea_continue/alea : Error
    3/4 of 4/4 [A] alea_on/alea : Error
    4/4 of 4/4 [A] alea_continue_on/alea : Error
    1/4 of 3/4 [W] warning/warning : Because
    2/4 of 3/4 [W] warning_continue/warning : Because
    3/4 of 3/4 [W] warning_on/warning : lu
    ======================
    ====== X:4 A:4 W:3 on 17 tests
    ======================
    ====== Resume Series
    ======================
    1/4 [X] success X:1 A:0 W:0
    2/4 [X] failure X:3 A:0 W:0
    4/4 [A] alea X:0 A:4 W:0
    3/4 [W] warning X:0 A:0 W:3
    ======================
    ====== X:2 A:1 W:1 on 4 series
    ======================






    =======================
    ====== 2/2 Exceptions
    =======================




    ======
    == 1/2 no_policy
    ======
    1/3 [X] throws : Unknown Exception was caught
    2/3 [X] throws_with : Erreur !!! (Unknown)
    3/3 [O] nothrow :
    ======
    == Resume
    ======
    1/3 [X] throws : Unknown Exception was caught
    2/3 [X] throws_with : Erreur !!! (Unknown)
    ======
    == X:2 A:0 W:0 on 3 tests
    ======


    ======
    == 2/2 policy
    ======
    1/3 [W] throws : Exception uncaught (Unknown)
    2/3 [X] throws_with : Erreur !!! (Unknown)
    3/3 [O] throws_with2 : (Unknown)
    ======
    == Resume
    ======
    2/3 [X] throws_with : Erreur !!! (Unknown)
    1/3 [W] throws : Exception uncaught (Unknown)
    ======
    == X:1 A:0 W:1 on 3 tests
    ======


    =======================
    ====== Resume tests
    =======================
    1/3 of 1/2 [X] throws/no_policy : Unknown Exception was caught
    2/3 of 1/2 [X] throws_with/no_policy : Erreur !!! (Unknown)
    2/3 of 2/2 [X] throws_with/policy : Erreur !!! (Unknown)
    1/3 of 2/2 [W] throws/policy : Exception uncaught (Unknown)
    ======================
    ====== X:3 A:0 W:1 on 6 tests
    ======================
    ====== Resume Series
    ======================
    1/2 [X] no_policy X:2 A:0 W:0
    2/2 [X] policy X:1 A:0 W:1
    ======================
    ====== X:2 A:0 W:0 on 2 series
    ======================






    #####################
    ########## RESUME TESTS
    #####################
    4/5 of 1/4 of 1/2[X] success_continue_on/success/Assertions : ERROR
    1/4 of 2/4 of 1/2[X] failure/failure/Assertions : Because
    2/4 of 2/4 of 1/2[X] failure_continue/failure/Assertions : Because
    3/4 of 2/4 of 1/2[X] failure_on/failure/Assertions : Error
    1/3 of 1/2 of 2/2[X] throws/no_policy/Exceptions : Unknown Exception was caught
    2/3 of 1/2 of 2/2[X] throws_with/no_policy/Exceptions : Erreur !!! (Unknown)
    2/3 of 2/2 of 2/2[X] throws_with/policy/Exceptions : Erreur !!! (Unknown)
    1/4 of 4/4 of 1/2[A] alea/alea/Assertions : Error
    2/4 of 4/4 of 1/2[A] alea_continue/alea/Assertions : Error
    3/4 of 4/4 of 1/2[A] alea_on/alea/Assertions : Error
    4/4 of 4/4 of 1/2[A] alea_continue_on/alea/Assertions : Error
    1/4 of 3/4 of 1/2[W] warning/warning/Assertions : Because
    2/4 of 3/4 of 1/2[W] warning_continue/warning/Assertions : Because
    3/4 of 3/4 of 1/2[W] warning_on/warning/Assertions : lu
    1/3 of 2/2 of 2/2[W] throws/policy/Exceptions : Exception uncaught (Unknown)
    #####################
    ########## X:7 A:4 W:4 on 23 tests
    #####################
    ########## RESUME SERIES
    #####################
    1/4 of 1/2[X] success/Assertions X:1 A:0 W:0
    2/4 of 1/2[X] failure/Assertions X:3 A:0 W:0
    1/2 of 2/2[X] no_policy/Exceptions X:2 A:0 W:0
    2/2 of 2/2[X] policy/Exceptions X:1 A:0 W:1
    4/4 of 1/2[A] alea/Assertions X:0 A:4 W:0
    3/4 of 1/2[W] warning/Assertions X:0 A:0 W:3
    #####################
    ########## X:4 A:1 W:1 on 6 series
    #####################
    ########## RESUME FILES
    #####################
    1/2 [X] Assertions X:2 A:1 W:1 on 4 series
    2/2 [X] Exceptions X:2 A:0 W:0 on 2 series
    #####################
    ########## X:2 A:0 W:0 on 2 FILES
    #####################


    Qu'en pensez-vous pour le moment ?
    Est-ce que cela vous semble intuitif ou trop compliqué ? (Je fais bien exprès de ne pas donner d'informations ^^).

    Est-ce que cela vous semble intéressant ? Ou est-ce une horreur comparé à ce qui existe actuellement ?
    Avez-vous des idées d'évolutions ? (ex. Je pense chronométrer l'exécution de chaque tests).

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par défaut
    Salut

    Quelques remarques rapides après une lecture rapide, à prendre à la légère :
    • Ca ressemble vachement à Google Test
    • Je n'aime pas le principe des macros "Debut"/"Fin". Par exemple à mon avis, END_SERIE n'a pas lieu d'être, il est certainement possible d'implémenter ça uniquement avec TEST_SERIE. D'une manière générale, je pense qu'un certain nombre des fonctionnalités peut être implémenté sans macros .
    • Dommage de ne pas voir des assertions du genre ASSERT_EQUAL, ça aide bien pour débugguer un test pété en formatant un message très clair ("value was y, expected x"). J'ai peut être manqué une subtilité ?
    • Un bon point sur le traitement des exceptions, c'est souvent mis de côté ou mal traité par les frameworks de tests.


    Pour l'évolution, chronométrer n'est pas une mauvaise idée mais à mon avis tu devrais améliorer l'aspect fixtures avec quelque chose de plus souple que BEFORE_FUNCTION et AFTER_FUNCTION.

    C'est quoi le but du projet, c'est un peu pour le fun pour s'exercer ou tu vas vraiment l'exploiter ?

  3. #3
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Bonjour,
    Merci pour ta réponse.


    Citation Envoyé par jblecanard Voir le message
    Ca ressemble vachement à Google Test
    J'aurais plutôt dis que cela ressemble à Boost.

    Je n'aime pas le principe des macros "Debut"/"Fin". Par exemple à mon avis, END_SERIE n'a pas lieu d'être, il est certainement possible d'implémenter ça uniquement avec TEST_SERIE.
    En effet, en trichant un peu, ce devrait être possible.

    D'une manière générale, je pense qu'un certain nombre des fonctionnalités peut être implémenté sans macros .
    Je ne pense pas, même boost utilise des macros.

    Dommage de ne pas voir des assertions du genre ASSERT_EQUAL, ça aide bien pour débugguer un test pété en formatant un message très clair ("value was y, expected x"). J'ai peut être manqué une subtilité ?
    J'ai modifié cela, désormais, on affiche la condition. Mais on a pas la valeur.
    Je ne pense pas que la valeur soit vraiment intéressante, ce qui est intéressant, c'est de savoir pourquoi, quelle est la condition qui a conduit à l'échec.
    Avoir "value was 14, expected 32", cela ne me dit rien.
    Mais "foo() == MAX_PIECE_IN_BOARD", c'est déjà bien plus parlant.

    En effet :
    • si la valeur est une erreur, on peut considéré qu'elle est "indéterminé", donc que ce soit 14, 15, 1442, ou autre, on s'en moque un peu.
    • si la valeur est 14 mais que c'est voulu, le programmeur se doute un peu de sa valeur, c'est juste qu'il a mal compris, donc "foo() == MAX_PIECE_IN_BOARD" l'aidera à comprendre.


    D'autant plus que si j'ai un ASSERT_EQUAL, il me faudrait les mêmes pour >=, <=, ==, >, <, !=.
    Se pose aussi le problème des fonctions qui ont un état interne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if ( foo() == 4 )
          std::string mess = toString( foo() ) + ", expected " + toString( 4 );
    Au premier appel, foo retournera 5 et au second 4 par exemple.


    À moins que tu voies un cas où ce sera en effet très intéressant ?


    Pour l'évolution, chronométrer n'est pas une mauvaise idée mais à mon avis tu devrais améliorer l'aspect fixtures avec quelque chose de plus souple que BEFORE_FUNCTION et AFTER_FUNCTION.
    Je vois mal comment avoir plus souple que BEFORE_FUNCTION et AFTER_FUNCTION, aurais-tu un exemple ?

    Depuis mon dernier message j'ai :

    • mesure du temps des tests ;
    • affichage des ligne, fichier et condition pour mes assertions ;
    • amélioré l'affichage des résultats ;
    • répétions de série de tests avec des valeurs/argument templates différentes.


    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
    21
    22
    CREATE_SERIE_REAPETABLE_D(Exceptions, toto,
                              T i COMMA int j COMMA int k=3,
                              i     COMMA j     COMMA k,
                              template<typename T>
                              )
     
    TEST( nothrow )
        {
            T v = i;
            std::cerr << j << std::endl;
        };
     
     
    END_SERIE_REAPETABLE_D(Exceptions, toto)
     
    SERIE_REAPETABLE2(toto, "tit", 7 COMMA 4, <int>)
     
    int main(void)
    {
        SERIE_REAPETABLE(toto, "tit", 7 COMMA 4, <int>);
        SERIE_REAPETABLE(toto, "tiit", 7 COMMA 3, <int>);
    }
    4
    4
    3


    C'est quoi le but du projet, c'est un peu pour le fun pour s'exercer ou tu vas vraiment l'exploiter ?
    Je me suis vraiment éclaté, donc on ne peut pas dire que je ne l'ai pas fait pour le fun.
    Mais vu où j'en suis arrivé, je pense que je vais l'exploiter.

  4. #4
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Retrait de END_SERIE_REAPETABLE_D

    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
    21
    22
    CREATE_SERIE_REAPETABLE_D(Exceptions, toto,
                              T i COMMA int j COMMA int k,
                              i     COMMA j     COMMA k,
                              template<typename T>,
                              <T>
                              )
    {
     
        TEST( nothrow )
        {
            T v = i;
            std::cerr << j << std::endl;
        };
    }
     
    SERIE_REAPETABLE2(toto, "tit", 7 COMMA 4 COMMA 8, <int>)
     
    int main(void)
    {
        SERIE_REAPETABLE(toto, "tiiit", 7 COMMA 4 COMMA 2, <int>);
        SERIE_REAPETABLE(toto, "tiit", 7 COMMA 3 COMMA 3, <int>);
    }
    Il y a une légère répétition, mais d'un autre côté le gain est énorme, on a des sortes de templates de séries qu'on peut appeler avec des valeurs différentes !

    Retrait de END_REPEATABLE_TEST
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        REPEATABLE_TEST(alea_continue)
        {
            for(auto & i : tab )
                for(auto & j : i )
                    for(auto & k : j )
     
                    {
                        START_REPEATABLE_TEST
     
                        int * i = new int;
                        C_ALEA( (std::size_t)j, "Error"); // Error with the value j
                        delete i;
                    }
        };
    Retrait de END_SERIE
    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
    TEST_SERIE_D(Exceptions, no_policy )
    {
        TEST( throws )
        {
            throw int(1);
        };
     
        TEST( throws_with )
        {
            FAIL_ON_CATCH("Erreur !!!");
            throw int(2);
        };
     
        TEST( nothrow )
        {
     
        };
    }

    Je pense que je vais commencer à écrire une doc dans les prochains jours.

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par défaut
    Citation Envoyé par Neckara Voir le message
    si la valeur est une erreur, on peut considéré qu'elle est "indéterminé", donc que ce soit 14, 15, 1442, ou autre, on s'en moque un peu.
    Citation Envoyé par Neckara Voir le message
    ce qui est intéressant, c'est de savoir pourquoi, quelle est la condition qui a conduit à l'échec.
    Sincèrement, je ne suis pas d'accord avec la première assertion et d'accord avec la deuxième. Pour moi, il faut les deux, ça m'a toujours vachement aidé d'avoir la valeur qui n'allait pas, ça m'a bien souvent dirigé vers l'origine du bug. Si tu attend "15.2", c'est quand même pas la même chose que la valeur en erreur soit "15.1" ou "-13.6e10".

    Citation Envoyé par Neckara Voir le message
    Je vois mal comment avoir plus souple que BEFORE_FUNCTION et AFTER_FUNCTION, aurais-tu un exemple ?
    Déjà un système qui permette de partager les mêmes fixtures sur plusieurs séries de test sans avoir à répéter le code BEFORE/AFTER. J'aime bien ce qui offre un scope déjà peuplé, à la manière de gtest.

    Citation Envoyé par Neckara Voir le message
    Je pense que je vais commencer à écrire une doc dans les prochains jours.
    Si tu veux que les gens s'en servent, c'est indispensable . Et un dépôt de code accessible facilement aussi genre github. Bon courage pour la suite !

  6. #6
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    Lu,

    J'ai survolé les messages sans vraiment regarder mais:

    Citation Envoyé par Neckara Voir le message
    J'ai modifié cela, désormais, on affiche la condition. Mais on a pas la valeur.
    Je ne pense pas que la valeur soit vraiment intéressante, ce qui est intéressant, c'est de savoir pourquoi, quelle est la condition qui a conduit à l'échec.
    Je pense que savoir les valeurs est un début de "pourquoi?".

    Citation Envoyé par Neckara Voir le message
    D'autant plus que si j'ai un ASSERT_EQUAL, il me faudrait les mêmes pour >=, <=, ==, >, <, !=.
    Se pose aussi le problème des fonctions qui ont un état interne
    Boost le fait bien

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #define ASSERT_COMPARE(op, a, b)
    if (![](auto const & x, auto const & y) {
      bool r = (x op y);
      if (!r) { std::cout <<  #a " " #op " " #b << "  with " << x << " " #op " " << y << "\n"; }
      return r;
    }((a), (b))) {
      //...
    }

  7. #7
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    Sincèrement, je ne suis pas d'accord avec la première assertion et d'accord avec la deuxième. Pour moi, il faut les deux, ça m'a toujours vachement aidé d'avoir la valeur qui n'allait pas, ça m'a bien souvent dirigé vers l'origine du bug. Si tu attend "15.2", c'est quand même pas la même chose que la valeur en erreur soit "15.1" ou "-13.6e10".
    Citation Envoyé par jo_link_noir Voir le message
    Boost le fait bien

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #define ASSERT_COMPARE(op, a, b)
    if (![](auto const & x, auto const & y) {
      bool r = (x op y);
      if (!r) { std::cout <<  #a " " #op " " #b << "  with " << x << " " #op " " << y << "\n"; }
      return r;
    }((a), (b))) {
      //...
    }
    Je n'aime pas trop cela.

    Quid si on veut sqrt( foo() ) < value; ?
    Il faut penser à le réécrire foo() < value * value; ce qui n'a pas forcément autant de sens.

    Ou tab[ foo() ] < value ? Comment le réécrire ?
    Sachant que je permet l'ajout d'un message personnalisé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FAIL_ON( i == 1, "Value for i was " + i);
    Au pire, je peux proposer une syntaxe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FAIL_ON( VAR( i ) == 1, "Error"); // Error : (i == 1) with i = 8
    Cela te semble-t-il être un bon compromis ?

    Déjà un système qui permette de partager les mêmes fixtures sur plusieurs séries de test sans avoir à répéter le code BEFORE/AFTER. J'aime bien ce qui offre un scope déjà peuplé, à la manière de gtest.
    Tu as un exemple de syntaxe ?

    Sinon, rien ne t'empêche de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void init(void){}
     
    TEST_SERIE(toto)
    {
          BEFORE_FUNCTION
          {
               init();
          }
     
    }
    Si les fixtures sont très proches, est-ce cohérent d'avoir deux séries distinctes ?

    Tu peux même faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #define FIX \
    i = 5;
     
    TEST_SERIE(toto)
    {
          int i = 5;
     
          BEFORE_FUNCTION
          {
               FIX
          }
     
    }


    Si tu veux que les gens s'en servent, c'est indispensable . Et un dépôt de code accessible facilement aussi genre github. Bon courage pour la suite !
    Merci.

  8. #8
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Juste une preuve de concept :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        int i = 7;
        int j = 5;
        EXPR( VAR(i) + VAR(3 + VAR(2) ) > VAR(j) + 2 )
    (i) + (3 + (2) ) > (j) + 2 with i = 7 with 2 = 2 with 3 + (2) = 5 with j = 5
    Qu'en pensez-vous ?

  9. #9
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Désolé, je me floode moi-même.

    À l'origine, j'ai 4*4 macro, mais je pense qu'elles ne sont pas toutes cohérentes.

    Je pense donc les renommer et en supprimer quelques unes.
    Par quitter, je veux dire quitter le test courant, quand on quitte, on passe au test suivant dans la série.

    QUITTER CONTINUER QUITTER SI CONTINUER SI
    OK SUCCESS(MESS) => inutile (1) SUCCESS_IF(COND, MESS) => inutile (1)
    ERREUR FAIL(MESS) ERROR(MESS) (4) FAIL_IF(COND, MESS)
    ASSERT(!COND, MESS) (2)
    ERROR_IF(COND, MESS) (4)
    EASSERT(!COND, MESS)
    WARNING => inutile (3) WARNING(MESS) => inutile (3) WARNING_IF(COND, MESS)
    WASSERT(!COND, MESS) (3)
    ALEA (5) (5) (5) (5)

    1. Cela reviendrait à changer l'état courant en un état "OK" puis à continuer le test.
      Cela se défend, on pourrait se mettre, au début du test, dans un état d'erreur "par défaut".
      Mais dans les autres cas, cela revient à acquitter une erreur, je ne pense pas que ce soit une bonne chose.
    2. Quitte si l'assertion est fausse.
    3. quitter pour un warning est incohérent et pourrais cacher une erreur, autant continuer. Il faudra aussi que je fasse en sorte de pouvoir accumuler les warning.
    4. Utile si on veut libérer quelques ressources avant de quitter, toutes les erreurs suivantes seront aussi enregistrée (pour les tours de boucles par exemples).
    5. Cet état n'a pas vraiment de sens. Le but était de montrer qu'une erreur s'était produit dans un test non-déterministe.
      Je pense qu'une simple macro SEED(seed) suffit.


    Pour les conditions, j'ai : ASSERT(VAR(i) == 3, "mess").
    Mais on peux avoir des éléments qui ne sont pas présent dans l'expression du test qui peuvent aussi être importants.
    Je pense donc faire en sorte qu'on puisse utiliser VAR en dehors des conditions.

    Pour les textes, j'utilisais un std:.string, je pense que je vais changer pour un std::stringstream pour permettre l'utilisation des opérateurs de flux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ASSERT( VAR(i * j) == 0, (i * j) << " est bien trop grand pour une image !") 
    // 42 est bien trop grand pour une image ! ( (i*j) == 0 with i*j = 42 )

    Je pense que cela va être les dernières petites retouches finales.
    Qu'en pensez-vous ?

  10. #10
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    J'ai à nouveau fini.

    Le problème, c'est que ma classe UnitTest sert à la fois pour enregistrer le test, le jouer puis contenir les résultats du test.
    Donc si je veux exploiter les résultats, il faut que j'aille rechercher ma classe UnitTest.

    Je ne peux pas non plus enregistrer les résultats sous forme structurée.


    Je pense donc me faire une sorte de "dom" qui permettra de récupérer et de sauvegarder des fichiers au format TLV ou XML "simplifié".
    Actuellement, il n'existe pas de bibliothèque mature C++ pour les TLV.
    Je pense aussi y ajouter un système de requête à la XPATH, ça devrait être assez très marrant.

    expr : ensemble_nœud

    ensemble_nœud : / nom_nœud
    ensemble_nœud : nom_nœud
    ensemble_nœud : fonction ( ensemble_nœud )
    ensemble_nœud : ( ensemble_nœud )

    ensemble_nœud : ensemble_nœud / nom_nœud
    ensemble_nœud : ensemble_nœud // nom_nœud
    ensemble_nœud : ensemble_nœud [ condition ]
    ensemble_nœud : condition

    condition : ! ensemble_nœud
    condition : ensemble_nœud == ensemble_nœud
    condition : ensemble_nœud != ensemble_nœud
    condition : ensemble_nœud > ensemble_nœud
    condition : ensemble_nœud < ensemble_nœud
    condition : ensemble_nœud >= ensemble_nœud
    condition : ensemble_nœud <= ensemble_nœud
    condition : ensemble_nœud && ensemble_nœud
    condition : ensemble_nœud || ensemble_nœud


    Je pense déjà qu'avec ça on aura de quoi s'amuser.
    Avec la possibilité d'ajouter ses propres fonctions bien sûr sinon, c'est pas marrant.

Discussions similaires

  1. Choix d'un logiciel pour test unitaire en C++
    Par tiagocerqueira dans le forum C++
    Réponses: 7
    Dernier message: 27/01/2010, 18h44
  2. Tests Unitaires - Production de documents
    Par giviz dans le forum Test
    Réponses: 13
    Dernier message: 07/02/2005, 08h41
  3. Tests unitaires en C#
    Par Bouboubou dans le forum Test
    Réponses: 2
    Dernier message: 01/10/2004, 13h03
  4. [TESTS] Tests unitaires
    Par mathieu dans le forum Test
    Réponses: 4
    Dernier message: 08/01/2004, 12h59

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