Using TDD to peek into the future of code

A small change

I had ended the previous post in the series with a WPSchedule_Time_Factory class like this

class WPSchedule_Time_Factory implements WPSchedule_Interface_FactoryInterface {

    protected static $slugsAndClasses = array(
        'now' => 'WPSchedule_Time_Now',
        '8pm' => 'WPSchedule_Time_EightPM',
        '8am' => 'WPSchedule_Time_EightAM'
    );

    protected static $defaultSlug = 'now';
    protected static $optionPostfix = '_schedule_time';

    public static function make( $hook, array $args = null ) {
        if ( ! is_string( $hook ) ) {
            throw new Exception( 'Hook name must be a string' );
        }

        $timeSlug = get_option( $hook . self::$optionPostfix, self::$defaultSlug );
        $timeSlug = self::isLegitSlug( $timeSlug ) ? $timeSlug : self::$defaultSlug;

        $instance = null;

        $slugsAndClasses = self::getSlugsAndClasses();
        $class = $slugsAndClasses[ $timeSlug ];

        return new $class;
    }

    public static function getSlugsAndClasses() {
        return self::$slugsAndClasses;
    }

    public static function isLegitSlug( $timeSlug ) {
        $slugsAndClasses = self::getSlugsAndClasses();

        return is_string( $timeSlug ) && array_key_exists( $timeSlug, $slugsAndClasses );
    }
}

Before moving on to test the WPSchedule_Interval_Factory class I will refactor the code of the class again to remove more knowledge of the class from the code testing (and using) it; in the WPSchedule_Time_Factory class I add a field

protected static defaultClass = 'WPSchedule_Time_Now';

and a method

public static function getDefaultClass(){
    return self::$defaultClass;
}

and this allows me to rewrite the test code to

/**
 * @test
 * it should return Now time if option not set
 */
public function it_should_return_now_time_if_option_not_set() {
    FunctionMocker::replace( 'get_option', false );

    $time = WPSchedule_Time_Factory::make( 'some_hook' );

    $this->assertInstanceOf( WPSchedule_Time_Factory::getDefaultClass(), $time );
} 

freeing the test code from the knowledge of the default class returned.

A bigger thought

Testing the code allows me to get a taste of the future to come: if changing a legit option in my class, like the default value returned, requires me to change my code then the client code using that class will need to do so in the future. Avoiding the need to know a class defaults and inner workings before hand when testing it allows me to write loosely coupled code that’s easier to update (ideally not needing any update) and replace should the need arise.

The code

Updated code is on GitHub tagged post-8.

Probably related

I appreciate your input