Home » Php » mysql – How to test a scheduling program in php

mysql – How to test a scheduling program in php

Posted by: admin July 12, 2020 Leave a comment

Questions:

I have a codeigniter app that schedules events for specific dates and times in a mysql DB, sometimes weeks in advance, with another part that will send email reminders and perform other actions when those dates occur. How would one approach time based testing? Is there a testing suite I could use or read about?

How to&Answers:

This is something that I pondered for quite a while – and then I realized my problem! I was concentrating on time as if it was something I couldn’t control and measure. Time is just like any other calculation that happens in our applications. So, time based testing is easy – we just have to change the way we think about it – and how we construct our application.

First off, the number one thing to do is to separate out the current time generation sequence to a method. This way, we can mock this out later (that is, generate our own method that always returns a predetermined ‘time’ for testing). This can be as simple as something like…

protected function _getCurrentTime()
{
     return time();
}

What is the benefit: in our code, we will call this to get the current time to do calculations. However, in testing, we can always generate the exact same time.

that’s important – we can always generate the exact same time, every time.

Now, I’m not entirely certain how to put this into practice in your particular application, but let me explain a ‘fake’ application – and see if you can adapt it to your specifications.

Ok, first off, we have this method that puts an entry in our database that is a ‘reminder’ for 3 weeks from now.

this is the old code

public function addReminderToDB()
{
    $this->_executeSQL('insert into mytable values (1,2,date_add(now(), interval 3 week))');
}

So, how do we test this? It’s obviously going to be different each time?

Well, let’s break it up. This is our new code…

new code

public function addReminderToDB()
{
    $currentDate = date('m-d-Y h:i:s', $this->_getCurrentTime());
    $sql = "insert into mytable values (1,2,date_add('{$currentDate}', interval 3 week))";
    $this->_executeSQL($sql);
 }

Now, when it comes to testing… you can set up your test db. Next, mock out the method _getCurrentTime() to always return an integer that you know. Then, run the addReminderToDB() (it will use that integer you know). Finally, query the datasource to validate the row inserted has the proper values you’d expect.

I know this isn’t exactly spot on with what you’re asking, but the question is kind of vague too :-/ Best of luck!

Answer:

Do you want to run a unit test to verify your code is working, or test a production environment?

If you want to make sure your scheduled tasks are running in production… The one I created writes a log every time it successfully completes execution.

Then we test it by checking if it has run (eg: test if “daily” tasks have run in the 36 hours). If they haven’t run, then we alert an administrator.

Answer:

Are you using Cron Jobs, PHP live Scripts or JavaScript? There are many ways to achieve a scheduled time application and each way has its own methods of testing.

Evidently, regardless of what solution you are using and as others have mentioned you can simply adjust the time. Change it to 1 minute to confirm your script is carrying out the specified functions correctly.

Once you are confident that your script is working correctly than you can do a final test for a longer time. Also make sure that you are using some sort of log file. This will make life a lot easier down the track when try to spot errors.

Depending what solution you are using, you can also mock test the database as others have also mentioned however this is dependent on how you are achieving your goal.

Hope that helps

Answer:

What we do here is we iterate over all tables, over all columns, and if it’s one of the date/time columns, subtract required time from it:

    // $con is PDO connection
    // $interval can be eg. "5 DAY"
    $tables = $con->query('show tables');
    foreach($tables->fetchAll(PDO::FETCH_COLUMN) as $table) {
            $columns = $con->query(sprintf("show columns from %s where Type in ('date', 'datetime')", $table));
            $fields = array();
            foreach($columns->fetchAll(PDO::FETCH_ASSOC) as $field) {
                    $field = $field['Field'];
                    $fields[] = sprintf('%s = DATE_SUB(%s, INTERVAL %s)', $field, $field, $interval);
            }
            if ($fields) {
                    $q = sprintf('UPDATE %s SET %s', $table, implode(', ', $fields));
                    $con->query($q);
            }
    }

Then continue testing as usual – what was scheduled to happen in 5 days, is scheduled now.