ibooksonline

Copy-Paste-Tweak-Repeat Antipattern

The satisfaction of getting a test to pass encourages you to get back there again with another passing test. The fastest way to the next passing test is Cut-Paste-Tweak-Repeat. Cut-Paste-Tweak-Repeat is not a sustainable practice. It generates a lot of tests quickly from a seed test case, but if refactor is not part of the cycle, a mess follows.

The improved test cases from the Ramble-on Test pattern exhibit the Cut-Paste-Tweak-Repeat symptoms. Numerous tests almost look the same, requiring careful study to see the difference between test cases. The refactored tests minimize the duplication.

t1/tests/HomeAutomation/LightSchedulerTest.cpp
 TEST(LightScheduler, ScheduleWeekEndFridayExcluded)
 {
  LightScheduler_ScheduleTurnOn(lightNumber, WEEKEND, scheduledMinute);
  setTimeTo(FRIDAY, scheduledMinute);
  LightScheduler_WakeUp();
  checkLightState(LIGHT_ID_UNKNOWN, LIGHT_STATE_UNKNOWN);
 }
 
 TEST(LightScheduler, ScheduleWeekEndSaturdayIncluded)
 {
  LightScheduler_ScheduleTurnOn(lightNumber, WEEKEND, scheduledMinute);
  setTimeTo(SATURDAY, scheduledMinute);
  LightScheduler_WakeUp();
  checkLightState(lightNumber, LIGHT_ON);
 }
 
 TEST(LightScheduler, ScheduleWeekEndSundayIncluded)
 {
  LightScheduler_ScheduleTurnOn(lightNumber, WEEKEND, scheduledMinute);
  setTimeTo(SUNDAY, scheduledMinute);
  LightScheduler_WakeUp();
  checkLightState(lightNumber, LIGHT_ON);
 }
 
 TEST(LightScheduler, ScheduleWeekEndMondayExcluded)
 {
  LightScheduler_ScheduleTurnOn(lightNumber, WEEKEND, scheduledMinute);
  setTimeTo(MONDAY, scheduledMinute);
  LightScheduler_WakeUp();
  checkLightState(LIGHT_ID_UNKNOWN, LIGHT_STATE_UNKNOWN);
 }

In the refactored test, we used TEST_GROUP variables, lightNumber and scheduledMinute, and extracted setTimeTo and checkLightState. Using the TEST_GROUP variables helps illuminate that the day of the week is the input being varied between the tests.