web-dev-qa-db-fra.com

GoogleTest: comment passer un test?

Utilisation de Google Test 1.6 (Windows 7, Visual Studio C++). Comment puis-je désactiver un test donné? (aka comment puis-je empêcher un test de courir). Y a-t-il autre chose que je puisse faire en plus de commenter l'ensemble du test?

101
User

Les docs pour Google Test 1.7 suggérez :

"Si vous avez un test cassé que vous ne pouvez pas corriger tout de suite, vous pouvez ajouter le préfixe DISABLED_ à son nom. Cela l'exclura de l'exécution."

Exemples:

// Tests that Foo does Abc.
TEST(FooTest, DISABLED_DoesAbc) { ... }

class DISABLED_BarTest : public ::testing::Test { ... };

// Tests that Bar does Xyz.
TEST_F(DISABLED_BarTest, DoesXyz) { ... }
142
Bill

Vous pouvez également exécuter un sous-ensemble de tests , selon la documentation:

Exécution d'un sous-ensemble des tests

Par défaut, un programme Google Test exécute tous les tests définis par l'utilisateur. Parfois, vous souhaitez exécuter uniquement un sous-ensemble des tests (par exemple, pour le débogage ou la vérification rapide d’une modification). Si vous définissez la variable d'environnement GTEST_FILTER ou l'indicateur --gtest_filter sur une chaîne de filtre, Google Test n'exécutera que les tests dont les noms complets (sous la forme TestCaseName.TestName) correspondent au filtre.

Le format d'un filtre est une liste de motifs génériques séparés par un ':' (appelés modèles positifs), suivis éventuellement d'un '-' et d'une autre liste de modèles séparés par un ':' (appelés modèles négatifs). Un test correspond au filtre si et seulement s'il correspond à l'un des modèles positifs, mais ne correspond à aucun des modèles négatifs.

Un motif peut contenir '*' (correspond à n'importe quelle chaîne) ou '?' (correspond à n'importe quel caractère). Pour plus de commodité, le filtre '* -NegativePatterns' peut également être écrit sous la forme '-NegativePatterns'.

Par exemple:

./foo_test Has no flag, and thus runs all its tests.
./foo_test --gtest_filter=* Also runs everything, due to the single match-everything * value.
./foo_test --gtest_filter=FooTest.* Runs everything in test case FooTest.
./foo_test --gtest_filter=*Null*:*Constructor* Runs any test whose full name contains either "Null" or "Constructor".
./foo_test --gtest_filter=-*DeathTest.* Runs all non-death tests.
./foo_test --gtest_filter=FooTest.*-FooTest.Bar Runs everything in test case FooTest except FooTest.Bar. 

Pas la solution la plus jolie, mais ça marche.

63
Kiril

Voici l'expression pour inclure les tests dont les noms contiennent les chaînes foo1 ou foo2 et exclure les tests dont les noms contiennent les chaînes bar1 ou bar2:

--gtest_filter=*foo1*:*foo2*-*bar1*:*bar2*
16
ashutosh

Je préfère le faire en code:

// Run a specific test only
//testing::GTEST_FLAG(filter) = "MyLibrary.TestReading"; // I'm testing a new feature, run something quickly

// Exclude a specific test
testing::GTEST_FLAG(filter) = "-MyLibrary.TestWriting"; // The writing test is broken, so skip it

Je peux commenter les deux lignes pour exécuter tous les tests, décommenter la première ligne pour tester une fonctionnalité que je suis en train d'étudier/travailler, ou décommenter la deuxième ligne si un test est cassé mais je veux tester tout le reste.
Vous pouvez également tester/exclure une suite de fonctionnalités en utilisant des caractères génériques et en écrivant une liste, "MyLibrary.TestNetwork *" ou "-MyLibrary.TestFileSystem *".

8
pilkch

Vous pouvez maintenant utiliser la macro GTEST_SKIP() pour ignorer conditionnellement un test lors de l'exécution. Par exemple:

