Unit Testing X - Creating our Validator Class

Moving validation to a separate class


In the previous article in this series, we created the unit test for our Validator class. In this one, we'll see the Validator class itself.


MODX logo

Validator Class

Now that we have the tests for our Validator class, we need to create a class that will pass the tests.

Here's the code for that class:

<?php

class Validator {

/**
     * Returns true if valid, false if not
     * @param string $name
     * @return bool
     */
    public function validateUsername($name) {
        return (bool) (strlen($name) < 25) &&
            (strlen($name) >= 3);
    }

    /**
     * Returns true if valid, false if not
     * Validates USA phone numbers.
     * May not work with some international numbers.
     * @param string $phone
     * @return bool
     */
    public function validatePhone($phone) {
        $pattern='~^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*' .
        '([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)' .
        '|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*' .
        '(?:[.-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]' .
        '{2})\s*(?:[.-]\s*)?([0-9]{4})(?:\s*' .
        '(?:#|x\.?|ext\.?|extension)\s*(\d+))?$~';

        return (bool) preg_match($pattern, $phone);
    }

    /**
     * Returns true if valid, false if not
     * @param string $email
     * @return bool
     */
    public function validateEmail($email) {

      $result =  preg_match('/^(?!(?:(?:\x22?\x5C[\x00-' .
      '\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){255,})(?!' .
      '(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?' .
      '[^\x5C\x22]\x22?)){65,}@)(?:(?:[\x21\x23-\x27' .
      '\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22' .
      '(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-' .
      '\x7F]|(?:\x5C[\x00-\x7F]))*\x22))(?:\.(?:' .
      '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F' .
      '\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F' .
      '\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))' .
      '*\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)' .
      '?[a-z0-9]+(?:-[a-z0-9]+)*\.){1,126}){1,}(?:' .
      '(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-' .
      '[a-z0-9]+)*)|(?:\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}' .
      '(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\]])' .
      '{7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::' .
      '(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:' .
      '(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)' .
      '|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::' .
      '[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::' .
      '[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2' .
      '[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))' .
      '(?:\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]' .
      '{2})|(?:[1-9]?[0-9]))){3}))]))$/iD', $email);

      /* Alternate test patterns -- faster, but less accurate */
      // $result =  preg_match('/^[^@]+@[a-zA-Z0-9._-]+\.[a-zA-Z]+$/', $email);
      // $result = preg_match('/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/', $email);

        return (bool) $result;
    }
}

The code above is available at GitHub here.

The username validator is the simplest. It simply makes sure the username is at least three characters long and less than 25. In a real application, you might want to lower the maximum length and outlaw certain characters in the username.

The other two validators set a regular expression pattern and check it with preg_match().

All three validators return boolean True if the pattern is valid and false if not. We cast the return values with (bool) to make sure they return the proper values. This is necessary for the two regular expression validators because preg_match() returns 0 or 1 and our test code uses assertEquals which uses strict (===) match to pass.

The cast isn't necessary for the validateUsername() method, but we put it there anyway to make the code clearer. Users of our validator methods can use === true or === false to test the return values, which can prevent some nasty, hard-to-find bugs.

Our User class test is no longer dependent on the validation code. Because we've created an independent test of the Validator class, we no longer need to test the validation code in our user test.


Coming Up

In the next article in this series, we'll modify our user class test to remove the validation tests and make it less dependent on the Validator class with some new stubbing techniques.



For more information on how to use MODX to create a web site, see my web site Bob's Guides, or better yet, buy my book: MODX: The Official Guide.

Looking for high-quality, MODX-friendly hosting? As of May 2016, Bob's Guides is hosted at A2 hosting. (More information in the box below.)



Comments (0)


Please login to comment.

  (Login)