web-dev-qa-db-fra.com

Comment lier des cours de test Google avec mes cours?

J'ai entendu dire qu'il était possible d'activer les amis des classes TestCase de google-test dans mes classes, permettant ainsi aux tests d'accéder à mes membres privés/protégés.

Comment y parvenir?

37
pajton

Essayez ceci (directement à partir de Google Test docs ...):

FRIEND_TEST(TestCaseName, TestName);

Par exemple:

// foo.h
#include <gtest/gtest_prod.h>

// Defines FRIEND_TEST.
class Foo {
  ...
 private:
  FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
  int Bar(void* x);
};

// foo_test.cc
...
TEST(FooTest, BarReturnsZeroOnNull) {
  Foo foo;
  EXPECT_EQ(0, foo.Bar(NULL));
  // Uses Foo's private member Bar().
}
39
hobbit

Je sais que c'est vieux mais je cherchais la même réponse aujourd'hui. "gtest_prod.h" introduit simplement une macro simple pour référencer les classes de test.

#define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test

Donc FRIEND_TEST(FooTest, BarReturnsZeroOnNull); est équivalent à:

friend class FooTest_BarReturnsZeroOnNull_Test;

Cela fonctionne car chaque test est sa propre classe, comme mentionné dans la réponse précédente.

25
Ralfizzle

Une bien meilleure stratégie consiste à ne pas autoriser les tests d'amis parmi vos tests unitaires.

Autoriser les tests d'amis à accéder aux membres privés entraînera une base de code difficile à maintenir. Les tests qui échouent chaque fois que les détails de l'implémentation interne d'un composant sont refactorisés ne sont pas ce que vous voulez. Si un effort supplémentaire est mis à la place pour obtenir une conception où les composants peuvent être testés via leur interface publique, vous obtiendrez des tests qui n'ont besoin d'être mis à jour que lorsque l'interface publique d'un composant est mise à jour.

Tests reposant sur gtest/gtest_prod.h doit être considéré comme un signe de mauvaise conception.

6
Martin G

Lorsque votre classe testée et votre classe de test se trouvent dans un espace de noms différent (par exemple, vos tests sont dans l'espace de noms global), vous devrez peut-être déclarer en avant votre classe de test et ajouter votre préfixe d'espace de noms dans FRIEND_TEST:

// foo.h
#include <gtest/gtest_prod.h>

class FooTest_BarReturnsZeroOnNull_Test;

// Defines FRIEND_TEST.
class my_namespace::Foo {
  ...
 private:
  FRIEND_TEST(::FooTest, BarReturnsZeroOnNull);
  int Bar(void* x);
};

// foo_test.cc
using namespace my_namespace;

...
TEST(FooTest, BarReturnsZeroOnNull) {
  Foo foo;
  EXPECT_EQ(0, foo.Bar(NULL));
  // Uses Foo's private member Bar().
}

Je sais que les tests unitaires d'amis (ou la convivialité en C++ en général) et les tests en boîte blanche sont un sujet controversé, mais lorsque vous travaillez sur des algorithmes scientifiques complexes, dont vous devez tester et valider chaque étape, mais que vous ne Je ne veux pas exposer dans des interfaces publiques (ou même protégées), les tests d'amis m'apparaissent comme une solution simple et pragmatique, notamment dans une approche de développement pilotée par les tests. Il est toujours possible de refactoriser le code plus tard (ou de supprimer complètement les tests en boîte blanche) s'il est contraire à sa religion d'utiliser la convivialité ou les tests en boîte blanche.

1
Corentor