Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python date string testing

In my python based application, user can enter dates in format of dd/mm/yy with date separator variations(like they can use /,- or space as a seperator). Therefore all these are valid dates:

10/02/2009
07 22 2009
09-08-2008
9-9/2008
11/4 2010
 03/07-2009
09-01 2010

Now in order to test it, I need to create a list of such dates, but I am not sure how to auto generate random combinations of these date strings with seperators.

This is what I started doing:

date = ['10', '10', '2010']
seperators = ['/', '-', ' ']
for s in seperators:
    new_date = s.join(date)
like image 518
Prim Avatar asked Aug 26 '26 02:08

Prim


1 Answers

I think the previous answers didn't really help too much. If you choose "day" as a number from 1-31 and "month" as any number from 1-12 in your test data, your productive code MUST raise Exceptions somewhere - 02/31/2013 should not be accepted!

Therefore, you should create random, but valid dates and then create strings from them with arbitrarily chosen format strings. This is what my code does:

import datetime
import time
import random

separators = ["/",",","-"," "]
prefixes = [""," "]

def random_datetime(min_date, max_date):
    since_epoch_min = time.mktime(min_date.timetuple())
    since_epoch_max = time.mktime(max_date.timetuple())
    random_time = random.randint(since_epoch_min, since_epoch_max)
    return datetime.datetime.fromtimestamp(random_time)

def random_date_string_with_random_separators(dt):
    prefix = random.choice(prefixes)
    sep1 = random.choice(separators)
    sep2 = random.choice(separators)

    format_string = "{}%m{}%d{}%Y".format(prefix, sep1, sep2)
    return dt.strftime(format_string)



min_date = datetime.datetime(2012,01,01)
max_date = datetime.datetime(2013,01,01)

for i in range(10):
    print random_date_string_with_random_separators(
                    random_datetime(min_date, max_date)
          )

This should cover all cases (if you take more than ten values).

Nevertheless, I have two remarks:

Don't use random data as test-input

You'll never know if someday your test will fail, maybe you don't catch all possible problems with the data generated. In your case it should be o.k., but generally it's not good practice (if you have another choice). Alternatively, you could create a well-thought set of hard-coded input strings where you cover all corner cases. And if someday your tests fail, you know it's no random effect.

Use well-tested code

For the task you describe, there's a library for that! Use dateutil. They have a fantastic datetime-parser that swallows almost everything you throw at it. Example:

from dateutil import parser

for i in range(10):
    date_string = random_date_string_with_random_separators(
                    random_datetime(min_date, max_date)
          )
    parsed_datetime = parser.parse(date_string)
    print date_string, parsed_datetime.strftime("%m/%d/%Y")

Output:

 01 05,2012 01/05/2012
05 17-2012 05/17/2012
06-07-2012 06/07/2012
10 31,2012 10/31/2012
 10/04,2012 10/04/2012
 11 16,2012 11/16/2012
 03/23 2012 03/23/2012
02-26-2012 02/26/2012
 01,12-2012 01/12/2012
12-21 2012 12/21/2012

Then you can be sure it works. dateutilhas tons of unit tests and "just will work". And the best code you can write is code you don't have to test.

like image 136
Thorsten Kranz Avatar answered Aug 27 '26 16:08

Thorsten Kranz