Moodle unit testing through simple test

I’ve used the simpletest PHP unit test framework and as Moodle uses the simpletest, I thought that setting up unit tests and running them would be straightforward. As with a lot of things Moodle, there are various gotchas which are not documented and it was only by searching through the source code that I was able to get them running.

I set up a unit test class and ran it through Site Administration -> Development -> Unit Tests. The first thing that went wrong was it complained that unittestprefix had not been set. A search through the source revealed that this variable refers the prefix you need to use on the test tables in the Moodle database. In my config.php, the setting was

//Unit testing. 
//This refers to the prefix for the test tables in the database
$CFG->unittestprefix = 'testing_';

The next problem was that Moodle couldn’t find my unit tests. It took a bit of digging but I found that I had prefix the name the php file with the unit test with ‘test_’. After that, my tests worked OK.

if (!defined('MOODLE_INTERNAL')) {
   ///  It must be included from a Moodle page
    die('Direct access to this script is forbidden.');    
}

global $DB, $CFG;

class test_block_rollover_clone_test extends UnitTestCase
{
    public function testInitialTesting()
    {
        $this->assertFalse(true);
    }

}

This resulted in the following:

Moodle form validation tips

There are a number of gotchas with Moodle Quick Form and it’s only through trial and error that I’ve discovered how they work.

The first is that when you implement any sort of validation, the form will only return data when the validation passes.

The second is that you don’t call any custom validation directly, you need to check that is_validated() is returning true.

class block_rollover_form extends moodleform
{

    function definition()
    {
        $form = $this->_form;
        //add form definitions here
        $form->addElement('date_selector', 'livedate', get_string('livedate', 'block_rollover'), array(
            'startyear' => 2012,
            'stopyear' => 2020
        ));

        $form->addElement('date_selector', 'archivedate', get_string('archivedate', 'block_rollover'), array(
            'startyear' => 2012,
            'stopyear' => 2020
        ));
        
    }

    /**
     * Custom validation to check that the start date and archive date are in future
     *
     * @param array $data
     * @param array $files
     * @return array
     */
    function validation($data, $files)
    {
        $errors = parent::validation($data, $files);
        $now = time();
        $live_date = $data['livedate'];
        $archive_date = $data['archivedate'];
        if ($live_date <= $now) {
            $errors['livedate'] = 'Please ensure that the start date for the new course is after today';
        }

        if ($archive_date <= $now) {
            $errors['archivedate'] = 'Please ensure that the archive date for the old course is after today';
        }
        return $errors;
    }


    /**
     * This function handles the form submission
     */
    public function handle()
    {
        //Do nothing if submitted or cancelled.
        if (!$this->is_submitted() || $this->is_cancelled()) {
            return;
        }

        //If the validation fails, it will print out the error messages on the form
        //note that $this->get_data() will return empty until the validation passes.
        if (!$this->is_validated()) {
            return;
        }

        //Form has been submitted and it validates, now we can get the data in the form
        $data = $this->get_data();

    }
}