2016-07-05 19 views
5

Mit Google-Test möchte ich ein Test-Fixture für die Verwendung in verschiedenen Testfällen angeben. Die Vorrichtung muss Objekte der Klasse TheClass und ihre Datenverwaltungsklasse TheClassData zuordnen und freigeben, wobei die Datenverwaltungsklasse den Namen einer Datendatei erfordert.
Für die verschiedenen Tests sollte der Dateiname variieren.Konstruktorargumente für einen Google-Test angeben Fixture

definiert ich folgende Fixture:

class TheClassTest : public ::testing::Test { 
protected: 
    TheClassTest(std::string filename) : datafile(filename) {} 
    virtual ~TheClassTest() {} 
    virtual void SetUp() { 
    data = new TheClassData(datafile); 
    tc = new TheClass(data); 
    } 
    virtual void TearDown() { 
    delete tc; 
    delete data; 
    } 

    std::string datafile; 
    TheClassData* data; 
    TheClass* tc; 
}; 

nun verschiedene Tests sollte das Gerät mit unterschiedlichen Dateinamen verwenden. Stellen Sie sich dies als Einrichten einer Testumgebung vor.

Die Frage: Wie kann ich den Dateinamen aus einem Test angeben, d. H. Wie man einen nicht standardmäßigen Konstruktor eines Fixtures aufruft?

Ich fand Dinge wie ::testing::TestWithParam<T> und TEST_P, was nicht hilft, da ich nicht einen Test mit unterschiedlichen Werten, sondern verschiedene Tests mit einem Gerät ausführen möchte.

+0

Sie möchten diese Vorrichtung also selbst ausführen? Der standardmäßige Testlauf von Google Test kann Fixtures mit Parametern nicht instanziieren. –

+0

Ich möchte einen Test (wahrscheinlich 'TEST_F') mit dem Gerät ausführen. Die Antwort ist also, dass es nicht möglich ist? Vielen Dank. – Gregor

+0

Ich denke 'TestWithParam ' und 'TEST_P' ist genau das, was Sie brauchen. Suchen Sie in den [Erweiterten Dokumenten] (https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md) nach, wie Sie diese in der Praxis verwenden können. Sie können die zu testende Instanz immer innerhalb des Testfalls instanziieren (ich nehme an, es ist 'TheClass'). –

Antwort

3

Wie von einem anderen Benutzer vorgeschlagen, können Sie nicht erreichen, was Sie wollen durch die Instantiierung eines Fixtures mit einem Nicht-Standard-Konstruktor. gibt es jedoch andere Möglichkeiten. Überlastung einfach die SetUp Funktion und Anruf, dass Version explizit in den Tests:

class TheClassTest : public ::testing::Test { 
protected: 
    TheClassTest() {} 
    virtual ~TheClassTest() {} 
    void SetUp(const std::string &filename) { 
     data = new TheClassData(filename); 
     tc = new TheClass(data); 
    } 
    virtual void TearDown() { 
     delete tc; 
     delete data; 
    } 

    TheClassData* data; 
    TheClass* tc; 
}; 

Jetzt in dem Test einfach diese Überlastung verwendet Dateinamen einzurichten:

TEST_F(TheClassTest, MyTestCaseName) 
{ 
    SetUp("my_filename_for_this_test_case"); 

    ... 
} 

Die parameterlos TearDown automatisch nach oben wird reinigen, wenn der Test ist abgeschlossen.

+0

Großartig. Danke vielmals! – Gregor

+0

Die SetUp-Methode wird weiterhin von gtest aufgerufen, was zu zwei Aufrufen von SetUp führt. In diesem Fall liegt ein Speicherleck vor, da TearDown nur die letzten Zuordnungen löscht. Ich würde SetUp in etwas anderes umbenennen, so dass gtest es nicht anruft. – Andreas

+0

Sorry, ich liege falsch. Da Ihr 'Setup' einen Parameter benötigt, wird dieser nicht von gtest aufgerufen. Ich würde 'SetUp' in etwas anderes umbenennen, da es mit' SetUp() 'verwechselt werden kann, das von gtest aufgerufen wird. – Andreas

0

Verwenden Sie die aktuelle Klasse als Basisklasse für Ihre Armaturen:

class TheClassTestBase : public ::testing::Test { 
protected: 
    TheClassTestBase(std::string filename) : datafile(filename) {} 
    ... 
}; 

Für jeden bestimmten Dateinamen - Verwendung abgeleiteter Aufnahme:

class TheClassTestForFooTxt : public TheClassTestBase { 
protected: 
    TheClassTestForFooTxt() : TheClassTestBase ("foo.txt") {} 
}; 

Dies ist jedoch zusätzlicher Schritt für jeden Satz von Parametern benötigt - So können Sie versuchen, Vorlagen oder Makros zu verwenden, um es mit weniger Aufwand zu erledigen. Wie:

template <typename ClassTestTag> 
struct ClassTestParams 
{ 
    static std::string filename; 
}; 

template<typename ClassTestTag> 
class TheClassTest : public TheClassTestBase { 
protected: 
    TheClassTest() : TheClassTestBase (ClassTestParams<ClassTestTag>::filename) {} 
}; 

Dann - für jeden Satz von Parametern - das tun:

class FooTxtTag {}; 
template <> std::string ClassTestParams<FooTxtTag>::value = "foo.txt"; 
using TheClassTestForFooTxt = TheClassTest<FooTxtTag>; 
TEST_F(TheClassTestForFooTxt, xxxx) {} 

jedoch - in Ihrem speziellen Fall - ich würde auch GoogleTest:type-parameterized-tests versuchen.

+0

Danke. Ich denke, das ist ein bisschen zu viel Aufwand für die Größe meines Problems. – Gregor