2026-06-30 20:45:25 +02:00

4.2 KiB

name, description, user-invocable
name description user-invocable
testcase-common-setup Use when: refactoring tests to eliminate duplication via test fixtures, extracting common setup into SetUp(), converting TEST() to TEST_F() in Google Test. Run this after adding new test cases that duplicate setup code. true

Test Case Common Setup (Google Test)

This skill refactors Google Test suites by extracting duplicate setup code into a shared test fixture with SetUp(). Applying this skill makes tests more maintainable and reduces noise from repeated scaffolding.

When to Use

  • Multiple TEST() cases create the same object or call the same configuration
  • A new test case requires copying setup lines from an existing test
  • Reviewing test code and noticing the same 2+ lines repeated across every test
  • After adding a new test that duplicates setup from existing tests

Procedure

1. Identify Duplicated Setup

Scan all TEST() blocks in the test suite. Look for lines that are identical across every test — typically:

  • Object creation: VendingMachine vm; (or similar SUT construction)
  • Common configuration calls: vm.configureSlot(...)
  • Pre-conditions that apply to all tests

2. Create a Test Fixture

Introduce a fixture class deriving from ::testing::Test:

class <TestSuiteName> : public ::testing::Test {
protected:
  // Shared state goes here — typically the System Under Test
  <Type> <variable>;
};
  • Place it right after the includes, before the first test
  • Declare shared variables as protected members
  • Name the fixture after the test suite (e.g. VendingMachineTest)

3. Extract Shared Setup into SetUp()

Define void SetUp() override inside the fixture with the lines common to all tests:

class <TestSuiteName> : public ::testing::Test {
protected:
  <Type> <variable>;

  void SetUp() override
  {
    // Lines that every test needs — extracted here once
    <sharedSetupLine1>;
    <sharedSetupLine2>;
  }
};

Rules:

  • Only move lines that appear in every test
  • If a line only appears in some tests, leave it in the individual TEST_F() bodies
  • Keep SetUp() focused — it runs before each test, so don't put expensive or test-specific logic there

4. Convert TEST() to TEST_F()

Replace every occurrence:

// Before
TEST(<TestSuiteName>, <TestCaseName>)
{
  <Type> <variable>;          // ← now redundant
  <sharedSetupLine1>;         // ← now redundant (in SetUp)
  ...
}

// After
TEST_F(<TestSuiteName>, <TestCaseName>)
{
  // Only test-specific code remains
  ...
}
  • Remove the redundant object declaration from each test body
  • Remove any lines now handled by SetUp()
  • Remove configuration calls that were duplicates across all tests

5. Verify

Run the test suite to confirm all tests still pass:

./run_tests.sh

All tests must pass before considering the refactor complete.

Example

Before — three tests with duplicated setup:

TEST(VendingMachineTest, unconfigured_choice_dispenses_nothing)
{
  VendingMachine vm;
  EXPECT_EQ(vm.dispense(Choice::Cola), std::nullopt);
}

TEST(VendingMachineTest, configured_slot_dispenses_can)
{
  VendingMachine vm;
  vm.configureSlot(Choice::Cola, Can::Coke);
  EXPECT_EQ(vm.dispense(Choice::Cola), Can::Coke);
}

TEST(VendingMachineTest, multiple_slots_dispense_correctly)
{
  VendingMachine vm;
  vm.configureSlot(Choice::FizzyOrange, Can::Fanta);
  vm.configureSlot(Choice::Cola, Can::Coke);
  EXPECT_EQ(vm.dispense(Choice::FizzyOrange), Can::Fanta);
}

After — fixture with SetUp():

class VendingMachineTest : public ::testing::Test {
protected:
  VendingMachine vm;

  void SetUp() override
  {
    vm.configureSlot(Choice::Cola, Can::Coke);
    vm.configureSlot(Choice::FizzyOrange, Can::Fanta);
  }
};

TEST_F(VendingMachineTest, unconfigured_choice_dispenses_nothing)
{
  EXPECT_EQ(vm.dispense(Choice::Beer), std::nullopt);
}

TEST_F(VendingMachineTest, configured_slot_dispenses_can)
{
  EXPECT_EQ(vm.dispense(Choice::Cola), Can::Coke);
}

TEST_F(VendingMachineTest, multiple_slots_dispense_correctly)
{
  EXPECT_EQ(vm.dispense(Choice::FizzyOrange), Can::Fanta);
}

References