Screenplay: Unittest: GTest Fixtures

Predefined Environment for a Number of Tests

#include <gtest/gtest.h>


class PredefinedTestEnvironment : public ::testing::Test
{
protected:
    int initial_state = 666; // C++11!
};

TEST_F(PredefinedTestEnvironment, ParanoidTest)
{
    // don't trust anybody!
    ASSERT_EQ(initial_state, 666);
}

int main(int argc, char** argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

Discussion

  • A fixture is a class (in gtest). Technically,

    • “environment”: protected members

    • TEST_F(): C macro; derives from fixture class

  • initial_state is not a very complex test environment, but you get the point

    • database

    • running co-process

    • a server that’s being talked to

  • Otherwise (untechnically), it’s just a function that operates on an environment

Environment is Isolated Per Test

#include <gtest/gtest.h>


class TheFixture : public ::testing::Test
{
protected:
    int initial_state = 666; // C++11!
};

TEST_F(TheFixture, TestThatModifiesState)
{
    initial_state = 42;
}

TEST_F(TheFixture, ParanoidTest)
{
    // don't trust anybody!
    ASSERT_EQ(initial_state, 666);
}

int main(int argc, char** argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

Discussion

  • See how environment modification is not seen by the other test

More Complex Environment: SetUp(), TearDown()

#include <gtest/gtest.h>


// attention: this is complete nonsense. it only demonstrates SetUp()
// (and TearDown(), for that matter)
class ComplexFixture : public ::testing::Test
{
protected:
    static const int N = 28;
    std::vector<int> first_n;

private: // :-)
    void SetUp() override
    {
        for (int i=0; i<N; i++)
            first_n.push_back(i);
    }
};

TEST_F(ComplexFixture, SomeTest)
{
    ASSERT_EQ(first_n[10], 10);
}

int main(int argc, char** argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

Discussion

  • Fixture is historically defined as being set up and torn down

  • Naive alternative: use constructor and destructor

    • Destructor must not throw!

    • TearDown() exception is a normal failure