TEST(Foo, Bar)
{
    if (blah)
        GTEST_SKIP();

    ...
}

Notez qu'il s'agit d'une très fonctionnalité récente , vous devrez donc peut-être mettre à jour votre bibliothèque GoogleTest pour l'utiliser.

8
Peter Bloomfield

Si plusieurs tests sont nécessaires, ne pas passer

--gtest_filter=-TestName.*:TestName.*TestCase
5
Vijay C

Pour une autre approche, vous pouvez encapsuler vos tests dans une fonction et utiliser des contrôles conditionnels normaux au moment de l'exécution pour les exécuter uniquement si vous le souhaitez.

#include <gtest/gtest.h>

const bool skip_some_test = true;

bool some_test_was_run = false;

void someTest() {
   EXPECT_TRUE(!skip_some_test);
   some_test_was_run = true;
}

TEST(BasicTest, Sanity) {
   EXPECT_EQ(1, 1);
   if(!skip_some_test) {
      someTest();
      EXPECT_TRUE(some_test_was_run);
   }
}

Ceci est utile pour moi, car j'essaie d'exécuter certains tests uniquement lorsqu'un système prend en charge l'IPv6 en double pile.

Techniquement, ce type de pile double ne devrait pas être un test unitaire, car cela dépend du système. Mais je ne peux pas vraiment faire de test d’intégration tant que je n’ai pas testé leur fonctionnement, ce qui garantit qu’il ne signalera pas les échecs si ce n’est pas la faute des codes.

En ce qui concerne le test de celui-ci, j'ai des objets stub qui simulent la prise en charge par un système de la pile double (ou l'absence de) en construisant de fausses sockets.

Le seul inconvénient est que la sortie du test et le nombre de tests vont changer, ce qui peut poser problème avec un élément surveillant le nombre de tests réussis.

Vous pouvez également utiliser ASSERT_ * plutôt que EQUAL_ *. Affirmez à propos du reste du test s'il échoue. Empêche de transférer beaucoup de choses redondantes sur la console.

4
David C. Bishop

J'avais le même besoin de tests conditionnels et j'ai trouvé une bonne solution de contournement. J'ai défini une macro TEST_C qui fonctionne comme une macro TEST_F, mais qui possède un troisième paramètre, qui est une expression booléenne, évaluée à l'exécution dans main.cpp AVANT le démarrage des tests. Les tests qui évaluent false ne sont pas exécutés. La macro est moche, mais elle ressemble à:

#pragma once
extern std::map<std::string, std::function<bool()> >* m_conditionalTests;
#define TEST_C(test_fixture, test_name, test_condition)\
class test_fixture##_##test_name##_ConditionClass\
{\
    public:\
    test_fixture##_##test_name##_ConditionClass()\
    {\
        std::string name = std::string(#test_fixture) + "." + std::string(#test_name);\
        if (m_conditionalTests==NULL) {\
            m_conditionalTests = new std::map<std::string, std::function<bool()> >();\
        }\
        m_conditionalTests->insert(std::make_pair(name, []()\
        {\
            DeviceInfo device = Connection::Instance()->GetDeviceInfo();\
            return test_condition;\
        }));\
    }\
} test_fixture##_##test_name##_ConditionInstance;\
TEST_F(test_fixture, test_name)

De plus, dans votre main.cpp, vous avez besoin de cette boucle pour exclure les tests qui évaluent false:

// identify tests that cannot run on this device
std::string excludeTests;
for (const auto& exclusion : *m_conditionalTests)
{
    bool run = exclusion.second();
    if (!run)
    {
        excludeTests += ":" + exclusion.first;
    }
}

// add the exclusion list to gtest
std::string str = ::testing::GTEST_FLAG(filter);
::testing::GTEST_FLAG(filter) = str + ":-" + excludeTests;

// run all tests
int result = RUN_ALL_TESTS();
4
Jiri Zbranek